在用户定义的标记之后 #include 文件是否存在潜在问题?

问题描述 投票:0回答:2

由于预处理器的工作方式,包含的头文件可能会受到包含头文件的文件的影响。例如,您可以使用以下命令来破坏 C:

#define printf
#include <stdio.h>
/*  extern int printf(const char *const restrict format, ...);
    Becomes
    extern int (const char *const restrict format, ...);
    And this results in an instant syntax error */

但是,我担心任何随机的用户定义标识符都可能以类似的方式破坏特定实现的头文件。但是可以期望库头文件永远不会相互破坏,因为这样 C 实现就会完全破坏,因此不符合要求。因此,我一直小心地将库标题始终放在顶部:

#include <stdio.h>
#include <somelibrary.h>

#define some_macro
typedef some_type some_other_type;

而不是:

#define some_macro
typedef some_type some_other_type;

#include <stdio.h>
#include <somelibrary.h>

因为如果任何一个库碰巧包含令牌

some_macro
some_other_type
它们可能会崩溃。

这些担忧是否有根据?或者 C 是否要求可以 'break' 库标头的令牌数量以某种方式限制为仅由标头定义的用户可见的令牌?

c header name-conflict
2个回答
2
投票

一些库有条件地定义符号。

__POSIX_SOURCE
_POSIX_C_SOURCE
,__是我最常遇到的,但还有很多其他人。每个@Someprogrammerdude 都有大量且令人困惑的保留名称空间,您不应该使用它们来避免未定义的行为。例如
_
前缀和
_t
后缀是保留的,但我经常看到在用户代码中使用。


1
投票

我担心任何随机的用户定义标识符...

C有reserved identifiers(bolding mine)的概念:

每个标头都声明或定义了其相关子条款中列出的所有标识符,并可选择声明或定义其相关未来库方向子条款中列出的标识符和始终保留供任何用途或用作文件范围标识符的标识符。

如果程序在保留标识符的上下文中声明或定义标识符(7.1.4 允许的情况除外),或者将保留标识符定义为宏名称,则行为未定义.

标识符 C 储备由 C 标准标识。

此外,POSIX 等平台 保留额外的标识符,Windows 也这样做 - 其中一些可以在这里找到 - 但 Windows 保留了 lot 更多标识符。

注意上面的第二个引用,特别是粗体部分:

如果程序在保留标识符的上下文中声明或定义标识符(7.1.4 允许的情况除外),或者将保留标识符定义为宏名称,则行为未定义.

是的,如果您使用保留标识符,您可以并且将会破坏您的程序。

修复:不要这样做。

例如这是一个保留标识符:

__SOMETHING
.

以双下划线开头,所以是保留标识符。不要那样做。

这也是POSIX下的保留标识符:

something_t

_t
结尾,POSIX下保留。不要那样做。 (很多人打破了这个,有时他们后来会遇到问题。不要依赖你的
_t
标识符是碰撞安全的。)

在文件范围内,这是一个保留标识符:

static int _count;

以下划线开头。这是文件范围内的保留标识符。不要这样。 (同样在这里 - 许多程序员违反了这条规则并认为他们逃脱了它 - 他们只是幸运。不要让运气成为your代码正常工作的必要条件......)

很多程序员使用保留标识符并且不会遇到冲突,所以他们认为这样做是可以的。但他们在未来无缘无故地面临碰撞和破损。

© www.soinside.com 2019 - 2024. All rights reserved.