问题 使用gcc,严格包含C99符号,特别是不包括POSIX


经过多年的编程,我正在修课。我的导师没有使用POSIX机器,最近我因使用它而受到处罚 index 在作业中发挥作用。我做了一些研究,我注意到了 index 它是AT&T Unix的早期版本,符合POSIX标准,不属于C99标准。 我希望gcc帮我找到类似符号的用法。我正在使用gcc 4.2编译OSX( LLVM)

我的第一站研究涉及到我的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代码时,我认为这与我想说的相反。我不明白的是什么?


7621
2017-08-13 07:51


起源

你真的坚持使用gcc 4.2吗?因为这甚至不完全符合C99本身。 Clang可能是更好的选择。 - Jens Gustedt
不,绝不!我愿意尝试新的编译器(我已经在更新的OSX上使用clang / llvm用于其他项目)。也许明天我会报告。 - Chris Trahey
index 并不完全符合“POSIX标准”。它已在POSIX 2008中删除,并已在POSIX 2001中弃用。 - Nicholas Wilson
问题可能是两者都有 -ansi 和 -std=c99。 -ansi 是指定的 -std=c89。当被要求遵守两个不同的标准时,我不确定gcc的行为,但是 -ansi 和 -std=c99 似乎是互斥的选择。 - hmjd
@hmjd谢谢,善良的眼睛(尝试许多选项的证据)。如果我正确地理解了许多GNU工具,那么通常只需遵守最后一个就可以解决具有矛盾含义的多个标志。虽然我将删除-ansi(并在编辑帖子之前验证结果是否相同) - Chris Trahey


答案:


  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-implicit-function-declaration \
    -D_ANSI_SOURCE -pedantic -Wall -std = c99 ...
错误:函数'index'的隐式声明

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


11
2017-08-13 08:38



+1 - 一个实用方法的很好的总结,它将涵盖大多数非ISO C功能(这可能足以满足ctrahey的需求) - Sander De Dycker
很棒的答案!我不知道 _ANSI_SOURCE。 - Norman Ramsey
很好的答案,谢谢!这样做对我的目的很好:-) - Chris Trahey


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

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


1
2017-08-13 07:55



很抱歉最初省略它(我编辑了我的问题以表明这一点),但我一直在使用这些标志;它们不会引起警告(没有POSIX功能宏),也不会导致链接失败(即使使用宏) - Chris Trahey


记录:用 icc 我发现它最有帮助

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

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

至于抛出错误,我只是用 -Werror

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

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


1
2017-08-13 08:20



-Werror-implicit-function-declaration 至少和GCC 4.0一样古老。 - Dietrich Epp
啊,我明白了,我的意思是新语法: -Werror=implicit-function-declaration,... - hroptatyr