C99将这三个定义为宏,它们"是‘’指向文件的指针‘’类型的表达式,分别指向与标准错误流、输入流和输出流相关联的文件对象".

鉴于此,这些表达式可能是const,也可能不是const(即,指针可能被写入以重定向到另一文件或流,也可能不被写入以重定向到另一文件或流);并且它们可能具有内部或外部链接(即,在两个单独编译的C文件之间写入重定向到另一文件或流可能不会持久存在).因此,try 从C文件内重定向stdout可能具有意外行为.

(注:在GCC-9.4.0中,它们似乎是映射到外部链接的非const变量的宏,具有相同的名称,并附有注释:/* C89/C99 say they're macros. Make them happy. */.)

有没有人能解释一下这是否有官方的原因,或者可以安全地认为这是原始标准中的另一个"疏忽",应该避免从C代码内部重定向流,以保持可移植?

推荐答案

这些表达式可以是也可以不是const(即,指针可以被写入也可以不被写入以重定向到另一文件或流);

对,是这样.

它们可以有内部联系或外部联系

宏标识符本身有100个链接,只有当它们的替换文本是标识符时,链接对它们才是有意义的.

[.]因此,try 从C文件中重定向stdout可能具有意外行为.

不是的.Attempting to assign a new value to 100可能会失败或产生意外的结果.但是,是的,您已经发现执行这样的分配并不是更改stdout所连接的目的地的可靠方式.

有没有人能解释一下这是否有官方的原因

有一张official rationale document for C99.它没有解决这一点.

或者可以认为这是原始标准中的又一次"疏忽"?

我不明白你的意思.我认为可以很安全地假设stdinstdoutstderr被故意指定为宏.它直接来自于它们的规范,您不能为了任何目的而依赖于分配给它们.

我推断,指定它们是为了允许实现的灵活性.例如,它们可以实现为函数调用或表查找.它们不必是对象标识符.

为了保持程序的可移植性,应该避免从C代码内部重定向数据流?

不是的.为了严格遵守C语言规范,必须避免Assigning tostdinstdoutstderr(这大致等同于"保持事物的可移植性").如果您想要将一个标准流与不同的目的地相关联,那么这就是freopen()函数的主要目的,该函数在标准C的所有版本中都可用.

C++相关问答推荐

如何在C中通过转换为char * 来访问float的字节表示?

在x86汇编中,为什么当分子来自RDRAND时DIV会引发异常?

如何确保内存分配在地址附近?

Mise()在虚拟内存中做什么?

在C语言中使用scanf()时我无法理解的警告

自定义应用程序上的日志(log)轮换问题

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

在列表中插入Int指针(C)

非常大的数组的大小

将宏值传递给ARM链接器,该链接器将变量放置在特定位置

试图从CSV文件中获取双精度值,但在C++中始终为空

解决S随机内存分配问题,实现跨进程高效数据共享

将返回的char*设置为S在函数中定义的字符串文字可能会产生什么问题?

<;unistd.h>;和<;sys/unistd.h>;之间有什么区别?

C整型和_泛型.哪些类型是兼容的?

为什么二进制文件的大小不会随着静态数据的大小而增加?

向左移位3如何得到以字节为单位的位数?

Tcl_GetDoubleFromObj在列表的迭代中是一个缺点

无法在线程内用 C 打印?

运行以下 C 程序时出现分段错误