为什么我们需要功能测试宏?
通过阅读-D_XOPEN_SOURCE 做什么/意味着什么?,我了解如何使用功能测试宏。
但是我还是不明白为什么我们需要它,我的意思是,我们可以启用所有可用的功能吗?然后文档是这样写的:这个功能只在Mac/BSD下可用,那个功能只在Linux下可用,如果你使用它,那么你的程序只能在那个系统上运行。
那么为什么我们首先需要一个功能测试宏呢?
回答
为什么我们需要它,我的意思是,我们可以启用所有可用功能吗?
想象一下,某家公司编写了完美的超级可移植代码,大致如下所示:
#include <stdlib.h>
struct someone_s { char name[20]; };
/// @brief grants Plant To someone
int grantpt(int plant_no, struct someone_s someone) {
// some super plant granting algorithm here
return 0;
}
int main() {
// some program here
struct someone_s kamil = { "Kamil" };
return grantpt(20, kamil);
}
该程序完全正常并且一切正常,并且该程序与 C 非常兼容,因此应该可以移植到任何地方。现在想象一下_XOPEN_SOURCE不存在的时刻!客户收到该程序的源代码,并尝试在他的尖端 Unix 计算机上编译并运行它,并在经过认证的 POSIX 系统上使用经过认证的 C 编译器,然后他收到了该公司必须修复的错误,并且必须支付以下费用:
/tmp/1.c:7:9: error: conflicting types for ‘grantpt’; have ‘int(struct someone_s, int)’
7 | int grantpt(struct someone_s someone, int plant_no) {
| ^~~~~~~
In file included from /tmp/1.c:2:
/usr/include/stdlib.h:977:12: note: previous declaration of ‘grantpt’ with type ‘int(int)’
977 | extern int grantpt (int __fd) __THROW;
| ^~~~~~~
看起来 POSIX 中已经采用了为函数选择的完全随机名称 - grantpt()。
当引入不在保留空间中的新符号时,像 POSIX 这样的标准不能只是“添加它们”并期望世界不要抗议 - 冲突的定义可以并且将会并且确实会破坏有效的程序。为了解决这个问题,引入了feature_test_macros。当程序执行时#define _XOPEN_SOURCE 500,意味着它已为 POSIX 标准做好准备,并且该版本中 POSIX 引入的代码和符号之间没有冲突。
功能测试宏不仅仅是“我的程序想要使用这些功能”,最重要的是“我的程序与这些功能没有冲突”,这更重要,让现有程序继续运行。