首页 > 解决方案 > 为什么我们需要功能测试宏?

问题描述

通过阅读-D_XOPEN_SOURCE 的作用/含义是什么?,我了解如何使用功能测试宏。

但我仍然不明白为什么我们需要它,我的意思是,我们可以只启用所有可用的功能吗?然后文档是这样写的:这个功能只能在Mac/BSD中使用,那个功能只能在Linux中使用,如果你使用它,那么你的程序只能在那个系统上运行。

那么为什么我们首先需要一个功能测试宏呢?

标签: clinux

解决方案


为什么我们需要它,我的意思是,我们可以只启用所有可用的功能吗?

想象一下,某家公司编写了非常完美的超级可移植代码,大致如下:

#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 在该版本中引入的代码和符号之间没有冲突。

功能测试宏不仅仅是“我的程序要使用这些功能”,最重要的是“我的程序与这些功能没有冲突”,更重要的是,让现有的程序继续运行。


推荐阅读