我可以禁用或忽略苹果添加到C标准头吗?

我可以禁用或忽略苹果添加到C标准头吗?,c,clang,c-standard-library,xcode-command-line-tools,C,Clang,C Standard Library,Xcode Command Line Tools,我正在开发一个C应用程序,我希望它具有合理的可移植性。它在Linux上使用gcc和clang构建,在Windows上使用MSVC构建。访问Mac后,我尝试使用命令行工具构建 它无法编译,因为我的代码声明了一个函数isnumber,苹果的ctype.h头也声明了一个(非标准?isnumber)。我可以重命名我的函数,这样它就不会发生冲突,但是有没有办法通过禁用或忽略所有或特定的苹果添加到标准头中来避免这种情况?例如,是否有编译器选项或预处理器pragma可以忽略它们 我的isnumber与检查字符

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

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

我的
isnumber
与检查字符类无关。下面的代码再现了这个问题——它是用clang/Linux和MSVC/Windows编译的,但不是在Mac上编译的(这不是实际的代码)

#包括
#包括
char*isnumber(无效);
内部主(空)
{
char*opt=“A”;
如果(isupper(*opt))
printf(“IS编号为:%s\n”,isnumber());
其他的
printf(“IS编号为:%s\n”,isnumber());
返回0;
}
char*isnumber(无效)
{
返回“IS-123”;
}
错误:

/Users//repro/main.c:4:7:错误:“isnumber”的类型冲突
char*isnumber(无效);
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/_ctype.h:323:1:注意:前面的定义在这里
isnumber(整数c)
更新: 正如Acorn的回答和评论所描述的,“isnumber”是一个坏名字,因为标准保留了它:

7.31未来的图书馆方向
为方便起见,以下名称分组在各个标题下下面描述的所有外部名称都是保留的,无论程序包含哪些标题

7.31.2字符处理

“以
开头的函数名为
,可以在
标题中的声明中添加小写字母。”

因此,对我的原始问题来说,正确的解决方案是重命名我的函数

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

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

C和POSIX都保留所有
is[a-z]*
名称(对于POSIX,仅当包含头时),因此代码不可移植

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

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

非解决方案包括:

  • 避免包含
    ctype.h
    。仍然不可移植,即使在实践中它在其他系统中工作的可能性更高
  • 使用某些宏定义禁用扩展。仍然不可移植,因为其他系统可能无法识别并仍然定义
    isnumber
    。实际上,您将不得不研究如何在每个系统中执行类似的操作

是的,它们可以被禁用。但在禁用任何东西之前,我强烈建议阅读Acorn的答案。仅仅因为你可以禁用它们,并不意味着你应该禁用它们。例如,在我的案例中,试图禁用Apple附加功能是错误的解决方案。但我的问题是‘可以……’而不是‘应该……’

可以通过在
\include ctype.h
之前添加
\define\u POSIX\u C\u SOURCE
\define\u ANSI\u SOURCE
来禁用它们。这将“禁用”库中的Apple附加项,例如:

#define _POSIX_C_SOURCE

#include <ctype.h>
#include <stdio.h>
...
说明: 苹果的
ctype.h
包括
\u ctype.h
,其中附加声明和定义由以下内容保护:

#如果!已定义(_ANSI_SOURCE)&(!已定义(_POSIX_C_SOURCE)|已定义(_DARWIN_C_SOURCE))

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

重命名函数有什么问题?也许你的项目有50000行,你需要30分钟来替换所有调用…你试过用
-std=c11
编译吗?@FelixG我刚刚试过用-std=对c89、c99、c11和c17中的每一行进行编译,结果都是一样的。你有没有查看头文件,看看有没有关于这些函数的
\ifdefs
,但再看一眼,也许还有希望。。。这是一个非常有用的信息,但我可能会接受我自己的答案,因为具体问题是关于禁用可能有应用程序的Apple插件。例如,在Mac上进行初级开发的人可能希望禁用苹果添加,以避免意外地依赖于苹果特定的东西。即使
不包括在内,
是[a-z]*
名称仍由C标准保留(C11 7.31和7.31.2)。@IanAbbott你说得对,谢谢!我还要补充一点。这里有一个指向doc::-)(或者至少是它的草稿)的链接。关键的一点是,禁用Apple扩展并不能使代码可移植。事实上,当移植来自其他系统的不可移植软件时,这通常是一个逃生舱,即在不更改代码的情况下工作。但这意味着该软件的可移植性较低,而不是更高<代码>\u ANSI\u源代码来自BSD。这会使代码的可移植性降低,因为您几乎肯定会使用POSIX。在这种情况下,
isnumber()
仍然与POSIX冲突。谢谢@AndrewHenle,不,我不认为我会使用POSIX,所以源代码可能对我来说是正确的,但我会更新答案,以反映_POSIX_C_SOURCE可能是更好的选择。我不认为我会使用POSIX,因此您只需通过函数访问文件,如
fopen()
/
fread()#ifdef __MACH__
#define _POSIX_C_SOURCE
#endif

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