13

经过多年的编程,我正在学习 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 代码,而我认为这与我想告诉它的相反。我不明白什么?

4

3 回答 3

12
  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 -Werror-隐式函数声明 \
    -D_ANSI_SOURCE -pedantic -Wall -std=c99 ...
错误:函数“索引”的隐式声明

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

于 2012-08-13T08:38:38.947 回答
1

为了记录:icc我发现这样做最有帮助

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

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

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

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

因此,从本质上讲,您声明的编译器和版本的组合并不能真正帮助您满足您的需求。

于 2012-08-13T08:20:43.080 回答
1

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

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

于 2012-08-13T07:55:47.060 回答