2

Since de-referencing nullptr (NULL) is an undefined behavior both in C and C++, I am wondering if expression &(*ptr) is a valid one if ptr is nullptr (NULL).

If it is also an undefined behavior, how does OFFSETOF macro in the linked answer work?

I always thought that ptr->field is a shorthand for (*ptr).field

I think the answer to my question is similar in C and C++.

Community
  • 1
  • 1
TruLa
  • 825
  • 7
  • 17
  • 3
    C11 draft standard n1570: *6.5.3.2 Address and indirection operators 3 The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand 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.* – EOF Jul 27 '16 at 14:13
  • I marked this as a duplicate, but be sure to read the discussion under the C++ answer, as well as [this discussion](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232), as this is not quite so explicit in the C++ standard. – TartanLlama Jul 27 '16 at 14:17
  • 2
    I doubt this is duplicate as OP asks "if dereferencing `nullptr` is UB how offesetof works" – Slava Jul 27 '16 at 14:22
  • Thank you @TartanLlama. I read that topic and will read it again. It was just not clear what question was asked and was the correct answer to that question. It looks more like discussion :-) – TruLa Jul 27 '16 at 14:22
  • 1
    @TartanLlama Since I can't find an equivalent exemption for using `&*NULL` in c++, I suspect this may be one of the points where the two languages diverge. The supposed duplicate can only stand if the `c`-tag is removed. – EOF Jul 27 '16 at 14:26
  • @EOF I'm not sure what you mean; that question has answers addressing C and C++. – TartanLlama Jul 27 '16 at 14:29
  • The dupe is wrong.... Perhaps http://stackoverflow.com/q/7346634/560648? Depends on the language though. I wish the OP would bloomin' pick one. – Lightness Races in Orbit Jul 27 '16 at 14:31
  • @TartanLlama: If you read my first comment here, you'll notice that **there is no `NULL`-dereference** if the code is treated as C. Therefore, answers explaining undefinedness of `NULL`-dereference are not suitable as duplicates. – EOF Jul 27 '16 at 14:31
  • @EOF Ah yes, my mistake, ignore my silliness. – TartanLlama Jul 27 '16 at 14:33
  • @RaymondChen: Nope, that's not right either. – Lightness Races in Orbit Jul 27 '16 at 14:37
  • @LightnessRacesinOrbit The problem is that OP asked four questions. OP should pick one question so people can give the answer to it. – Raymond Chen Jul 27 '16 at 14:38
  • @RaymondChen: And at least one of them, as far as I can tell, differs between C and C++, in contradiction to the OP's assertion that the answers would be similar for the two languages. – EOF Jul 27 '16 at 14:39
  • I am not sure why the question was marked as duplicate to the [question](http://stackoverflow.com/questions/9383684/is-there-a-platform-or-situation-where-dereferencing-but-not-using-a-null-poin)? I am wondering if my example is an undefined behavior (and how `offsetof` works if it is). The question above already **gives** an example of undefined behavior and is about the platform. These two questions are completely different. I think I am very specific in mine. How can I reformulate it? – TruLa Jul 27 '16 at 14:49
  • @Trula I think answer to your question is "implementation of standard library does not have to be valid C or C++ code and discussing if implementation itself there is standard complaint is useless". – Slava Jul 27 '16 at 14:56
  • 1
    The identified duplicate does not answer this question. – Peter Jul 27 '16 at 14:58
  • The C standards, since the 1989 ANSI standard all specify that `&*ptr` has well defined behaviour, since result (in such expression) effectively discards both the `&` and the `*`. Not sure, offhand, what the C++ standards have to say. – Peter Jul 27 '16 at 15:06

2 Answers2

4

TL;DR &(*(char*)0) is well defined.

The C++ standard doesn't say that indirection of null pointer by itself has UB. Current standard draft, [expr.unary.op]

  1. The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T”, the type of the result is “T”. [snip]

  2. The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. [snip]

There is no UB unless the lvalue of the indirection expression is converted to an rvalue.


The C standard is much more explicit. C11 standard draft §6.5.3.2

  1. The unary & operator yields the address of its operand. If the operand has type "type", the result has type "pointer to type". If the operand 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. Otherwise, the result is a pointer to the object or function designated by its operand.
Community
  • 1
  • 1
eerorika
  • 181,943
  • 10
  • 144
  • 256
1

If it is also an undefined behavior, how does offsetof work?

Prefer using the standard offsetof macro. Home-grown versions result in compiler warnings. Moreover:

offsetof is required to work as specified above, even if unary operator& is overloaded for any of the types involved. This cannot be implemented in standard C++ and requires compiler support.

offsetof is a built-in function in gcc.

Maxim Egorushkin
  • 119,842
  • 14
  • 147
  • 239
  • 1
    OP is referring to the macro from the link: #define OFFSETOF(type, field) ((unsigned long) &(((type *) 0)->field)) – Franko Leon Tokalić Jul 27 '16 at 14:38
  • @Byteventurer No reason to use a home-grown `offsetoff`, it results in compiler warnings. Use the standard [`offsetof`](http://en.cppreference.com/w/cpp/types/offsetof). – Maxim Egorushkin Jul 27 '16 at 14:40
  • 1
    I am not propagating the use of the macro, I am explaining what the OP is referring to when asking the question... – Franko Leon Tokalić Jul 27 '16 at 14:41
  • @Byteventurer I think the OP is confusing `offsetof` with `OFFSETOF`. `offsetof` is an identifier reserved for the implementation, whereas `OFFSETOF` could be anything. – Maxim Egorushkin Jul 27 '16 at 14:45
  • 1
    Perhaps he is. Still, the question was about &(*p) where p is a null pointer, not about offsetof itself, and the offsetof macro he linked to did just that. Before the edit, you missed the point of the question IMO. – Franko Leon Tokalić Jul 27 '16 at 14:48
  • 1
    @MaximEgorushkin, I am aware that `offsetof` and `OFFSETOF` are different. Nevertheless, the question was not about which one to use. `OFFSETOF` was just a simple example with `64` upvotes and marked as an accepted answer. I can give another [example](http://lxr.free-electrons.com/source/include/linux/stddef.h) if that would be more convenient ;-) – TruLa Jul 27 '16 at 14:58