首页 > 解决方案 > libc 包含不遵守源类型参数更改的守卫

问题描述

问题

如果我包含time.h,更改“源类型参数”并重新包含该标题,它不应该添加到那些新定义中吗?我知道这是由于包括警卫而发生的。我的问题是:这是 libc 中的错误吗?它不应该能够处理这个吗?

#include <time.h>
#define _XOPEN_SOURCE 600
#include <time.h>

static struct timespec t;

错误信息:

example.c:5:24: error: storage size of ‘t’ isn’t known
    5 | static struct timespec t;
      |                        ^

背景

我在使用-std=c99. 如果我在包含之前包含标准库,Python.h我会因为缺少 POSIX 功能的定义而出现编译错误。如果我Python.h在其他一切之前移动了包含,一切都很好。当然也可以使用-std=gnu99作品进行编译。但我想深入了解错误发生的原因,并将其提炼为上述代码示例。

这就引出了另一个问题。如果上述行为不是错误,那么_XOPEN_SOURCE在标头中设置和类似的源类型参数是否被认为是不好的做法?Python 应该在其标头中删除该参数的设置,而是要求用户在编译期间定义它,还是使用std=gnu99?

标签: clibc

解决方案


您所称的“源类型参数”称为功能测试宏,如果已定义它们,则特别需要在包含任何标准标头之前对其进行定义。

这是在XSH 2.2.1 POSIX.1 Symbols中指定的:

符合 POSIX 的应用程序应确保在包含任何标头之前定义功能测试宏 _POSIX_C_SOURCE。

...

符合 XSI 的应用程序应确保在包含任何标头之前使用值 700 定义功能测试宏 _XOPEN_SOURCE。

Linux 手册页feature-test-macros还清楚地说明了对标准及其扩展的要求:

注意:为了有效,必须在包含任何头文件之前定义功能测试宏

您不能重新定义和重新包含标题来更改内容,实际上在标题之间定义或取消定义/重新定义它们(甚至是不同的,看似不相关的标题)可能会完全破坏事物。


推荐阅读