“C89/C99说它们是宏。让它们开心。”

3

我在我可以访问的各种Linux系统中发现了这个有趣的代码,它在/usr/include/stdio.h中。

167 /* Standard streams.  */
168 extern struct _IO_FILE *stdin;      /* Standard input stream.  */
169 extern struct _IO_FILE *stdout;     /* Standard output stream.  */
170 extern struct _IO_FILE *stderr;     /* Standard error output stream.  */
171 /* C89/C99 say they're macros.  Make them happy.  */
172 #define stdin stdin
173 #define stdout stdout
174 #define stderr stderr

问题:定义一个本质上什么也不做的宏有什么意义?

8
所以您可以使用#ifdef作为示例。 - Ed Heal
10
可能是因为否则它将不符合标准。 - SilverWolf
3
你不理解你复制的评论的哪一部分? - Jens Gustedt
所以 #undef stdin 将会起作用。 - Hans Passant
1
你为什么发了两次代码? - M.M
1个回答

2
C11标准在7.21.1p3中定义了stdinstdoutstderr
  1. [在<stdio.h>中定义的宏]是:

    [...]

    • stderr
    • stdin
    • stdout

    它们是指向分别与标准错误、输入和输出流相关联的FILE对象的指向FILE的指针表达式。

    [...]

由于标准将它们定义为宏,因此它们必须是宏。但是这些表达式必须有一些定义,并且标准允许它们也可以用作变量名,但它们不必是实际的标识符。
Linux用户空间尝试大部分符合POSIX标准,同时符合C11标准。在POSIX中,要求这些符号是外部标识符。由于C11要求它们是宏,而POSIX要求它们是外部标识符,因此最简单的方法是定义与相应标识符完全相同名称的宏。
的确可以争论POSIX标准是否意味着它们也是具有外部链接的变量,但值得注意的是POSIX.1 2008标准在其系统接口卷中确实声明:

与一致性相关的唯一章节是SYNOPSIS、DESCRIPTION、RETURN VALUE和ERRORS章节。

而这些的SYNOPSIS章节确实说到:

SYNOPSIS

#include <stdio.h>

extern FILE *stderr, *stdin, *stdout;

我没有看到任何证据支持POSIX要求它们成为外部标识符的说法。所链接的概要只是粗糙的符号表示,而不是规范要求。 - R.. GitHub STOP HELPING ICE
@R.. 现在我正在阅读这个页面,我必须表示不同意。例如,措辞与 errno 不同;errno 在概要中没有任何特定的链接。 - Antti Haapala -- Слава Україні
我仍然认为这只是粗心,而不是有意的意图。 - R.. GitHub STOP HELPING ICE
答案中最令人满意的部分是您提到了POSIX的要求。我从未听说过它! - iBug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接