admin管理员组文章数量:1402806
Where the C++ standard allows an identifier with name space of a structure (a "non-ordinary" identifier in C) in a primary expression?
Consider the following code (which is a valid C++, but an invalid C):
struct s
{
int x;
int y[sizeof x];
};
Here the sizeof
is applied to structure member x
while declaring the structure itself. This is allowed in C++ (and not in C) because:
- In C++ the
x
has class (and a struct is a class) scope. Therefore, as I understand,sizeof
will searchx
in the class scope first. - C++ seems to allow an identifier with name space of a structure (a "non-ordinary" identifier in C) in a primary expression (which is an operand of the
sizeof
).
To compare with C: C23 (n3299.pdf, 6.5.2p2) has the following constraint (emphasis added):
The identifier in an identifier primary expression shall have a visible declaration as an ordinary identifier that declares an object or a function.
This constraint invalidates the code above (being compiled as C code), because x
is (at least) a non-ordinary identifier.
How does C++ treat / classify identifier x
(e.g. as an identifier with name space struct s
)?
Where does the C++ standard allow an identifier with name space of a structure in a primary expression?
Where the C++ standard allows an identifier with name space of a structure (a "non-ordinary" identifier in C) in a primary expression?
Consider the following code (which is a valid C++, but an invalid C):
struct s
{
int x;
int y[sizeof x];
};
Here the sizeof
is applied to structure member x
while declaring the structure itself. This is allowed in C++ (and not in C) because:
- In C++ the
x
has class (and a struct is a class) scope. Therefore, as I understand,sizeof
will searchx
in the class scope first. - C++ seems to allow an identifier with name space of a structure (a "non-ordinary" identifier in C) in a primary expression (which is an operand of the
sizeof
).
To compare with C: C23 (n3299.pdf, 6.5.2p2) has the following constraint (emphasis added):
The identifier in an identifier primary expression shall have a visible declaration as an ordinary identifier that declares an object or a function.
This constraint invalidates the code above (being compiled as C code), because x
is (at least) a non-ordinary identifier.
How does C++ treat / classify identifier x
(e.g. as an identifier with name space struct s
)?
Where does the C++ standard allow an identifier with name space of a structure in a primary expression?
Share Improve this question edited Mar 25 at 15:03 pmor asked Mar 21 at 15:16 pmorpmor 6,4984 gold badges24 silver badges49 bronze badges2 Answers
Reset to default 3In C opposite to C++ there is no notion of the scope of a structure. There is used the notion of name spaces to distinguish identifiers. In C to refer to an identifier (member of a structure) in a name space of a structure you need to use operators . or -> to access the member. Only in this case the compiler determines that the identifier belongs to the structure name space. From the C Standard (6.2.3 Name spaces of identifiers):
1 If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:
//...
— the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the . or -> operator);
— all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).
For example in C you may write
struct A
{
int x;
} a;
struct B
{
int y[sizeof a.x ]
};
Or without creating an object of the structure struct A
you might write
struct A
{
int x;
};
struct B
{
int y[sizeof( ( (struct A * )0)->x)]
};
So in your code example the compiler issues an error because it searches for an ordinary identifier x
instead of referencing to the data member x
of the structure.
In C++ an identifier (member of a class) is visible inside a class declaration after its point of declaration and belongs to the class scope. From the C++20 Standard (6.4.2 Point of declaration):
6 After the point of declaration of a class member, the member name can be looked up in the scope of its class.
And according to the unqualified name lookup the search of the name x
of your structure s
starts in the scope where the name is used that is in the class scope.
It is similar to use tag names of structures in C to declare an object of a structure type like
struct a
{
int a;
};
struct a a;
In C++ you may write
struct a
{
int a;
};
a a;
If in a C program you will write an object definition as shown above in a C++ program
struct a
{
int a;
};
a a;
then again the compiler will search for an ordinary identifier a
and as result will issue an error because there is no declaration of such an ordinary identifier.
To make the code to compile in C you need to introduce an ordinary identifier a
by means of a typedef declaration like for example
typedef struct a a;
struct a
{
int a;
};
a a;
Pay attention to that the sizeof
operator belongs to unary operators.
[expr.prim.id.general]/4:
An id-expression that denotes a non-static data member or implicit object member function of a class can only be used:
- as part of a class member access (after any implicit transformation (see above)) in which the object expression refers to the member's class or a class derived from that class, or
- to form a pointer to member ([expr.unary.op]), or
- if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
The operand of sizeof
is an unevaluated operand and thus matches the third bullet.
本文标签:
版权声明:本文标题:scope - Where does the C++ standard allow an identifier with name space of a structure in a primary expression? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744343881a2601642.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论