tags:

views:

526

answers:

4
int* p = 0;
int* q = &*p;

Is this undefined behavior or not? I browsed some related questions, but this specific aspect didn't show up.

+3  A: 

Yes that would be undefined behavior, but your compiler might optimize the &* out.

Why it its undefined, is that you are attempting to access memory outside your addressable space.

Daniel A. White
It is undefined in all cases.
avakar
If compiler optimize it out it is some behaviour. Undefined behaviour means that anything can happen - including flying elephants and nothing.
Maciej Piechotka
Undefined behavior means that *according to the spec*, behavior is not defined. Of course, that doesn't preclude that the construct has still some well-defined behavior on other levels.
Johannes Schaub - litb
A: 

Yes, dereferencing the null pointer is undefined behavior. Integer constant 0 in a pointer context is the null pointer. That's it.

Now, if your second line was int *q = p; that would be a simple pointer assignment. If the compiler removes the &* and reduces the dereference to an assignment, you're OK.

mpez0
But it's still undefined. Just because a particular version of a particular compiler with a particular optimization level handles this doesn't mean "you're OK" - because it's undefined, it could stop working in the next release of the compiler, if the optimization level changes (or in months ending with 'R').
David Gelhar
A: 

IMHO, As far as the two code lines are concerned, there isn't any access outside the address space. The second statement is simply taking the address of (*p) which would be 'p' again and hence it will store '0'. But the location is never accessed.

Salil
+37  A: 

The answer to this question is: it depends which language standard you are following :-).

In C90 and C++, this is not valid because you perform indirection on the null pointer (by doing *p), and doing so results in undefined behavior.

However, in C99, this is valid, well-formed, and well-defined. In C99, if the operand of the unary-& was obtained as the result of applying the unary-* or by performing subscripting ([]), then neither the & nor the * or [] is applied. For example:

int* p = 0;
int* q = &*p; // In C99, this is equivalent to int* q = p;

Likewise,

int* p = 0;
int* q = &p[0]; // In C99, this is equivalent to int* q = p + 0;

From C99 §6.5.3.2/3:

If the operand [of the unary & operator] is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.

Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator.

(and its footnote, #84):

Thus, &*E is equivalent to E (even if E is a null pointer)

James McNellis
+1. What i was going to add as a comment to another answer in a hurry, until i saw this answer :)
Johannes Schaub - litb
I'll also note that it may not be the intent in C++ that performing indirection on a null pointer results in undefined behavior (per [CWG defect 232](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232)). However, the proposed resolution to that defect was _not_ incorporated into the C++0x final committee draft, so it's unlikely to be fixed before the next C++ standard is published.
James McNellis
Martin York
@Martin well we have proven you in another answer somewhere around last year that your interpretation of what "derereference" means is wrong. Applying unary `*` to a pointer dereferences, whether or not the lvalue to rvalue conversion is done is irrelevant. Edit: Please see the comment thread of this answer: http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by-the/988220#988220
Johannes Schaub - litb
In particular notice the wording of `3.8/5` which says "Such a pointer may be dereferenced but the resulting lvalue may only be used in limited ways, as described below." and the various notes that make clear that "dereference" applies to transforming an address to an lvalue. The other action, transforming an lvalue to an rvalue, is not called dereference, but it's called lvalue-to-rvalue conversion or simply "accessing the stored value" (as in 3.10/15) etc.
Johannes Schaub - litb