C++ 为什么<;信号h>;防止使用;"是";作为某些变量名称的前缀?

C++ 为什么<;信号h>;防止使用;"是";作为某些变量名称的前缀?,c++,c,linux,C++,C,Linux,我一直在调试代码中出现的一个奇怪的编译错误,结果发现如果包含,我就不能对某些变量名(任何类型)使用前缀si\ucode> 下面是一个非常简单的源代码示例,再现了这个问题: #include <signal.h> int main(void) { int si_value = 0; return 0; } 尽管如此,如果我使用另一个名称,例如si_value2,则不会显示错误。作为参考,我在Ubuntu Mate 18.04.1 LTS上使用GCC v7.3.0。

我一直在调试代码中出现的一个奇怪的编译错误,结果发现如果包含
,我就不能对某些变量名(任何类型)使用前缀
si\ucode>

下面是一个非常简单的源代码示例,再现了这个问题:

#include <signal.h>

int main(void)
{
    int si_value = 0;

    return 0;
}
尽管如此,如果我使用另一个名称,例如
si_value2
,则不会显示错误。作为参考,我在Ubuntu Mate 18.04.1 LTS上使用GCC v7.3.0。在
g++
中也观察到同样的问题

我认为这种行为是由于
标题中的一些宏定义造成的,但在简要地查看之后,我似乎找不到任何真正相关的内容

老实说,我可以用另一个名字来修复它。然而,我担心的是:我今后如何优雅地避免此类问题?


更新:正如@F.X.所建议的,使用
gcc-E示例。c
显示变量名已展开(因此出现错误):

我怎样才能在将来优雅地避免此类问题

您可以检查一些正在使用的标题,并避免记录为保留的名称。

实际上并不会阻止在变量上使用
si\uu
作为前缀。但是,POSIX规范声明保留该前缀,以便允许它声明的头和库函数使用这些名称,而不必担心它们会与您自己的变量冲突

所以这里发生的事情是,
si_value
在头文件中以某种方式定义,可能是作为宏或typedef,您尝试使用相同的名称与此冲突。如果您使用了
si_vy1ghad563nvy43wd
,它可能会起作用,但理论上头部可以使用该名称(认为它不太可能与应用程序程序员使用的任何名称冲突)


C没有真正的名称空间,所以像这样的命名约定被用作一个简单的替代品。

你能看看
gcc-E
(就在预处理器之后)的输出吗?它可能会提示您出了什么问题。它只是名称
si_值
?闻起来好像宏被替换到了代码中。类似于
si_vy1ghad563nvy43wd
的东西呢?@alterigel抱歉,
si_vy1ghad563nvy43wd
也是一个保留关键字。@AndrewHenle好吧,这是一个笑话。它在哪里说
si_value
是一个保留名称?我所看到的只是在
siginfo\u t
结构中对该名称字段的引用,但这完全不是一回事?@unwind 2.2.2namespace@Jean-弗朗索瓦·法布可能也用同样的方式保留了一个
\u t
suffix@Jean-Françoisfare——它之所以保留是因为POSIX(搜索siçuz)。@SRG不用担心;你的投票,你的判断,这都是出于设计。标识符不是以“\uuuuuuuuuuuuu”开头的吗?它不能用它来代替吗?或者这是其他的东西?我认为这实际上是一个POSIX的东西,而
\uuu
是一个C的东西。因此,POSIX试图避免保留给C实现的名称。但
signal.h
不是标准头吗?C11保留以
SIG
开头,后跟大写字母的名称,或
SIG
后跟大写字母(C11)。当包含
时,POSIX会保留更多的符号前缀-。C标准保留了前导的
\uuuu
供实现(C11)使用。阅读并注意避免冲突。或者在它们出现时修复。@Kevin:The
头既是标准的C头,也是标准的POSIX头。由于在调用GCC时没有指定
-std=c11
或类似项,因此它启用了所有GNU扩展,其中包括POSIX函数和符号。如果指定了
-std=c11
,则可能需要在编译器命令行上编写
-dxopen\u SOURCE=700
,或者在头或代码中编写类似的
#define
(我建议在头中执行此操作,十年前在代码中使用过一次,并且此后花费了相当长的时间撤消它)。
> 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
...
    int 
# 6 "example.c" 3 4
       _sifields._rt.si_sigval 
# 6 "example.c"
                = 0;
...