如何将FILE**变量设置为stdout?

Joa*_*m W 7 c mingw

我的生产代码的样机:

/* version 1 */
#include <stdio.h>
FILE** fout = &stdout;
int main() {
     fprintf( *fout, "hello\n" );
}
Run Code Online (Sandbox Code Playgroud)

在gcc下正常工作,但据报道无法在mingw下编译(lvalue需要作为一元'&'操作数).

我看到设置FILE*等于stdout portable吗?; 我明白那个

/* version 2 */
#include <stdio.h>
int main() {
    FILE* fout = stdout;
    fprintf( fout, "hello\n" );
}
Run Code Online (Sandbox Code Playgroud)

完全有效.但是,我需要预设一个全局变量.不幸,

/* version 3 */
#include <stdio.h>
FILE* fout = stdout;
int main() {
    fprintf( fout, "hello\n" );
}
Run Code Online (Sandbox Code Playgroud)

不适合替换版本1; 它甚至不在gcc下编译(第2行:初始化元素不是常量).

知道如何将stdout变为在main()启动之前初始化的变量吗?

ams*_*ams 6

在Linux(glibc)中,stdout定义如下:

extern struct _IO_FILE *stdout;
Run Code Online (Sandbox Code Playgroud)

所以,你可以随心所欲地做任何事情.

但是,在MinGW上,stdout定义如下stdio.h:

#define stdout  (&_iob[STDOUT_FILENO])
Run Code Online (Sandbox Code Playgroud)

唉,这不是你能得到的地址,而且,正如你所发现的,它不是你可以在全局初始化器中使用的东西.:-(

问题的根源是C标准说这些应该是宏,这意味着任何便携式程序都不应该对内部的内容做出任何假设.所以,我担心,没有简单的方法可以避免以stdout编程方式进行阅读.这就是为什么许多库需要一个lib_initialize()必须先调用的函数.

C++确实允许构造函数用于全局变量,并且这些变量在之前自动调用main,即使对于库也是如此.这是可能的,有gcc,破解一个C程序做同样的,但是这是一个邪恶的把戏,我不记得如何做到这一点从我的头顶.

我只是这样做:

#include <stdio.h>
FILE* fout = NULL;

int my_library_function() {
    if (!fout)
      fout = stdout;
    fprintf( fout, "hello\n" );
}
Run Code Online (Sandbox Code Playgroud)

这不是一个很大的效率问题:fout无论如何你必须加载,与零比较是相当便宜的.


nic*_*kie 5

根据C标准(7.21.1),stdout是一个宏,它是"指向FILE的指针"类型的表达式.它不一定是全局变量.如你所见,它不是便携式的C来获取它的地址---它在gcc中工作但在mingw中不起作用.

使用代码的第二个版本---这是可移植的.

如果移动内部的初始化,第三个也可以:foutmain

/* version 3 */
#include <stdio.h>
FILE* fout;
int main() {
    fout = stdout;
    fprintf( fout, "hello\n" );
}
Run Code Online (Sandbox Code Playgroud)

这种初始化不能与声明相结合fout,因为stdout它不是(至少不一定是)常量表达式.

如果你想要一个FILE **指针,请使用:

/* version 4 */
#include <stdio.h>
FILE* mystdout;
FILE** fout = &mystdout;
int main() {
     mystdout = stdout;
     fprintf( *fout, "hello\n" );
}
Run Code Online (Sandbox Code Playgroud)

mystdout由于同样的原因,初始化不能在其声明中.