C++ Streams vs. C-style IO?
Solution 1
This is an heated topic.
Some people prefer to use the C++ IO since they are type-safe (you can't have divergence between the type of the object and the type specified in the format string), and flow more naturally with the rest of the C++ way of coding.
However, there is also arguments for C IO functions (my personal favorites). Some of them are:
- They integrate more easily with localisation, as the whole string to localise is not broken up in smaller strings, and with some implementation the localizer can reorder the order of the inserted value, move them in the string, ...
- You can directly see the format of the text that will be written (this can be really hard with stream operators).
- As there is no inlining, and only one instance of the
printf
function, the generated code is smaller (this can be important in embedded environment). - Faster than C++ function in some implementation.
Personally, I wouldn't consider it bad practice to use C stream in C++ code. Some organisations even recommend to use them over C++ stream. What I would consider bad style is to use both in the same project. Consistency is the key here I think.
As other have noted, in a relatively large project, you would probably not use them directly, but you would use a set of wrapper function (or classes), that would best fit your coding standard, and your needs (localisation, type safety, ...). You can use one or the other IO interface to implement this higher level interface, but you'll probably only use one.
Edit: adding some information about the advantage of printf
formatting function family relating to the localisation. Please note that those information are only valid for some implementation.
You can use %m$
instead of %
to reference parameter by index instead of referencing them sequentially. This can be used to reorder values in the formatted string. The following program will write Hello World!
on the standard output.
#include <stdio.h>
int main() {
printf("%2$s %1$s\n", "World!", "Hello");
return 0;
}
Consider translating this C++ code:
if (nb_files_deleted == 1)
stream << "One file ";
else
stream << nb_file_deleted << " files ";
stream << removed from directory \"" << directory << "\"\n";
This can be really hard. With printf
(and a library like gettext
to handle the localization), the code is not mixed with the string. We can thus pass the string to the localization team, and won't have to update the code if there are special case in some language (in some language, if count of object is 0, you use a plural form, in other language, there are three forms one for singular, one when there is two object and a plural form, ...).
printf (ngettext ("One file removed from directory \"%2$s\"",
"%1$d files removed from directory \"%2$s\"",
n),
n, dir);
Solution 2
printf
and friends are hideously unsafe compared to <iostream>
, and cannot be extended, plus of course fopen
and friends have no RAII, which means that unless you've proved with a profiler that you definitely need the performance difference (that you've proved exists on your platform and in your code), you'd have to be an idiot to printf
.
Edit: Localization is an interesting thing that I hadn't considered. I've never localized any code and cannot comment on the relative localizational ability of printf
and <iostream>
Solution 3
For a small hobby project I would probably go with the more type-safe C++ io streams.
Funny enough, I've never seen a non-trivial real-life project that uses either of them. In all cases we used some abstractions built on top of the native OS API for IO.
Solution 4
Advantages
- Type safety: the argument types of C++ streaming operations are checked at compile time, while
printf
arguments are passed through...
causing undefined behaviour if they do not match the formatting. - Resource management: C++ stream objects have destructors to close file handles, free buffers, and what have you. C streams require you to remember to call
fclose
.
Disadvantages
- Performance: this depends on the implementation, of course, but I've found formatting with C++ streams to be considerably slower than the equivalent
printf
formatting.
Solution 5
Nothing can be considered bad practice if it has a definite purpose. I mean, if IO is the bottleneck of the program, then yes, C-style IO works faster than C++ IO. But if it is not, I would go with C++ stream approach. Cuz it's cuter :)
Comments
-
gablin almost 2 years
I was coding some C++ for a small hobby project when I noticed that I'm using C-style operations to access IO (
printf
,fopen
, etc.).Is it considered "bad practice" to involve C functions in C++ projects? What are the advantages of using streams over C-style IO access?
-
R. Martinho Fernandes about 13 years+1 for the localization bullet. But how do you reorder the values in printf?
-
Sylvain Defresne about 13 yearsI've updated my post to explain how you can reorder the values in
printf
(hint :%m$
). -
gablin about 13 yearsIn that case I need not worry, since encapsulating IO code into a class is exactly what I've done. =)
-
David Thornley about 13 yearsI haven't found any reference to rearranging orders in
printf
in any reasonably official source I have handy. Where are you getting this%2$
idea? -
UncleBens about 13 yearsAFAIK, basic localization is done by extracting string literals from the program (that are surrounded by a call to a translation function) and having people translate those strings. Imagine having to translate and construct meaningful sentences out of the sentence fragments that you get with cout. - Boost.Format can help you out with this, though.
-
Sylvain Defresne about 13 yearsThis may be a GNU extension, I found it in the manpage of
printf
on my linux box. This does seems to works on Mac OS X though. I don't know if this is required by the C standard. -
David Thornley about 13 years@Sylvain Defresne: It is not required by the C standard. I don't think it's actually allowed by the C standard, although I'm not going to bother looking that up. It may be a Gnu extension (XCode for Mac OSX uses gcc, although they may be moving away), but there is no hint in the question title, body, or tags of using a specific compiler.
-
Triskeldeian almost 8 yearsActually it's not true that Google C++ Style Guide for example recommends using C style I/O over C++ style I/O. It says that is better to use alternative libraries for more complex usages but otherwise use the streams when necessary. It doesn't even ever mention the C I/O system
-
vitaut almost 8 yearsThey must have changed that. I've updated the answer, thanks!