C99将这三个定义为宏,它们是“指向与标准错误、输入和输出流相关联的FILE对象的类型为‘指向FILE的指针’的表达式”。
鉴于此,这些表达式可能是const
(即指针可能被写入以重定向到另一个文件或流),也可能具有内部或外部链接(即写入以重定向到另一个文件或流可能不会在两个单独编译的C文件之间持续)。因此,在C文件中尝试重定向stdout
可能会产生意外行为。
(注意:在gcc-9.4.0中,它们似乎是映射到具有相同名称的具有外部链接的非const
变量的宏,并附带注释:/* C89/C99 say they're macros. Make them happy. */
。)
是否有官方原因导致这种情况还是可以安全地假设这是原始标准中的另一个“疏忽”,并且应该避免在C代码中重定向流以保持可移植性?
#define stdout stdout
是可以的。原因很可能是历史原因。很长一段时间(197x-200x),大多数系统都使用像#define stdin _ios[0]
(或可能是&_ios[0]
—— 名称在“保留给系统”的命名空间中)这样的宏。这意味着它们可以在全局范围内的文件流初始化器中使用(static FILE *err = stderr;
)。GNU C库在“oughts”某个时候更改了它们的定义,现在不再可能这样做。 - Jonathan Lefflerstdin
等可能也是对象标识符,如果是这样,那么这些标识符将具有内部或外部链接。 - John Bollingerfreopen
来重定向标准流。 - Ian Abbott