符合 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】:

是的,只要它们是标准中的保留标识符之一,就允许兼容的实现定义其他标识符,包括函数。例如:

以下划线和大写字母或其他字母开头的所有标识符 下划线始终保留用于任何用途;

以下划线开头的所有标识符始终保留用作标识符 在普通名称空间和标记名称空间中都具有文件范围;

所有以istostrmemwcs 后跟小写字母开头的外部名称;

此外,还有一些名称仅在您包含某些标题时才保留;例如,如果您包含&lt;errno.h&gt;,那么它可以定义任何以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

除了标准库中包含的工具之外,Linux 上的 Python 还存在哪些分析工具?

在 CUDA NVRTC 代码中包含 C 标准头文件

C语言标准库函数strcpy与strcmp的简单实现

前言-绪论-导读