我最近偶然发现了一个奇怪的代码构造,它导致C编译器进入一个奇怪的状态.我想解释一下为什么会这样.
这是我的小代码片段,演示了这个问题:
#include <stdlib.h>
typedef int type_t;
int main (void)
{
int a = 10, b = 100;
type_t *type_t = &a; // We name a variable with type name
type_t *type_c = &b; // We define a variable with type_t
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
这是显示的错误消息gcc
:
#> gcc -Wall -Wextra -o sample sample.c
sample.c: In function ‘main’:
sample.c:11:11: error: ‘type_c’ undeclared (first use in this function); did you mean ‘type_t’?
type_t *type_c = &b;
^~~~~~
type_t
sample.c:11:11: note: each undeclared identifier is reported only once for each function it appears in
Run Code Online (Sandbox Code Playgroud)
或者,用clang
:
#> clang -Wall -Wextra -o sample sample.c
sample.c:11:11: error: use of undeclared identifier 'type_c'; did you mean 'type_t'?
type_t *type_c = &b;
^~~~~~
type_t
sample.c:10:11: note: 'type_t' declared here
type_t *type_t = &a;
^
sample.c:11:10: error: invalid operands to binary expression ('type_t *' (aka 'int *') and 'type_t *')
type_t *type_c = &b;
~~~~~~ ^~~~~~~
2 errors generated.
Run Code Online (Sandbox Code Playgroud)
请注意,如果我们修改代码如下,它编译正常:
int main (void)
{
int a = 10, b = 100;
type_t *type_c = &b; // We define a variable with type_t
type_t *type_t = &a; // We name a variable with type name
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
那么,我的问题吧!
似乎错误是由于赋值运算符'='的l值被误认为是type_t
和之间的乘法而产生的type_c
.如type_c
未知,它解释了错误消息.
但是,为什么我们对l值有这种混淆?type_t
参考类型而不是变量不应该是明确的吗?
我想这是不是一个实现的问题,因为这两个,gcc
和clang
相同的行为.但是,我真的很想知道这个问题的关键.
Jon*_*ler 11
这是预期和正确的行为.在C中,有许多名称空间:标签,成员,标签和普通标识符.一个typedef
名称是普通的标识符名字空间,因为是变量名.
你有:
type_t *type_t = &a; // We name a variable with type name
type_t *type_c = &b; // We define a variable with type_t
Run Code Online (Sandbox Code Playgroud)
这里有三次type_t
.第一个是typedef名称; 没问题.第二个是新的变量名称; 没问题,但它隐藏(阴影)typedef名称; 您不能再引用type_t
当前代码块中的类型.第三种情况是指变量; 您将整数指针乘以未定义的变量(并尝试将结果用作l值来接收地址b
),这在许多级别上都是错误的.
当你颠倒这些行的顺序时,它工作正常,因为type_c
声明是type_t *
正常的; 然后type_t
定义为类型的变量type_t *
,但不能type_t
对当前块中的类型进行进一步的引用(任何此类引用都是变量,而不是类型).
请注意,如果它typedef
位于函数内部,则无法使用它进行遮罩type_t *type_t = &a;
.见C11§6.2.1标识符的范围.
归档时间: |
|
查看次数: |
125 次 |
最近记录: |