I recently found this code:
struct foo { int foo; } foo;
And I compiled this snippet (with an empty main()
function of course!), and it compiled without a warning. Why is this legal?
CodePudding user response:
The compiler can tell them apart by the context in which they appear. C 2018 6.2.3, “Name spaces of identifiers,” says:
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 any of the keywords
struct
,union
, orenum
);— 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).
CodePudding user response:
Names in C used to be in namespaces.
In your example, the name foo appears in the struct, struct field, and global namespaces.
This duplicate situation was allowed probably because it takes extra computation to find collisions between those namespaces, and computation used to be very expensive.
Ever since, C maintains backwards compatibility because that’s what C does.