In following code, I have declared a structure member variable as a same name of structure name.
struct st
{
int st;
};
int main()
{
struct st t;
t.st = 7;
return 0;
}
I wonder, it's working fine on GCC compiler and doesn't give a conflict error.
So,
How does the compiler know structure name and variable name?
What mechanism compiler internally use?
Yes, it's valid. The struct tag and the struct members are in different namespace.
C11, 6.2.3 Name spaces of identifiers:
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).
The name of the structure type is struct st. Not just st, so there's no conflict at all.
Related
I'm trying to understand this answer - typedef struct vs struct definitions [duplicate]:
(Line 3): ["] In the first line you are defining the identifier S within the struct name space (not in the C++ sense). [."]
It seems like for struct X {...};, the {...} is like an adjective for X, and X {...} is thrown into something called struct-namespace, how many struct-namespace are there in a program? Is there only one specified by struct?
It seems like in C/C++ struct and class are almost the same? So in C++ struct and class are both in class-namespace?
From the C99 standard draft
6.2.3
6.2.3 Name spaces of identifiers
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 namespaces
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
,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).
In other words, if you have struct S, then S is in the struct namespace, whereas if you have int S as well, then it's in the namespace of ordinary identifiers.
This is not the case for C++
1 (for C): there is one namespace for all structure tags. You can have as many different tags as you want, even if the same name is used in other namespaces.
Each structure on its own is its own namespace (there are "infinite" struct namespaces).
// You can have
struct foo { int var; }
struct bar { double var; }
struct baz { int var; }
struct qux { int var; }
// with no conflict between all the `var`
I'm reading the N1570 Standard and have a problem to understand the wording of the name space definition. Here is it:
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).
32) There is only one name space for tags even though three are possible.
Here they are talking about in case of more than 1 declaration of particular identifiers is visible. Now words something like "To access an identifier one shall specify its namespace" or "To access an identifier in a specific namespace...".
Let me show an example first (this is strictly for understanding purpose, dont write code like this, ever)
#include <stdio.h>
int main(void)
{
int here = 0; //.......................ordinary identifier
struct here { //.......................structure tag
int here; //.......................member of a structure
} there;
here: //......... a label name
here++;
printf("Inside here\n");
there.here = here; //...........no conflict, both are in separate namespace
if (here > 2) {
return 0;
}
else
goto here; //......... a label name
printf("Hello, world!\n"); // control does not reach here..intentionally :)
return 0;
}
You see usage of identifier here. They belong to separate namespace(s) according to the rule, hence this program is fine.
However, say, for example, you change the structure variable name, from there to here, and you'll see a conflict, as then, there would be two separate declaration of same identifier (ordinary identifier) in the same namespace.
As discussed in this question, GCC defines nonstandard unary operator && to take the address of a label.
Why does it define a new operator, instead of using the existing semantics of the & operator, and/or the semantics of functions (where foo and &foo both yield the address of the function foo())?
Label names do not interfere with other identifiers, because they are only used in gotos. A variable and a label can have the same name, and in standard C and C++ it's always clear from the context what is meant. So this is perfectly valid:
name:
int name;
name = 4; // refers to the variable
goto name; // refers to the label
The distinction between & and && is thus needed so the compiler knows what kind of name to expect:
&name; // refers to the variable
&&name; // refers to the label
GCC added this extension to be used in initializing a static array that will serve as a jump table:
static void *array[] = { &&foo, &&bar, &&hack };
Where foo, bar and hack are labels. Then a label can be selected with indexing, like this:
goto *array[i];
Standard says that
C11: 6.2.1 Scopes of identifiers (p1):
An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.
Further it says in section 6.2.3:
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).
This means that an object and a label can be denoted by same identifier. At this point, to let the compiler know that the address of foo is the address of a label, not the address of an object foo (if exists), GCC defined && operator for address of label.
In the library FreeImagePlus, in FreeImage.h, there is a funny #define which seems to create a typedef and an enum with the same name:
#define FI_ENUM(x) typedef int x; enum x
This is expanded by the preprocessor to code like:
typedef int FREE_IMAGE_FILTER;
enum FREE_IMAGE_FILTER {
FILTER_BOX = 0,
FILTER_BICUBIC = 1,
[...]
What does this do? Is it even legal to have a typedef and an enum with the same name?
And isn't an enum compatible to int anyway? Why does FreeImage do this?
Names of structures, unions and enumerations lives in their own namespace. That's why you can declare a struct/union/enum variable with the same name as the actual struct/union/enum.
And it's not the name of the complete enum (e.g. for enum X I mean the X) that has to be compatible with an integer, it's the names inside the enumeration.
Quoting C99 N1256 draft 6.2.1 "Scopes of identifiers":
An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.
which means that in:
typedef int id;
id is an identifier.
And from 6.2.3 "Name spaces of identifiers":
BEGIN QUOTE
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, 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).
END QUOTE
So in:
typedef int id;
enum id {ID0};
the first id is an ordinary identifier
the second is a tag identifier
an both can coexist pacifically.
On the other hand, we could not do something like:
typedef int id;
int id;
because both would be ordinary identifiers.
I've read in SO about different namespaces in C where the type are defined, e.g. there is a namespace for Structs and Unions and a namespace for typedefs.
Is namespace the exact name for this? How many namespaces exist in C?
see 6.2.3
from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
6.2.3 Name spaces of identifiers
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 themember via the . or -> operator);
— all other identifiers, called ordinary identifiers (declared in ordinary
declarators or as enumeration constants).
I am not sure if "namespace" is the right word here, but I think I know what you mean.
You can do
union name1 { int i; char c; };
struct name2 { int i; char c; };
enum name3 { A, B, C };
typedef int name4;
int name5;
Here name1, name2 and name3 are in distinct "namespaces" (I'll keep that word for now), as they don't collide with each other.
This implies that using them requires to prefix their use with the respective keyword:
struct name1 var; // valid
name1 var; // invalid
On the other hand, name4 and name5 live in the global "namespace" and collide. So after having typedef int name4;, you cannot define a variable with that name name4.
BTW: The labels as well define their own namespace.