当前位置: 动力学知识库 > 问答 > 编程问答 >

structure tag in C vs C++

问题描述:

I wrote following simple program & compiled it on gcc compiler

#include <stdio.h>

typedef int i;

void foo()

{

struct i {i i;} i;

i.i = 3;

printf("%i\n", i.i);

}

int main() { foo(); }

It compiles & runs fine in C.(See live demo here) But it fails in compilation in C++. C++ compiler gives following error messages.

prog.cc: In function 'void foo()':

prog.cc:5:17: error: field 'i' has incomplete type 'foo()::i'

struct i {i i;} i;

^

prog.cc:5:12: note: definition of 'struct foo()::i' is not complete until the closing brace

struct i {i i;} i;

See live demo here

I couldn't find rules regarding this in C & C++ standards. Why it compiles fine in C but not in C++ ? What does the standard says about this ? I very well know that C & C++ are different languages having different rules but I am curious to know about exact rules.

网友答案:

The difference between C and C++ is the following. In C the data member i is considered as having type int because if you wanted that it had type struct i then you have to write struct i i specifying the keyword struct before i.

Structure tags are in their own namespace compared with the namespace of other variables.

According to 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:

— label names (disambiguated by the syntax of the label declaration and use);

the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct, union, or enum);

— 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).

As for C++ then inside the structure definition the name of the structure hides the name of the typedef and the compiler issues the error. In C++ there is separate class scope.

For example in C++ (3.4 Name lookup) there is written

3 The injected-class-name of a class (Clause 9) is also considered to be a member of that class for the purposes of name hiding and lookup.

and (3.4.1 Unqualified name lookup)

7 A name used in the definition of a class X outside of a member function body or nested class definition29 shall be declared in one of the following ways: — before its use in class X or be a member of a base class of X (10.2), or ...

Thus the injected name of the class hides the typedef name within the class definition.

Take into account that outside the class definition the name of the class can be hidden by the same name of an object. Thus if you want to declare an object of the class in that scope you have to use its elaborated name like

int i;

struct i {};

//...

struct i obj;
分享给朋友:
您可能感兴趣的文章:
随机阅读: