Mockup of my production code:
/* version 1 */
#include <stdio.h>
FILE** fout = &stdout;
int main() {
fprintf( *fout, "hello\n" );
}
Works fine under gcc, but reportedly fails to compile under mingw (lvalue required as unary '&' operand).
I have seen Is setting a FILE* equal to stdout portable?; I understand that
/* version 2 */
#include <stdio.h>
int main() {
FILE* fout = stdout;
fprintf( fout, "hello\n" );
}
would be perfectly valid. However, I need to preset a global variable. Unfortunately,
/* version 3 */
#include <stdio.h>
FILE* fout = stdout;
int main() {
fprintf( fout, "hello\n" );
}
is not suitable to replace version 1; it does not even compile under gcc (line 2: initializer element is not constant).
Any idea how to get stdout into a variable that is initialized before main() starts?
These three file pointers are automatically defined when a program executes and provide access to the keyboard and screen.
stdout stands for standard output stream and it is a stream which is available to your program by the operating system itself. It is already available to your program from the beginning together with stdin and stderr .
Stdout, also known as standard output, is the default file descriptor where a process can write output. In Unix-like operating systems, such as Linux, macOS X, and BSD, stdout is defined by the POSIX standard. Its default file descriptor number is 1.
Steps To Read A File:Open a file using the function fopen() and store the reference of the file in a FILE pointer. Read contents of the file using any of these functions fgetc(), fgets(), fscanf(), or fread(). File close the file using the function fclose().
In Linux (glibc), stdout
is defined like this:
extern struct _IO_FILE *stdout;
So, you can do whatever you need with that.
However, on MinGW, stdout
is defined like this, in stdio.h
:
#define stdout (&_iob[STDOUT_FILENO])
Alas, that's not something you can take the address of, and, as you discovered, it's not something you can use in a global initializer. :-(
The root of the problem is that the C standard says that these should be macros, which means any portable program should make no assumptions about what's inside. So, I'm afraid, there is no easy way to avoid doing reading stdout
programmatically. This sort of thing is why many libraries require a lib_initialize()
function that must be called before anything else.
C++ does permit constructors for global variables, and these are automatically called before main
, even for libraries. It is possible, with gcc
, to hack a C program to do the same, but that's an evil trick and I can't remember how to do it off the top of my head.
I'd just do this:
#include <stdio.h>
FILE* fout = NULL;
int my_library_function() {
if (!fout)
fout = stdout;
fprintf( fout, "hello\n" );
}
That isn't a big efficiency problem: you'd have to load fout
anyway, and a compare with zero is pretty cheap.
According to the C standard (7.21.1), stdout
is a macro which is an expression of type "pointer to FILE". It is not necessarily a global variable. It is not portable C to take its address --- it works in gcc but not in mingw, as you saw.
Use the second version of your code --- this is portable.
The third would be OK too if you moved the initialization of fout
inside main
:
/* version 3 */
#include <stdio.h>
FILE* fout;
int main() {
fout = stdout;
fprintf( fout, "hello\n" );
}
This initialization cannot be combined with the declaration of fout
, as stdout
is not (at least, not necessarily) a constant expression.
If you want to have a FILE **
pointer, use:
/* version 4 */
#include <stdio.h>
FILE* mystdout;
FILE** fout = &mystdout;
int main() {
mystdout = stdout;
fprintf( *fout, "hello\n" );
}
but again the initialization of mystdout
cannot be at its declaration, for the same reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With