最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Which value category does x have in `((struct s*)0)->x? - Stack Overflow

programmeradmin5浏览0评论

Consider the following code:

struct s
{
    int x;
    int y[sizeof((struct s*)0)->x];
};

When compiled as C++ (26), this code seems to be valid with GCC (g++ -std=c++26 -pedantic -Wall -Wextra does not complain), though it's invalid with Clang, which produces:

error: member access into incomplete type 'struct s'

demo

Assuming GCC is correct, this may imply that in C++ the result of the -> operator is not always an lvalue. Which value category does x have in ((struct s*)0)->x?

I've already consulted expr.ref and it seems that the case above falls into 7.2. Does it follow that x is an xvalue?

When compiled as C++, does this code lead to undefined behavior?

Consider the following code:

struct s
{
    int x;
    int y[sizeof((struct s*)0)->x];
};

When compiled as C++ (26), this code seems to be valid with GCC (g++ -std=c++26 -pedantic -Wall -Wextra does not complain), though it's invalid with Clang, which produces:

error: member access into incomplete type 'struct s'

demo

Assuming GCC is correct, this may imply that in C++ the result of the -> operator is not always an lvalue. Which value category does x have in ((struct s*)0)->x?

I've already consulted expr.ref and it seems that the case above falls into 7.2. Does it follow that x is an xvalue?

When compiled as C++, does this code lead to undefined behavior?

Share Improve this question edited Mar 27 at 12:12 pmor asked Mar 27 at 9:13 pmorpmor 6,4984 gold badges24 silver badges49 bronze badges 9
  • Clang rejects it for me. Maybe yours is treating this as a C file because you're using clang instead of clang++? – HolyBlackCat Commented Mar 27 at 9:15
  • GCC accepts it though gcc.godbolt./z/WEK8f1Mdj The question should be edited to mention the compiler divergence, ideally also including the error message from Clang. – cigien Commented Mar 27 at 9:25
  • Not an answer to the question, but declval en.cppreference/w/cpp/utility/declval is the better way to get an object for such tests. – gerum Commented Mar 27 at 9:33
  • 2 also, title asks for value category of x, but I think you ask for the value category of the whole (struct s*)0)->x – 463035818_is_not_an_ai Commented Mar 27 at 9:48
  • 1 In the case above an lvalue does not designate an object when it is evaluated sizeof operand is not evaluated (here) (C23 6.5.4.5p2) – Language Lawyer Commented Mar 27 at 9:49
 |  Show 4 more comments

1 Answer 1

Reset to default 7

In C++ *p is always an lvalue for pointers. E1->E2 is treated as (*(E1)).E2, so we are in expr.ref 7.2, and E1 is an lvalue so the whole expression is an lvalue. In C, the analysis is simpler, -> access is always an lvalue.

In both C1 and C++, sizeof expression does not evaluate expression, it just determines the size of the static type of that expression, which doesn't involve the value category of the expression.

Whether this is well formed is hard to say.

In C++ -> member access requires the pointer be to a complete type, unless the access is within the definition of the class [expr.ref#5]. It also requires the rhs to name a member of the class.

The C standard does not require the lhs to be a pointer to a complete type, but, like C++ it does require the rhs to name a member of that struct type.

I don't know if you can ever name a member of an incomplete type. Certainly there are occasions where you can't, because the compiler has no idea what names there are.

In either case, the behaviour is not undefined. Either the program is ill-formed, because x does not name a member of s (because it is incomplete) or y is an int [sizeof int]

  1. Unless the expression designates a VLA
发布评论

评论列表(0)

  1. 暂无评论