c - 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
?
解决方案
您所称的“源类型参数”称为功能测试宏,如果已定义它们,则特别需要在包含任何标准标头之前对其进行定义。
这是在XSH 2.2.1 POSIX.1 Symbols中指定的:
符合 POSIX 的应用程序应确保在包含任何标头之前定义功能测试宏 _POSIX_C_SOURCE。
...
符合 XSI 的应用程序应确保在包含任何标头之前使用值 700 定义功能测试宏 _XOPEN_SOURCE。
Linux 手册页feature-test-macros
还清楚地说明了对标准及其扩展的要求:
注意:为了有效,必须在包含任何头文件之前定义功能测试宏
您不能重新定义和重新包含标题来更改内容,实际上在标题之间定义或取消定义/重新定义它们(甚至是不同的,看似不相关的标题)可能会完全破坏事物。
推荐阅读
- php - 无法请求令牌
- xgboost - xgboost模型的内部节点预测
- firebase - 在颤振应用程序中包含 firebase_storage 的最佳方法是什么?
- kubernetes - 为什么我的 kubernetes webook 只在创建时调用而不在更新时调用?
- c# - 文本框限制值和小数位的简单验证代码是什么?
- testng - 使用 TestNG SoftAssertions 测试通过时如何打印通过消息
- c++ - 在表达式 left() = right() 中,为什么 right() 先排序?
- elasticsearch - 如何在 Elasticsearch 中存储布尔数组并执行 XOR 操作?
- r - R:在数据框中创建一个新列,使用来自另一个数据框的列名、条件和值
- swift - 在 UITableView 中选择单元格后更新视图控制器中的项目