TITLE: pros/cons of stdio vs streams (Newsgroups: comp.lang.c++, 20 Jun 99) ZHN: (zhn@aol.com) : Folks what is the story with streams? Stdio is so easy to use : and yet C++ shuns it (or seemingly) KUEHL: Dietmar Kuehl There are some pros and cons to using iostreams. I'd rate using iostreams to be the better choice in most, if not all cases. Here are the pros and cons: + You can integrate I/O operations for you own data types when using iostreams. This is impossible for stdio. The possibility to use the same syntax for user defined types as for standard types is an important use of overloading and makes programs a lot easier to understand and maintain. + You can integrate new external representations into iostreams. For stdio, at least as defined in C90 (ISO 9899; I haven't checked the new standard on this issue), this is not really possible: You can do some of the stuff using vsprintf() and vsscanf() but normally C code is written to pass around FILE* and you can't define a new external representation accessed through a FILE*. In C++ the streams to write to are identified using istream& and ostream& and the corresponding streams can easily be extended by defining subclasses of streambuf (of the templatized basic_... of all of these if you want to). = Type-safety of stdio and iostreams can be implemented, at least for the built-in types to be basically equivalent: eg. gcc checks that format strings match the argument list, except when the format string is not passed as a string literal (see below). However, normally such a features is apparently not used: I have yet to see a non-trivial use of stdio in a program which is really deployed where there is not at least one wrong use of format strings (especially, floating point input is normally wrong, mainly because there are different format specifier for double input and output: '%lf' vs. '%f', respectively). Thus, although it is conceptually equivalent, it is often a pro for iostreams. = Internationalization support for both is basically identical (at least for standard C; I would consider C better than iostreams in this respect if positional argument a la X/Open were standard): In C you can get format strings used for internationlized messages from a file but you give up any kind of type safety. On the other hand, doing the same stuff using iostreams is quite clumsy. The approach which is easiest to use, namely the X/Open positional arguments, is unfortunatly not type safe. A type safe approach for both would probably be the bestthe solution (I have an idea for this but I havn't really implemented it in all its details; I discussed this issue three or four years ago in comp.lang.c++ with James Kanze, potentially you can find this thread on dejanews). = Currently, stdio and iostreams are basically equally hard to learn: stdio is definitely harder to learn (often even experts make subtle errors) but there is a lot and also good documentation. On the other hand, iostreams are fairly easy to learn and even hard to misuse (except people try to derive from istream and/or ostream) but there is only few and mostly outdated documentation. There will be two books appearing at Addison Wesley which will help to change the situation: Nicolai Josuttis' book on "The C++ Standard Library", Addison-Wesley (see ) will cover iostreams in quite some details (I have translated and partially rewritten this chapter of his book) will appear in July this year. And Angelika Langer and Klaus Kreft work on a book for Addison-Wesley which is devoted to locales and iostreams only (locales and iostreams are tied together in some areas and it does not make much sense to describe iostreams in details without also describing locales). In addition, I'm currently working on a documentation for my own iostream implementation which will be available hopefully relatively soon via WWW (a revision of this article might very well become a part of this documentation). - I rate this one as a cons for using iostreams although it is not yet clear whether this is really a cons, actually I don't think so: All current implementation of iostreams are less efficient than stdio, eg. in terms of runtime, code size, compile time, and object size. The major goal of my implementation is to show that this is a quality of implementation issue, ie. that the lack of efficiency is not inherent to the definition as some people claim but only the result of the choice made during the implementation. I can't yet prove that iostreams are more efficient, mainly because I'm busy getting a complete implementation and documentation ready, rather than optimizing the code. However, I'm still convinced that I can prove that iostreams are more efficient or at least only slightly less efficient than stdio. There are some aspects of iostreams which don't have a counterpart in stdio (eg. the possibility to replace the way built-in types are process using user defined facets in locale objects) but there are correspondingly some things you can't do with iostreams (eg. writing only partial strings when passing the string as 'char cosnt*', if I remember correctly). I think I have covered the most important differences above. If there are more, fell free to correct me. I consider the pros of iostream to overweight the one cons of using them, especially since often I/O using stdio/iostreams is not used that heavily and often not really time critical. Where it is, it is often easy to replace the iostream stuff by equivalent stdio stuff. Of course, both this judgement as well as what are pros and cons for one or the approach are not objective: This is my personal view and I hope I have made clear why I made the corresponding judgement. For you own application, you have to judge yourself. ZHN: : A few questions to answer would be the history of stdio and streams, KUEHL: Well, stdio was introduced by Kernighan an Richie with the original version of C and they stayed, as far as I can tell, mainly unchanged since then. There were some additions like the variable argument versions of the functions, the wide character version, etc. but the concepts stayed the same (however, I'm not an expert on this). iostream got through two major rewrites, where the second made a big technical change but did not touch the basic concepts: I can't tell who designed/implemented the original iostreams but it was Jerry Schwartz who introduced the separation of stream buffers relatively early in the history of C++ but after the original release from Stroustrup. During standardization many of the functions got renamed but the biggest change was the introduction of templates to provide different character types. This basically required the introduction of locales to cope with certain aspect which were relatively hard coded in iostreams but which now needed to be factored out (eg. numeric formatting). ZHN: : whether or not it is -really-safe to use them both together KUEHL: It is absolutely save to use them together, at least according to the standard (current implementations might be in disagreement). Actually, stdio and iostreams only interfere with respect to the standard streams (stdin, stdout, and stderr vs. cin, cout, cerr, clog, wcin, wcout, wcerr, and wclolg; all are namespace std, of course): If you write alternatingly from stdio and from iostreams to these streams, there can be a problem. However, by default (that is unless you call 'std::ios_base::sync_with_stdio(false)') the stdio streams are synchronized with the corresponding iostreams which basically means that these iostreams are not buffered (this it not necessarily really true but a close approximation). There is no standard way to use any other stream from both stdio and iostream simulatenously and thus there is no issue of conflicting. However, it is easily possible to create iostream classes to cooperate with FILE*. ZHN: : ,and how are they related(if any relation exists.) KUEHL: The only relation between stdio and iostreams mandated by the standard is that - stdin and cin/wcin read from the same source - stdout and cout/wcin, - stderr and cerr/wcerr, - stderr and clog/wclog write to the same destination. Potentially, the corresponding streams are in some form synchronized. ZHN: : Another great help to many of us who were not trained in C++ is where : we might be able to find some good references to streams. KUEHL: As I mentioned above, there will some information be appearing relatively soon, partially in form of books, partially in form of web pages. There is already some information available, eg. at . However, I don't really like this documentation. In another reply to this article, my pages at my home page (see trailor) where mentioned: There is some information but it is neither up to date nor in any ways complete. It mostly describes creation of new external representations, ie. stream buffers. I hope to be soon in a position to make a complete documentation available. (Private correspondence) TRIBBLE: David R Tribble There are also some of us old die-hards who find the old printf format specifiers much simpler and less verbose than the equivalent iostream formatters. For example, try this with iostreams and see which is more succint: printf("%08X: %06o, %.*s\n", addr, strlen(str), 80, str); It must be remembered that it's a two-edged sword we're dealing with here: type safety on one side and readability/maintainability on the other. I've always wondered why no one came up with type-safe equivalents to the printf format specifiers for C++. For example: std::ostream::print_d(int x, int width=dfl, int prec=dfl); std::ostream::print_x(unsigned x, int width=dfl, int prec=dfl); std::ostream::print_f(double x, int width=dfl, int prec=dfl); std::ostream::print_s(const char *x, int width=dfl, int prec=dfl); etc.