为什么<signal.h>阻止使用"si_"作为某些变量名称的前缀?

SRG*_*SRG 24 c c++ linux

我一直在调试一个奇怪的编译错误,我在我的代码中,我最终发现我不能使用前缀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没有真正的命名空间,因此这样的命名约定被用作简单的替代.

  • C11保留名称以`SIG`后跟大写字母,或`SIG_`后跟大写字母(C11 [§7.14信号处理`<signal.h>`](http://port70.net/~nsz/c) /c11/n1570.html#7.14p4)).当包含`<signal.h>`时,POSIX保留了更多的符号前缀 - [§2.2.2名称空间](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02) .C标准保留领先的"__"以供实现使用(C11 [§7.1.3保留标识符](http://port70.net/~nsz/c/c11/n1570.html#7.1.3)).阅读并注意避免冲突.或者在它们出现时修复它们. (4认同)
  • 我认为这实际上是一个POSIX的东西,而`__`是C的东西.所以POSIX试图避免保留给C实现的名称. (3认同)
  • @Kevin:`<signal.h>`标头既是标准的C标头,也是标准的POSIX标头.由于在调用GCC时未指定`-std = c11`或类似内容,因此它启用了所有GNU扩展,其中包括POSIX函数和符号.如果指定了`-std = c11`,则可能需要在编译器命令行上编写`-D_XOPEN_SOURCE = 700`,或者在标题或代码中写一个类似的`#define`(我建议在标题中执行它,十年前曾在代码中使用它,并且从那时起花了相当多的时间撤消它. (2认同)

Bau*_*gen 12

我怎么能在将来优雅地避免这类问题?

您检查了正在使用的标头的一些文档,并避免记录为保留的名称.

  • @ Jean-FrançoisFabre可能以同样的方式保留了`_t`后缀 (4认同)
  • @SRG不用担心; 你的投票,你的判断,这是设计的. (4认同)
  • @ Jean-FrançoisFabre - 它是保留的,因为POSIX [说它是](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html)(搜索si_). (2认同)