我的生产代码的样机:
/* version 1 */
#include <stdio.h>
FILE** fout = &stdout;
int main() {
fprintf( *fout, "hello\n" );
}
在gcc下运行正常,但据报道无法在mingw下编译(lvalue需要作为一元'&amp;'操作数)。
我见过Is setting a FILE* equal to stdout portable?;我明白了
/* version 2 */
#include <stdio.h>
int main() {
FILE* fout = stdout;
fprintf( fout, "hello\n" );
}
完全有效。但是,我需要预设一个全局变量。不幸的是,
/* version 3 */
#include <stdio.h>
FILE* fout = stdout;
int main() {
fprintf( fout, "hello\n" );
}
不适合替换版本1;它甚至不在gcc下编译(第2行:初始化元素不是常量)。
知道如何将stdout转换为在main()启动之前初始化的变量吗?
答案 0 :(得分:6)
在Linux(glibc)中,stdout
的定义如下:
extern struct _IO_FILE *stdout;
所以,你可以随心所欲地做任何事情。
但是,在MinGW上,stdout
中的stdio.h
被定义为#define stdout (&_iob[STDOUT_FILENO])
:
stdout
唉,这不是你能得到的地址,而且,正如你所发现的,它不是你可以在全局初始化器中使用的东西。 : - (
问题的根源在于C标准说这些应该是宏,这意味着任何便携式程序都不应该对内部的内容做出任何假设。所以,我担心,没有简单的方法可以避免以编程方式阅读lib_initialize()
。这就是为什么许多库需要一个main
函数,必须先调用它。
C ++确实允许构造函数用于全局变量,并且这些变量在gcc
之前自动调用,即使对于库也是如此。使用#include <stdio.h>
FILE* fout = NULL;
int my_library_function() {
if (!fout)
fout = stdout;
fprintf( fout, "hello\n" );
}
,有可能破解C程序来做同样的事情,但这是一个邪恶的伎俩,我不记得如何做到这一点。
我只是这样做:
fout
这不是一个很大的效率问题:无论如何你必须加载{{1}},与零比较是非常便宜的。
答案 1 :(得分:5)
根据C standard(7.21.1),stdout
是一个宏,它是&#34;指向FILE&#34;的指针的表达式。它不一定是全局变量。如你所见,它不是便携式的C来获取它的地址---它可以在gcc中使用,但不能在mingw中使用。
使用代码的第二个版本---这是可移植的。
如果您在fout
内移动main
的初始化,第三个也可以。
/* version 3 */
#include <stdio.h>
FILE* fout;
int main() {
fout = stdout;
fprintf( fout, "hello\n" );
}
此初始化不能与fout
的声明结合使用,因为stdout
不是(至少,不一定)常量表达式。
如果您想要FILE **
指针,请使用:
/* version 4 */
#include <stdio.h>
FILE* mystdout;
FILE** fout = &mystdout;
int main() {
mystdout = stdout;
fprintf( *fout, "hello\n" );
}
但由于同样的原因,mystdout
的初始化不能在其声明中出现。
答案 2 :(得分:2)
我不认为这是一个非常好的主意,因为文件描述符通常不是可移植的。此外,它使库函数的实现非常低级,或者您将很难同步文件描述符和FILE
指针。
然而,正如@JoachimWuttke明确提出的那样,这是我之前评论中的想法:
/* version 5 */
#include <stdio.h>
#include <unistd.h>
int fdout = 1;
void use(FILE *fout)
{
fdout = fileno(fout);
}
void printing() {
const char msg[] = "hello\n";
write(fdout, msg, sizeof(msg)-1);
}
int main() {
printing(); // this one goes to stdout
FILE *f = fopen("output.txt", "wt");
use(f);
printing(); // this one goes to "output.txt"
printing(); // this one too
fclose(f);
use(stdout);
printing(); // this one goes to stdout too
return 0;
}