我可以禁用或忽略 Apple 对 C 标准头文件的添加吗?

cod*_*ast 2 c clang c-standard-library xcode-command-line-tools

我正在开发一个 C 应用程序,我希望它具有合理的可移植性。它可以在 Linux 上使用 gcc 和 clang 以及在 Windows 上使用 MSVC 构建。访问 Mac 后,我尝试使用命令行工具进行构建。

它无法编译,因为我的代码声明了一个函数,isnumber而 Apple 的ctype.h头文件也声明了一个 (non standard?) isnumber。我可以重命名我的函数,这样它就不会发生冲突,但是有没有办法通过禁用或忽略所有或特定的 Apple 添加到标准标头来避免这种情况?例如,是否有编译器选项或预处理器编译指示来忽略它们?

isnumber不知道检查字符类。下面是重现该问题的代码 - 它可以用 clang/Linux 和 MSVC/Windows 编译,但不能在 Mac 上编译( - 它不是实际代码)。

#include <ctype.h>
#include <stdio.h>

char *isnumber(void);

int main(void)
{
    char *opt = "A";

    if (isupper(*opt))
        printf("THE IS NUMBER IS: %s\n", isnumber());
    else
        printf("The IS number is: %s\n", isnumber());

    return 0;
}

char *isnumber(void)
{
    return "IS-123";
}
Run Code Online (Sandbox Code Playgroud)

错误:

/Users/ ... /repro/main.c:4:7: error: conflicting types for 'isnumber'
char *isnumber(void);
      ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/_ctype.h:323:1: note: previous definition is here
isnumber(int _c)
Run Code Online (Sandbox Code Playgroud)

更新:

正如 Acorn 的回答及其评论所描述的那样,“isnumber”是C11标准保留的函数的错误名称:

7.31 未来的库方向
为方便起见,以下名称分组在各个标题下。 无论程序包含什么头文件,下面描述的所有外部名称都被保留

...

7.31.2 字符处理<ctype.h>
“以is或开头的函数名称,to可以将小写字母添加到<ctype.h>标题中的声明中”。

所以我原来问题的“正确”解决方案是让我重命名我的函数。

Aco*_*orn 8

我正在开发一个 C 应用程序,我希望它具有合理的可移植性。

它无法编译,因为我的代码声明了一个函数 isnumber

C 和 POSIX 都保留所有is[a-z]*名称(在 POSIX 的情况下,仅当包含标头时),因此代码不可移植。

使其可移植的唯一方法是避免使用这样的标识符。

一种解决方案是在来自您提到的规范的所有标识符前加上类似于规范名称的内容,例如xx*or xx_*。C 库采用了类似的方法来避免与其他库发生冲突。

非解决方案包括:

  • 避免包含ctype.h. 仍然不便携,即使在实践中它有更高的机会在其他系统中工作。
  • 使用一些宏定义禁用扩展。仍然不可移植,因为其他系统可能无法识别并仍然定义isnumber. 在实践中,您最终将不得不研究如何在每个系统中做类似的事情。

  • 即使不包含 `&lt;ctype.h&gt;`,`is[az]*` 名称仍然由 C 标准保留(C11 7.31 和 7.31.2)。 (3认同)