C语言 对于 gcc,严格包括 C99 符号,特别是不包括 POSIX



经过多年的编程,我正在学习C语言课程。我的老师没有使用POSIX机器,我最近因为在作业中使用index功能而受到处罚。我做了一些研究,我注意到虽然index是AT&T Unix的早期部分并且符合POSIX标准,但它不是C99标准的一部分。我希望 gcc 帮助我找到类似符号的使用。我正在使用 gcc 4.2(不是 llvm)在 OSX 上编译

我的第一站研究涉及注意到我的 string.h 文件在以下功能测试宏检查中包装了index的原型:

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

经过一番挖掘,我发现了这个(在我的/usr/include/sys/cdefs.h):

 /* STRICT  Defining _POSIX_C_SOURCE or _XOPEN_SOURCE restricts the
 *      available APIs to exactly the set of APIs defined by the
 *      corresponding standard, based on the value defined.
 *
 *      A correct, portable definition for _POSIX_C_SOURCE is 200112L.
 *      A correct, portable definition for _XOPEN_SOURCE is 600L.
 */

所以有了这个 gcc 命令:

gcc -D _POSIX_C_SOURCE=200112L -pedantic -Wall -std=c99 -o myExec ./mySource.c

确实得到了一个不错的警告:

warning: incompatible implicit declaration of built-in function ‘index’

这让我感到困惑,我想让程序也无法链接。它让我感到困惑的原因是,我在 opengroup.org 读到定义宏应该公开 POSIX 符号,而不是隐藏它们。因此,这是我以简洁的形式提出的问题:

如何使 gcc 4.2(在 OSX 10.6 上)在严格 C99 的环境中编译和链接我的程序,没有其他可用的符号

理想情况下,我希望在编译和链接失败期间发出警告。我希望答案不涉及告诉gcc我正在编写POSIX代码,当我相信这与我想告诉它的相反。我不明白什么?

  1. 抱歉,您不会收到链接错误。 库不是这样工作的。 index函数标准库的一部分。 标准库同时支持多个版本的 C(和 POSIX),宏选择公开哪些原型。

  2. -ansi标志等同于-std=c89,所以不要再这样做了。

  3. 您是对的,_POSIX_C_SOURCE公开了其他功能,但它也指定了要公开的功能版本。 定义_POSIX_C_SOURCE=200112L意味着index出现在<strings.h>而不是<string.h> 中。 它仍然在那里。 指定 2008 POSIX 将完全摆脱index,因为它已从更高版本的 POSIX 标准中删除。

  4. 有一个宏表示"只有ANSI C",那就是_ANSI_SOURCE

  5. 您可以通过添加-Werror-implicit-function-declaration来获得编译错误(但不是链接错误)。

$ gcc -错误隐式函数声明 \    -D_ANSI_SOURCE -迂腐 -墙 -std=c99 ...错误:函数"索引"的隐式声明

这似乎适用于所有组合OS X 10.5/10.8,GCC 4.0/4.2。

要获取 C99 环境,请将标志-std=c99 -pedantic传递给 gcc。 这不应定义任何其他功能测试宏。

但请注意,这只是省略声明,因为这些声明会侵入 C99 程序员保留的命名空间。 实际的符号仍然可能可用 - 这些符号不应该影响正确 C99 程序的编译,因为它们往往是"弱"符号,但如果您自己声明并使用它们,它们不会强制出错。

郑重声明:有了icc,我发现这样做最有帮助

icc -no-gcc -diag-enable port-win -fabi-version=2 -std=c99 ...

这将跳过系统头文件中所有 gcc 特定的 voodoo,并警告 Windows 上不存在的 POSIXism。

至于抛出错误,我只会使用 -Werror .

不幸的是,gcc 无法关闭系统头文件中特定于 gnu 的属性处理。 而且,更不幸的是,所述的 gcc 版本不支持仅在某些警告时抛出错误的-Werror=<diagnostic>语法。

所以从本质上讲,你声明的编译器和版本的组合并不能真正帮助你实现你想要的东西。

最新更新