Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is calculating address difference undefined behaviour?

Let's say I perform the following:

void g(int* x)
{
    int y = 0;
    auto diff = uintptr_t(&y) - uintptr_t(x);
}

void f()
{
    int x = 0;
    g(&x);
}

Does diff merely have undefined value, or does the code invoke undefined behaviour? According to the specification, is the code guaranteed to run nicely and compute a value for diff, possibly meaningless, or does it invoke UB? I believe there's something about unrelated variables, but could not pinpoint it.

I'm interested in answers regarding any standard since (including) C++ 11.

Discussion arose from comments in: Print stack in C++

like image 919
Jeffrey Avatar asked May 12 '20 16:05

Jeffrey


People also ask

What is undefined behavior in programming?

In computer programming, undefined behavior (UB) is the result of executing a program whose behavior is prescribed to be unpredictable, in the language specification to which the computer code adheres.

Is unspecified behavior undefined behavior?

Undefined Behavior results in unpredicted behavior of the entire program. But in unspecified behavior, the program makes choice at a particular junction and continue as usual like originally function executes.

What causes undefined behavior c++?

Undefined behavior (often abbreviated UB) is the result of executing code whose behavior is not well defined by the C++ language. In this case, the C++ language doesn't have any rules determining what happens if you use the value of a variable that has not been given a known value.

Why does undefined behavior exist?

Undefined behavior exists mainly to give the compiler freedom to optimize. One thing it allows the compiler to do, for example, is to operate under the assumption that certain things can't happen (without having to first prove that they can't happen, which would often be very difficult or impossible).


2 Answers

To quote the C++11 standard draft. On the subject of converting a pointer to an integer

[expr.reinterpret.cast]

5 A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined.

Since uintptr_t must be defined for the your code to compile, then there exists an integer type on the target machine capable of being the target of the pointer-to-integer conversion. The mapping is implementation defined, but most importantly the result is not indeterminate. This means you obtain some valid integer for both conversions.

So the subtraction is not undefined behavior. But the result is implementation defined.

like image 181
StoryTeller - Unslander Monica Avatar answered Sep 22 '22 23:09

StoryTeller - Unslander Monica


Converting pointer to integer of sufficient size is well defined, subtracting unsigned integer from another is well defined regardless of their value. There is no undefined behaviour here.

But also, standard doesn't guarantee any particular value for the converted integers, and therefore neither for the result of their subtraction.

like image 44
eerorika Avatar answered Sep 21 '22 23:09

eerorika