我可以禁用或忽略 Apple 对 C 标准 headers 的补充吗?
Can I disable or ignore Apple additions to C standard headers?
我正在开发一个 C 应用程序,我希望它具有合理的可移植性。它可以在 Linux 上使用 gcc 和 clang,在 Windows 上使用 MSVC。在访问 Mac 之后,我尝试使用命令行工具进行构建。
它无法编译,因为我的代码声明了一个函数 isnumber
而 Apple 的 ctype.h
header 也声明了一个(非标准?)isnumber
。我可以重命名我的函数,这样它就不会发生冲突,但是有没有办法通过禁用或忽略所有或特定的 Apple 对标准 header 的添加来避免这种情况?例如。是否有编译器选项或预处理器编译指示来忽略它们?
我的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 Future library directions
The following names are grouped under individual headers for convenience. All external names described below are reserved no matter what headers are included by the program.
...
7.31.2 Character handling <ctype.h>
"Function names that begin with either is
or to
, and a lowercase letter may be added to the declarations in the <ctype.h>
header".
所以 'correct' 解决我原来问题的方法是重命名 my 函数。
I'm developing a C application that I would like to be reasonably portable.
It fails to compile because my code declares a function isnumber
C 和 POSIX 都保留所有 is[a-z]*
名称(在 POSIX 的情况下仅包含 header),因此代码不可移植。
使其可移植的唯一方法是避免使用此类标识符。
一个解决方案是在所有来自您提到的规范的标识符前加上类似于规范名称的内容,例如xx*
或 xx_*
。 C 库采用类似的方法来避免与其他库发生冲突。
Non-solutions包括:
- 避免包含
ctype.h
。仍然不可移植,即使在实践中它有更高的机会在其他系统中工作。
- 正在使用一些宏定义禁用扩展。仍然不可移植,因为其他系统可能无法识别并仍然定义
isnumber
。在实践中,您最终将不得不研究如何在每个系统中做类似的事情。
是的,它们可以被禁用。但在禁用任何功能之前,我强烈 建议阅读 Acorn 的回答。仅仅因为您可以禁用它们,并不意味着您应该这样做。例如,在我的案例中,尝试禁用 Apple 添加是 错误的 解决方案。但我的问题是 'Can ...' 而不是 'Should ...'.
可以通过在 #include ctype.h
之前添加 #define _POSIX_C_SOURCE
或 #define _ANSI_SOURCE
来禁用它们。这将 'disable' Apple 添加到库中,例如:
#define _POSIX_C_SOURCE
#include <ctype.h>
#include <stdio.h>
...
如果您只想在 maxOS 上定义它,您可以先检查系统定义的宏 __MACH__
,(参见 this question),例如:
#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,他首先向我指出了这个方向。
我正在开发一个 C 应用程序,我希望它具有合理的可移植性。它可以在 Linux 上使用 gcc 和 clang,在 Windows 上使用 MSVC。在访问 Mac 之后,我尝试使用命令行工具进行构建。
它无法编译,因为我的代码声明了一个函数 isnumber
而 Apple 的 ctype.h
header 也声明了一个(非标准?)isnumber
。我可以重命名我的函数,这样它就不会发生冲突,但是有没有办法通过禁用或忽略所有或特定的 Apple 对标准 header 的添加来避免这种情况?例如。是否有编译器选项或预处理器编译指示来忽略它们?
我的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 Future library directions
The following names are grouped under individual headers for convenience. All external names described below are reserved no matter what headers are included by the program....
7.31.2 Character handling
<ctype.h>
"Function names that begin with eitheris
orto
, and a lowercase letter may be added to the declarations in the<ctype.h>
header".
所以 'correct' 解决我原来问题的方法是重命名 my 函数。
I'm developing a C application that I would like to be reasonably portable.
It fails to compile because my code declares a function
isnumber
C 和 POSIX 都保留所有 is[a-z]*
名称(在 POSIX 的情况下仅包含 header),因此代码不可移植。
使其可移植的唯一方法是避免使用此类标识符。
一个解决方案是在所有来自您提到的规范的标识符前加上类似于规范名称的内容,例如xx*
或 xx_*
。 C 库采用类似的方法来避免与其他库发生冲突。
Non-solutions包括:
- 避免包含
ctype.h
。仍然不可移植,即使在实践中它有更高的机会在其他系统中工作。 - 正在使用一些宏定义禁用扩展。仍然不可移植,因为其他系统可能无法识别并仍然定义
isnumber
。在实践中,您最终将不得不研究如何在每个系统中做类似的事情。
是的,它们可以被禁用。但在禁用任何功能之前,我强烈 建议阅读 Acorn 的回答。仅仅因为您可以禁用它们,并不意味着您应该这样做。例如,在我的案例中,尝试禁用 Apple 添加是 错误的 解决方案。但我的问题是 'Can ...' 而不是 'Should ...'.
可以通过在 #include ctype.h
之前添加 #define _POSIX_C_SOURCE
或 #define _ANSI_SOURCE
来禁用它们。这将 'disable' Apple 添加到库中,例如:
#define _POSIX_C_SOURCE
#include <ctype.h>
#include <stdio.h>
...
如果您只想在 maxOS 上定义它,您可以先检查系统定义的宏 __MACH__
,(参见 this question),例如:
#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,他首先向我指出了这个方向。