2

I ran the following program under cygwin/gcc 4.7.3 and VS 2010.

#include <stdio.h>

int main()
{
   printf("This is a test.\n");
   return 0;
}

The output of running the program under those environments showed that VS 2010 treats stdout as a text stream.

Questions:

  1. Is stdout required to be a text stream?
  2. Is an implementation free to choose whether it uses a text stream or a binary stream for stdout?

EDIT

The question of how to write to stdout in binary mode is different from whether stdout is required to be a text stream or a binary stream.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Are you trying to write binary data to `stdout`? If so, why? Why not just open a file in binary mode and write to it? – Keith Thompson Mar 30 '15 at 20:26
  • @KeithThompson, no, I wasn't doing that. I find myself piping the `stdout` of Windows programs for further processing in cygwin and wanted to be clear on what to expect. – R Sahu Mar 30 '15 at 20:47

3 Answers3

4

stdout is required to be a text stream, as are stdin and stderr. From the C99 standard, 7.19.3 (7):

At program startup, three text streams are predefined and need not be opened explicitly -- standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). (...)

(Emphasis mine)1

For reference: in the 2011 revision of the C standard, this has been moved unchanged to 7.21.3 (7).2

Note that this means that these three streams are text streams at startup. Some platforms provide ways to switch the mode later, such as _setmode under Windows.

1 Just for the sake of completeness: that stdin, stdout, and stderr refer to these streams is defined in 7.19.1 (3).
2 The section mentioned in footnote 1 is moved to 7.21.1 (3) in C11.

Wintermute
  • 42,983
  • 5
  • 77
  • 80
  • May I ask from which website you have this ? – Rizier123 Mar 30 '15 at 19:12
  • Then what about software like sox (a comandline audio utility) which supports sending audio file out stdout? – Algorithmic Canary Mar 30 '15 at 19:12
  • 1
    That said, it's not that abnormal (at least on *nix type systems) to pass binary data through stdin/stdout - particulatly in command pipelines started by the shell for archiving and/or compression/decompression. – mah Mar 30 '15 at 19:13
  • 1
    I have it directly from my copy of the C99 standard. For binary output: On some platforms this just works, others allow mode switching (such as _setmode() under Windows). There are ways, but the C standard does not provide them. – Wintermute Mar 30 '15 at 19:16
  • 1
    Note that on POSIX systems, there is no difference between text and binary streams. I'm still searching POSIX for the place where this is defined explicitly and will come back with a link; in the meantine: the fact is mentioned in passing [here](https://www.gnu.org/software/libc/manual/html_node/Binary-Streams.html) and implicitly in the POSIX spec of [`fopen`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html) in that there is no difference between the `open` flag equvalents of `"r"` and `"rb"` (and so forth). – Wintermute Mar 30 '15 at 19:30
  • ISO C99 (not C90) does provide a way: `freopen()` with a null pointer as filename. But it's implementation-defined. – cremno Mar 30 '15 at 19:48
  • @cremno Ah, that is a good point. Do you happen to know if that works under Windows? C99 support has not been a priority there, heavens know. EDIT: According to the [MSDN](https://msdn.microsoft.com/en-us/library/wk2h68td.aspx), no. Blast. – Wintermute Mar 30 '15 at 19:56
  • @Wintermute - see here, [2008.1](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html), it states that using 'b' has no effect -- as POSIX has only one type of stream. – teppic Mar 30 '15 at 20:00
  • Not yet. Even VS2015 CTP 6, which has much better (mostly complete) support of the C99 standard library, doesn't implement that feature, so let's hope [my bug report](https://connect.microsoft.com/VisualStudio/Feedback/Details/1214245) gets fixed before its release. – cremno Mar 30 '15 at 20:18
  • @teppic Yeah, I found that one, but it's only implicit there. I have found an explicit mention in [this procedural document](http://www.opengroup.org/austin/aardvark/d6/xshbug.txt) (Enhancement Request 8). The wording of it makes clear that the distinction between text and binary streams that C has is removed in POSIX by stripping all mention of it from the parts that POSIX copies from C, so my hope of finding an explicit "we don't make a difference between text and binary streams" in POSIX itself is dwindling. It has to be enough that POSIX can't be implemented while making the distinction. – Wintermute Mar 30 '15 at 20:26
  • @Wintermute I'd say it's pretty much that POSIX defines only a stream (it doesn't define binary or text streams), so there's no reason to be explicit. Text and binary streams are part of the C standard, not POSIX, so it just states that the b option is there for compliance only. – teppic Mar 30 '15 at 20:30
  • @teppic I suppose that's true, and in any case you'll not hear me arguing that POSIX compliance is possible where binary streams behave differently from text streams. It's just that when I'm making an argument on the Internet, I feel better when I have somewhere to point that's so explicit that it cannot possibly be argued against (by a sane person). – Wintermute Mar 30 '15 at 20:41
  • 1
    @Wintermute Well, the POSIX standard is there to define the system API, and of course the C library is implemented in POSIX calls. If the underlying system has no concept of binary/text streams, it doesn't make sense to define them. You can write POSIX compliant I/O code that doesn't use any C standard I/O, and these two things will never come up. – teppic Mar 30 '15 at 20:48
2

stdout is not required to be a text stream - as in the case of redirection.

So I guess the answer is 'yes' to your second question.

Check this out - What is the simplest way to write to stdout in binary mode?

Community
  • 1
  • 1
abRao
  • 2,787
  • 1
  • 25
  • 37
  • 1
    If by redirection you mean `program_name > file_name`, the C standard still says that `stdout` is a text stream at program startup. – Keith Thompson Mar 30 '15 at 19:36
  • yes you are right - at program startup it is text stream - I thought the question was 'is it required'. By default stdout is a text stream. Similar to fopen which by default opens a text stream and not binary. So does that mean fopen is required to treat/handle text stream - the answer is no. Needless to add that is how I interpreted the "required" in the question - maybe R Sahu meant "by default" in my parlance. – abRao Mar 30 '15 at 20:22
0

You can stream raw bytes to stdout using fwrite() — or write(), with the equivalent file descriptor for stdout. This is how compression tools work, for instance.

Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
  • 2
    No, `fwrite()` doesn't treat a text stream as binary. On systems where it matters (Windows), using `fwrite()` to write a `'\n'` character to `stdout` will still cause `"\r\n"` to be written to the file. – Keith Thompson Mar 30 '15 at 19:37
  • So are you saying that `fwrite()` cannot be used to write a buffer of raw bytes ("binary") to standard output? – Alex Reynolds Mar 30 '15 at 19:39
  • 2
    Not if `stdout` is currently in text mode (as it is by default), and not if the system makes a meaningful distinction between text and binary. Unix-like systems do not; text and binary files and modes are treated identically. On Windows, in text mode `'\n'` is translated to a CR-LF pair on ouput, and versa on input, and Ctrl-Z marks the end of the file; in binary mode those translations don't occur. Other systems might have other characteristics. – Keith Thompson Mar 30 '15 at 19:41
  • It's my understanding that Cygwin is not Windows (though not entirely POSIX-compliant). – Alex Reynolds Mar 30 '15 at 19:43
  • Cygwin provides a Unix-like environment under Windows. I *think* it can optionally be configured to use Windows-style line endings, though I've never done so, and the default is to use Unix-style line endings. Still, for the sake of style and portability its best to write binary data only to a binary stream. – Keith Thompson Mar 30 '15 at 19:45
  • 1
    Using non-POSIX Windows endings in a POSIX compatibility library for Windows would make me very sad. – teppic Mar 30 '15 at 20:15
  • @teppic Read it and weep: https://cygwin.com/cygwin-ug-net/using-textbinary.html (Seriously though, they're doing the best they can under the circumstances) – Wintermute Apr 01 '15 at 10:26