2

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

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

4

2 回答 2

8

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

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

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

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

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

非解决方案包括:

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

是的,它们可以被禁用。但在禁用任何东西之前,我强烈建议阅读 Acorn 的答案。仅仅因为您可以禁用它们,并不意味着您应该这样做。例如,在我的情况下,尝试禁用 Apple 添加是错误的解决方案。但我的问题是“可以……”而不是“应该……”。

可以通过添加#define _POSIX_C_SOURCE#define _ANSI_SOURCE之前禁用它们#include ctype.h。这将“禁用”库中的 Apple 插件,例如:

#define _POSIX_C_SOURCE

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

如果你只想在 maxOS 上定义这个,你可以先检查系统定义的宏__MACH__,(见这个问题),例如:

#ifdef __MACH__
#define _POSIX_C_SOURCE
#endif

#include <ctype.h>
#include <stdio.h>
...
解释:

Apple 的ctype.h包括_ctype.h附加声明和定义受以下保护的地方:

#if !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))

感谢 FelixG,他首先向我指出了这个方向。

于 2020-08-12T09:48:59.147 回答