首页 > 解决方案 > 我可以禁用或忽略 Apple 对 C 标准头文件的添加吗?

问题描述

我正在开发一个 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";
}

错误:

/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)

更新:

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

7.31 未来的图书馆方向
为了方便起见,以下名称被分组在单独的标题下。 无论程序包含什么标头,下面描述的所有外部名称都是保留的。

...

7.31.2 字符处理<ctype.h>“以or
开头的函数名和一个小写字母可以添加到标题中的声明中”。isto<ctype.h>

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

标签: cclangc-standard-libraryxcode-command-line-tools

解决方案


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

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

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

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

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

非解决方案包括:

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

推荐阅读