引自here,
在C中,有两种不同的类型名称空间:struct / union / enum标记名称的名称空间和typedef名称的名称空间。
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
$
我正在尝试了解C命名空间冲突。
在第一种情况下,为什么会发生冲突?函数是否也属于typedef命名空间?
在第二种情况下,为什么没有冲突?函数和变量都命名为four。为什么编译器允许这样做? &four
应如何解决?
答案 0 :(得分:26)
C有四个不同的标识符名称空间:
goto
类型)。另见C99 6.2.3。
所以你的两个问题可以回答为:
答案 1 :(得分:7)
但是你的例子的关键点不是名称空间,而是名称的范围。
在 name.c 中,long2
都是“普通标识符”(共享相同的名称空间),并且它们都在同一范围内定义,因此存在冲突。 (C99§6.7/ 3)
如果 name2.c ,则局部变量four
的范围比函数four
更深,因此变量隐藏函数four
(C99§6.2.1/ 4)。
答案 2 :(得分:6)
你的第二个例子没有显示“没有冲突”。有冲突!试试这个:
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
struct dummy four;
four.member = four();
}
现在这个
#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 */
}
在第二个示例中,变量four
隐藏了函数four()
。
答案 3 :(得分:0)
快速回答您的两个问题。
Q1。在第一种情况下,为什么会有冲突?函数也属于typedef名称空间吗?
A1。是的,功能和类型定义的类型的标识符共享相同的名称空间。因此存在冲突。
第二季度。在第二种情况下,为什么根本没有冲突?函数和变量都命名为四个。为什么编译器允许这样做? &four应该如何解决?
A2。在第二个示例中,即使两个名为 four 的标识符属于相同的标识符名称,即Ordinary namespace
,也没有冲突。因为主要的变量标识符 four 在功能范围中,而函数标识符 four 在文件范围中>。因此,前者作为基本范围规则被后者隐藏了。如果将变量 four 移至如下所示的文件范围(全局),则会看到错误。
...
struct dummy four; // Error! there's a previous definition
// in this file scope(global).
int main() {
// struct dummy four; // Commented out.
}
实际上,有四个不同的标识符名称空间:标签,标签,成员和普通。您可以在https://en.cppreference.com/w/c/language/name_space
中找到有关它们的详细信息