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

时间:2013-08-29 08:12:55

标签: c mingw

我的生产代码的样机:

/* 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()启动之前初始化的变量吗?

3 个答案:

答案 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;
}