understanding C namespaces
Quoting from here,
In C, there are two different namespaces of types: a namespace of struct/union/enum tag names and a namespace of typedef names.
name.c
$ cat name.c
#include<stdio.h>
typedef long long long2;
int long2 () {
return 4;
}
int main() {
printf("hello, world!");
return 0;
}
$ gcc name.c -o name
name.c:4开发者_开发技巧: error: 'long2' redeclared as different kind of symbol
name.c:3: error: previous declaration of 'long2' was here
$
name2.c
$ cat name2.c
#include<stdio.h>
int four() {
return 4;
}
struct dummy {
int member;
};
int main() {
struct dummy four;
}
$ gcc name2.c -o name2
$
I am trying to understand C namespace conflicts.
In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is
&four
supposed to be resolved?
C has four different name spaces for identifiers:
- Label names (the
goto
type). - Tags (names of structures, unions and enumerations).
- Members of structures and unions (these have a separate namespace per structure/union).
- All other identifiers (function names, object names, type(def) names, enumeration constants, etc).
See also C99 6.2.3.
So your two question can be answered as:
- Yes, function names and typedef names share the same name space.
- No conflict, because the compiler will use scope rules (for function or object names). The identifier in main is said to shadow the global function name, something your compiler will warn you about if you set the warning levels high enough.
But the crucial point on your examples isn't about namespace, but the scope of the names.
In name.c, both long2
are "ordinary identifiers" (share the same name space), and both of them are defined in the same scope, so there is a conflict. (C99 §6.7/3)
If name2.c, the local variable four
is in a scope deeper than the function four
, so the variable hides the function four
(C99 §6.2.1/4).
Your 2nd example does not show "no conflict". There is a conflict! Try this:
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
struct dummy four;
four.member = four();
}
And now this
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
int (*fx)(void) = four; /* "save" function */
struct dummy four; /* hide it */
four.member = fx(); /* use "hidden" fx */
}
In your 2nd example, the variable four
hides the function four()
.
To answer your two questions quick.
Q1. In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
A1. Yes, identifiers for functions and typedef'ed types share the same namespace. So there's a conflict.
Q2. In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
A2. There's no conflict in your 2nd example even though the two identifiers named four belong to the same identifier namesapce, which is Ordinary namespace
. Because the variable identifier four in the main is in a function scope, whereas the function identifier four in a file scope. So the latter one is hidden by the former one as the basic scope rule. If you move the variable four to the file scope(global) like below, you'll see an error.
...
struct dummy four; // Error! there's a previous definition
// in this file scope(global).
int main() {
// struct dummy four; // Commented out.
}
Actually, there are four different identifier namespaces: Label, Tag, Member, and Ordinary. You can find details about them at https://en.cppreference.com/w/c/language/name_space
精彩评论