我一直在调试一个奇怪的编译错误,我在我的代码中,我最终发现我不能使用前缀si_的一些变量名称(任何类型),如果<signal.h>包括.
这是一个非常简单的源代码示例,可以重现该问题:
#include <signal.h>
int main(void)
{
int si_value = 0;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用GNU C编译器编译它gcc,我会收到以下错误:
> gcc example.c
In file included from /usr/include/signal.h:57:0,
from example.c:2:
example.c: In function ‘main’:
example.c:6:9: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
int si_value = 0;
^
example.c:6:9: error: expected expression before ‘.’ token
Run Code Online (Sandbox Code Playgroud)
尽管如此,如果我使用其他名称si_value2,则错误不会显示.作为参考,我在Ubuntu Mate 18.04.1 LTS上使用GCC v7.3.0.观察到同样的问题g++.
我认为这种行为是由于<signal.h>标题内部的一些宏定义所致,但在简要介绍之后,我似乎无法找到真正相关的内容.
老实说,我可以通过使用其他名称来修复它.但是,我担心的是:将来我怎么能优雅地避免这类问题呢?
更新:正如@FX建议的那样,使用gcc -E example.c显示变量名称被展开(因此,错误):
...
int
# 6 "example.c" 3 4
_sifields._rt.si_sigval
# 6 "example.c"
= 0;
...
Run Code Online (Sandbox Code Playgroud)
Bar*_*mar 23
<signal.h>实际上并没有阻止si_在变量上使用前缀.但是,POSIX规范声明此前缀是保留的,以便允许它声明的头和库函数使用这些名称,而不必担心它们会与您自己的变量冲突.
所以这里发生的事情是si_value在头文件中以某种方式定义,可能是宏或typedef,并且您尝试使用相同的名称与此冲突.如果您使用si_vy1ghad563nvy43wd它可能会起作用,但理论上头部可以使用该名称(认为它不太可能与应用程序员使用的任何东西冲突).
C没有真正的命名空间,因此这样的命名约定被用作简单的替代.