符合 ANSI C 标准的实现能否在其标准库中包含附加功能?
Posted
技术标签:
【中文标题】符合 ANSI C 标准的实现能否在其标准库中包含附加功能?【英文标题】:Can an ANSI C-compliant implementation include additional functions in its standard library? 【发布时间】:2011-11-14 15:34:54 【问题描述】:是否允许符合 ANSI C 的实现在其标准库中包含超出标准枚举的其他类型和函数? (理想的答案是参考 ANSI 标准的相关部分。)
我之所以这么问,是因为 Mac OS 10.7 在 stdio.h 中声明了 getline
函数,即使在使用 gcc 或 clang 使用 -ansi
标志编译时也是如此。这破坏了几个定义自己的 getline
函数的旧程序。这是 Mac OS 10.7 的故障吗? (Mac OS 10.7 上 getline
的手册页显示 getline
符合 2008 年推出的 POSIX.1 标准。)
编辑:澄清一下,我觉得奇怪的是,在 Mac OS 10.7 上的 ANSI C89 程序中包含 stdio.h 也会引入 getline
函数的声明,因为 getline
不是枚举的函数之一stdio.h 的 K&R(可能是 ANSI)描述。特别是尝试编译noweb:
gcc -ansi -pedantic -c -o notangle.o notangle.c
In file included from notangle.nw:28:
getline.h:4: error: conflicting types for ‘getline’
/usr/include/stdio.h:449: error: previous declaration of ‘getline’ was here
这是 Mac OS 10.7 中的一个错误,即使在针对 ANSI C89 标准进行编译时,也会在 stdio.h 中包含 getline
的声明?
【问题讨论】:
【参考方案1】:来自 n1570 的第 7.1.3 节第 2 段(这是 C1x 的草案):
没有保留其他标识符。
这部分意味着getline
不应由<stdio.h>
定义,因为根据规范它不是保留标识符。因此,如果您的库在 <stdio.h>
中定义了 getline
,那么它在技术上不符合 C 标准...
但是,您应该能够使用功能测试宏使 getline
在 <stdio.h>
中未定义。
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
这将只为您提供旧 POSIX 标准的定义。这不适用于某些 GNU C++ 实现,这对某些人来说是非常令人沮丧。
手册页的相关部分是(取自 glibc 手册页,抱歉...)
glibc 的功能测试宏要求(参见 feature_test_macros(7)): getline(), getdelim(): 从 glibc 2.10 开始: _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700 在 glibc 2.10 之前: _GNU_SOURCE手册页的这一部分告诉您需要将哪些宏定义为哪些值才能获得定义。我敢打赌,_POSIX_C_SOURCE
已经由您的编译器定义为 200809L
。
功能测试宏的想法是,如果您将宏(如_POSIX_C_SOURCE
、_BSD_SOURCE
、_XOPEN_SOURCE
等)定义为所需的值,则无需担心新的库函数会发生冲突与您现有的功能。还有_GNU_SOURCE
,如果您使用glibc,它会打开一切,但我建议不要考虑这个宏。
【讨论】:
您的回答使我能够通过定义_POSIX_C_SOURCE 1
再次编译ANSI C89 代码。 (该值应该只启用 ANSI C89/ISO C90 功能。)这些功能测试宏未记录在 Mac 手册页中的 getline
中,并且 feature_test_macros
手册页在 Mac 上不存在。没有你的回答,我不会找到他们。尽管您现在的回答没有回答我最初的问题(ANSI C 实现 允许 在其标准库中声明其他函数),但您的回答解决了我的实际问题。如果可以的话,我会投票两次!
标准中“没有保留其他标识符”的部分意味着该实现在技术上不允许在其标头中定义其他功能,但我并不太清楚。跨度>
【参考方案2】:
是的,只要它们是标准中的保留标识符之一,就允许兼容的实现定义其他标识符,包括函数。例如:
以下划线和大写字母或其他字母开头的所有标识符 下划线始终保留用于任何用途;
以下划线开头的所有标识符始终保留用作标识符 在普通名称空间和标记名称空间中都具有文件范围;
所有以is
、to
、str
、mem
或wcs
后跟小写字母开头的外部名称;
此外,还有一些名称仅在您包含某些标题时才保留;例如,如果您包含<errno.h>
,那么它可以定义任何以E
开头后跟数字或大写字母的宏。
但是,getline()
不是这样的保留名称,兼容的实现必须使其可供程序员自己使用。
【讨论】:
这几乎是我正在寻找的答案。您是否有参考证明您声称getline()
必须可供程序员自己使用?
@Bradford Larsen:C 标准(N1256 是由 TC1、TC2 和 TC3 更新的最终 C99 标准)。具体参见第 7.1.3 和 7.26 节。以上是关于符合 ANSI C 标准的实现能否在其标准库中包含附加功能?的主要内容,如果未能解决你的问题,请参考以下文章
是否有符合标准的方法来检测 C 标准库中的函数是否通过内部/内置实现?
sql = 和<>遵循的sql-92标准的设置SET ANSI_NULLS ON