- "In defense of printf" - 22 Updates
- I don't understand this syntax for typedef and structs - 3 Updates
Lynn McGuire <lmc@winsim.com>: Dec 15 06:00PM -0600 "In defense of printf" http://kennykerr.ca/2014/12/08/in-defense-of-printf/ "Folks seem to enjoy pointing out that I use printf in many of my examples of "modern C++", as if printf is not really proper C++. Apparently, I should be using cout. The trouble is that cout isn't exactly modern either. It has been around for as long as I can remember and it certainly doesn't exemplify modern C++ as envisioned by C++11 and beyond. The oldest C++ textbook on my shelf was printed in 1993 and covers cout. I even posed the question to some C++ historians and they were able to date it back as far as 1989. Therefore, the argument that printf is old and cout is modern doesn't fly. A truly modern C++ solution would also not be substantially slower than hand-written code. Most printf implementations today provide adequate type checking both at compile time and run time. Visual C++ even provides secure versions that make it quite straightforward to write defensive code quite easily with printf. Go ahead and use cout if you prefer, but don't claim it's the modern replacement for printf." I have tried to cut my printf usage to very basic functions that get called a lot so they are fairly well tested. Printf usege in an error message is a bad idea, IMHO. Lynn |
william.bell@frog.za.net: Dec 15 10:45PM -0800 I agree with you. See boost's format library. http://www.boost.org/doc/libs/1_57_0/libs/format/ The format library provides a class for formatting arguments according to a format-string, as does printf, but with two major differences : format sends the arguments to an internal stream, and so is entirely type-safe and naturally supports all user-defined types. The ellipsis (...) can not be used correctly in the strongly typed context of format, and thus the function call with arbitrary arguments is replaced by successive calls to an argument feeding operator% |
scott@slp53.sl.home (Scott Lurndal): Dec 16 03:19PM >printf. Go ahead and use cout if you prefer, but don't claim it's the modern replacement for printf." >I have tried to cut my printf usage to very basic functions that get called a lot so they are fairly well tested. Printf usege in an >error message is a bad idea, IMHO. Of course, other opinions may differ. [sn/f]printf is far more readable, far more usable and far more efficient than output streams. |
Christopher Pisz <nospam@notanaddress.com>: Dec 16 10:27AM -0600 On 12/15/2014 6:00 PM, Lynn McGuire wrote: > and it certainly doesn't exemplify modern C++ as envisioned by C++11 and > beyond. The oldest C++ textbook on my shelf was printed in 1993 and > covers cout. 1992 was when it made it in officially if memory serves. I even posed the question to some C++ historians and they > were able to date it back as far as 1989. Perhaps before the library became standard. Therefore, the argument that > printf is old and cout is modern doesn't fly. Philosophically unsound argument. Your premise is incorrect, but even if it was your premises are the wrong ones. printf is C plain and simple. Hence why you have to include the cstdio header it requires! That's "C standard input output"...derp or in the case of those who refuse to change, stdio.h A truly modern C++ > solution would also not be substantially slower than hand-written code. Says who? What exactly is substantial? > Most printf implementations today provide adequate type checking both at > compile time and run time. Bullshit. Spent 6 months tracking down problems that boiled down to unsafe usage of printf just last year. To my surprise (not really), it was another stubborn C programmer that littered the code with printf and sprintf, because he refused to change his ways. Visual C++ even provides secure versions that > make it quite straightforward to write defensive code quite easily with > printf. Let's use non portable code to fix the problem. Go ahead and use cout if you prefer, but don't claim it's the > modern replacement for printf." It is, get over it. Why are C programmers so stubborn? They'll argue to the death over the most trivial things. |
Christopher Pisz <nospam@notanaddress.com>: Dec 16 10:30AM -0600 On 12/16/2014 9:19 AM, Scott Lurndal wrote: > Lynn McGuire <lmc@winsim.com> writes: SNIP > Of course, other opinions may differ. [sn/f]printf is far more readable, far more usable > and far more efficient than output streams. I don't mind if C programmers unite, but don't do it pretending to be C++ programmers and don't outright lie. Far more readable? Far more usable? Are you kidding me? We can argue efficiency maybe, but the former two have absolutely no basis. |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 16 05:22PM On Tue, 2014-12-16, Lynn McGuire wrote: > http://kennykerr.ca/2014/12/08/in-defense-of-printf/ >> Therefore, the argument that printf is old and cout is modern doesn?t >> fly. Printf doesn't work with user-defined types, and user-defined types are central to writing good C++. /That's/ why people don't like printf. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Paavo Helde <myfirstname@osa.pri.ee>: Dec 16 11:29AM -0600 > I have tried to cut my printf usage to very basic functions that get > called a lot so they are fairly well tested. Printf usege in an error > message is a bad idea, IMHO. In general, I also like the printf style better than C++ streams. Almost all my error messages are formatted printf-style. However, I am using a typesafe implementation in C++ (similar to Boost.Format) to avoid all the drawbacks of printf(). This way it is even slower than with streams as lots of run-time checks and conversions are involved. So in general it is good *only* for formatting error messages ;-) Cheers Paavo |
Paavo Helde <myfirstname@osa.pri.ee>: Dec 16 11:53AM -0600 Jorgen Grahn <grahn+nntp@snipabacken.se> wrote in > Printf doesn't work with user-defined types, and user-defined types > are central to writing good C++. /That's/ why people don't like > printf. On the other hand, the stream version assumes that you always want to stream your objects in the same way to text. In my experience, I always need multiple ways for representing the object textually, e.g. as a description, as an expression, as some kind of XML serialization, as a MD5 hash, etc. While there are probably ways to define custom manipulators for the stream to get different texts, it seems to me way easier to just add different member functions for the class returning the needed strings. And if one has already got those member functions returning strings, there is nothing prohibiting using them in printf as well. So the user-defined types can be used with printf style without any problems. To have type safety and avoid littering the code with c_str() calls one should of course use Boost.Format or equivalent instead of plain printf(). Cheers Paavo |
legalize+jeeves@mail.xmission.com (Richard): Dec 16 05:56PM [Please do not mail me a copy of your followup] Jorgen Grahn <grahn+nntp@snipabacken.se> spake the secret code >Printf doesn't work with user-defined types, and user-defined types >are central to writing good C++. /That's/ why people don't like >printf. Plus it isn't type-safe and it doesn't work well with localization. If you prefer the conciseness of a printf style format string, then use Boost.Format. There are legitimate complaints about the speed of iostreams vs. stdio and there are cases where this difference really matters. In the tests I've seen, the comparison was between printf and the stream insertion operator. The benchmark was pretty clear about the results. What I never gained from such tests is *why* the stream insertion operator was slower. I'm not yet convinced that the stream insertion is *intrinsically* slower than printf, but I am convinced that specific implementations are slower. The compiler has access to much more code optimization opportunities with stream insertion than with printf, so perhaps as the compilers get better, stream insertion will simply outperform printf someday. It is already the case that libraries like Boost.Spirit, which are heavily based in C++ templates, can outperform C library functions like itoa and atoi. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
scott@slp53.sl.home (Scott Lurndal): Dec 16 06:31PM >> and far more efficient than output streams. >I don't mind if C programmers unite, but don't do it pretending to be >C++ programmers and don't outright lie. I'm sorry, I don't understand your comment. I've been programming, for pay in C++ since 1989. Very large codebases (operating systems, hypervisors, simulators and large X.509 suites). >Far more readable? Far more usable? Are you kidding me? Yes, far more readable. Consider: lp->log("%-132.132s\n", start); or bytecount = snprintf(tbp, tbsize, " [%6.6llx:%6.6llu]", gethex(p_operands[1]->getaddress(), 6), getdigits(p_operands[1]->getaddress()+6, 6)); The equivalent output stream version resembles COBOL in terms of unnecessary verbosity (although in reality, COBOL picture clauses are much more similar to *printf than cout). I find your insistence on the "purity" of C++ to be completely silly. One uses a language to accomplish a task. As the *printf functions have been legitimately used in C++ code for almost three decades, there seems little reason to use the less readable and more verbose output streams particularly given the performance constraints on most of the C++ software that I'm responsible for. |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 16 06:47PM On Tue, 2014-12-16, Paavo Helde wrote: > stream your objects in the same way to text. In my experience, I always > need multiple ways for representing the object textually, e.g. as a > description, as an expression, as some kind of XML serialization, I rarely need that, but yes, it happens often enough to be a problem. > as a MD5 hash, etc. That's not a valid case IMHO -- you should have a way to hash your object into a class MD5Hash, or something. /That/ one can be printed. > different member functions for the class returning the needed strings. > And if one has already got those member functions returning strings, > there is nothing prohibiting using them in printf as well. Simpler IMO to just provide member functions: ostream& put_form1(std::ostream&); ostream& put_form2(std::ostream&); ostream& put_form3(std::ostream&); But that's because my "smaller" types are also ostream-compatible rather than printf- or to_string-compatible. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
legalize+jeeves@mail.xmission.com (Richard): Dec 16 06:55PM [Please do not mail me a copy of your followup] (Richard) legalize+jeeves@mail.xmission.com spake the secret code >>are central to writing good C++. /That's/ why people don't like >>printf. >Plus it isn't type-safe and it doesn't work well with localization. And I almost forgot: it's a long-standing source of hard crash bugs, which is why the compilers are doing their best these days to analyze such things and alert you to the sources of error. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Ian Collins <ian-news@hotmail.com>: Dec 17 08:13AM +1300 Scott Lurndal wrote: > The equivalent output stream version resembles COBOL in > terms of unnecessary verbosity (although in reality, COBOL > picture clauses are much more similar to *printf than cout). While undoubtedly true for cases involving fixed format numeric output, the reverse is true for outputting user defined types or output in generic code. -- Ian Collins |
Luca Risolia <luca.risolia@linux-projects.org>: Dec 16 09:01PM +0100 Il 16/12/2014 19:31, Scott Lurndal ha scritto: > The equivalent output stream version resembles COBOL in > terms of unnecessary verbosity (although in reality, COBOL > picture clauses are much more similar to *printf than cout). I wonder what would be the equivalent version in C++ in your opinion. |
scott@slp53.sl.home (Scott Lurndal): Dec 16 08:03PM >While undoubtedly true for cases involving fixed format numeric output, >the reverse is true for outputting user defined types or output in >generic code. When I need to dump a "user defined type" (aka class), I use a member function that formats the relevent member data using snprintf; in larger projects, an pure abstract class defines the member function name (a la a java interface). This isn't really different from using templated outputstream formatters. Works fine; just doesn't require an ostream or string stream (which in my experience is a good thing, since I find C++ I/O pretty much useless for real applications, preferring to use the posix[*] interfaces (pread/pwrite/mmap/poll/epoll) instead). [*] I'm fortunate in that I've never been required to program under a windows operating system in the last forty years of programming, aside from a couple of optical storage (WORM) device drivers for NT 3.51 back in the mid 90's as a consultant. |
Luca Risolia <luca.risolia@linux-projects.org>: Dec 16 09:07PM +0100 Il 16/12/2014 16:19, Scott Lurndal ha scritto: > Of course, other opinions may differ. [sn/f]printf is far more readable, far more usable > and far more efficient than output streams. The opposite is almost always true. streams are also type-safe (although nothing forbids to implement a type safe version of printf in C++11). |
Luca Risolia <luca.risolia@linux-projects.org>: Dec 16 09:14PM +0100 Il 16/12/2014 21:07, Luca Risolia ha scritto: > Il 16/12/2014 16:19, Scott Lurndal ha scritto: > The opposite is almost always true. streams are also type-safe (although > nothing forbids to implement a type safe version of printf in C++11). Furthermore there is no way for a classic C printf implementation to be faster than the C++ counterpart using variadic templates. Guess why. |
"Öö Tiib" <ootiib@hot.ee>: Dec 16 12:16PM -0800 On Tuesday, 16 December 2014 02:00:40 UTC+2, Lynn McGuire wrote: > "In defense of printf" > http://kennykerr.ca/2014/12/08/in-defense-of-printf/ You must be bored. ;) > "Folks seem to enjoy pointing out that I use printf in many of my > examples of "modern C++", as if printf is not really proper C++. Since C++ does not have anything useful in standard set the 'printf' is as perfect for usage in illustration code of raw C++ as is 'cout'. > Apparently, I should be using cout. It is sort of like discussing how good 'malloc' is compared to 'new' when we can use neither in actual C++ code (unless we write standard library or something competing with standard library) and it seems that we only gain from avoiding those. > The trouble is that cout isn't exactly modern either. It has been > around for as long as I can remember and it certainly doesn't > exemplify modern C++ as envisioned by C++11 and beyond. Yeah, pot vs kettle. > cout. I even posed the question to some C++ historians and they were > able to date it back as far as 1989. Therefore, the argument that > printf is old and cout is modern doesn't fly. Indeed, poop vs feces here. > straightforward to write defensive code quite easily with printf. Go > ahead and use cout if you prefer, but don't claim it's the modern > replacement for printf." I don't understand. Both are dead without resurrection possible. Let me evaluate ... 'printf' format becomes quickly complex and cryptic when the format specifiers are something else and more detailed than the '%d' and '%s'. Scott Lurndal already beat me in posting his oh so readable examples else-thread. The format specifiers don't specify everything; we need things like 'strftime' just to output time etc. also somewhere underneath a locale is screwing things over. However the 'cout' I/O manipulators are additionally annoyingly verbose so Scott is right that we get COBOL trying to format raw numbers using those. 'cout' is no way more familiar with 'struct tm' than 'printf' so sorry but no sugar and it is screwed up by locale as deep. Oh. But we next to never have raw context-free numbers exposed in C++. So we run to extend 'cout' by overloading 'operator<<(ostream,Foo const&)' *Terrible* idea. Especially devastating with novice in charge plus dynamic or static polymorphism and/or any forms of implicit conversions. They stare and debug it for hours and only positive outcome is that learn to hate 'cout' with passion. Soon we then pick the bit cleaner way out of it by making everywhere things like 'Foo.asText(optional_specifiers)'. As ultimate result we cut most features of both 'printf' and 'cout'. We use only '%s' with 'printf' and only 'operator<<(ostream,string const&)' with 'cout'. Hmm. What we now got? Big pile of unneeded bloat features underneath dragging down our application's efficiency on *both* cases. And since we are down to strings only it is now simple to verify that even 'operator+' of 'std::string' beats them both. :D > I have tried to cut my printf usage to very basic functions that > get called a lot so they are fairly well tested. Printf usege in > an error message is a bad idea, IMHO. There are no reason to use these in human interface when there is anything more comfortable (QString, Boost.Format, your own lib, whatever) available (and that must be is always the case). There are no point to use these for structured text (like XML, JSON, whatever). No well-performing parser/generator can result. Only two usages I can see: For constructing cryptic code to ensure job security for ourselves and for usage in academic raw C++ example codes for to screw schoolboys and enforce them to think about ways out of that excrement. |
Ian Collins <ian-news@hotmail.com>: Dec 17 09:38AM +1300 Scott Lurndal wrote: > in larger projects, an pure abstract class defines the member function > name (a la a java interface). This isn't really different from > using templated outputstream formatters. Which is all fine and dandy until you want dump the class in a function template... -- Ian Collins |
scott@slp53.sl.home (Scott Lurndal): Dec 16 09:21PM >> terms of unnecessary verbosity (although in reality, COBOL >> picture clauses are much more similar to *printf than cout). >I wonder what would be the equivalent version in C++ in your opinion. lots of "<<" operators. Lots of useless verbiage to set field widths (std::setw), std::showbase, std::internal, std::setfill('0') and data format (std::hex). And for this use case, I'd need to use a string output stream, and convert it back to bytes. But the point is, that the *printf* family of functions is perfectly cromulent, and perfectly legal to use in C++ programs. |
scott@slp53.sl.home (Scott Lurndal): Dec 16 09:25PM >> and far more efficient than output streams. >The opposite is almost always true. streams are also type-safe (although >nothing forbids to implement a type safe version of printf in C++11). The type-safety argument is overblown. Particularly since the compilers have had the capability to warn about mismatched format arguments for almost two decades. Readability is in the eye of the beholder, obviously. But in all my real-world C++ experience, I've never seen a project outside of some class project or new-hire code that even used C++ formatted I/O instead of snprintf; and I find snprintf much easier to read and especially to write than the redefinition of the bit shift operator into some sort of magic I/O operator. |
scott@slp53.sl.home (Scott Lurndal): Dec 16 09:28PM >> nothing forbids to implement a type safe version of printf in C++11). >Furthermore there is no way for a classic C printf implementation to be >faster than the C++ counterpart using variadic templates. Guess why. Please enlighten us. How is: std::cout << std::showbase << std::internal << std::setfill('0') << std::hex << std::setw(8) << x << endl; more efficient or more readable than: printf("0x%x\n", x); ? |
Barry Schwarz <schwarzb@dqel.com>: Dec 15 04:02PM -0800 >Hi. I'm new to c and c++. I am coming from the world of Modula-2 and >Ada and I'm trying to understand the following syntax Trying to learn both languages at the same time can be confusing. The languages have just enough similarity to lead newcomers in the wrong direction when trying to use a construct from one in the other. Pick one language. Get comfortable with it. Then tackle the other. -- Remove del for email |
Ian Collins <ian-news@hotmail.com>: Dec 16 02:01PM +1300 Ian Collins wrote: > Note many coding standards reserve all cast for macro names, not > class/struct names. That should have said "reserve all caps"... -- Ian Collins |
Robert Wessel <robertwessel2@yahoo.com>: Dec 15 07:51PM -0600 >_win_border_struct, but instead uses the WIN_BORDER identifier. >So my question is, what is the difference between the identifier that >follows struct and the one that follows the closing }? If you had just a stand alone struct definition: struct struct_name {int a; int b;} struct_instance; The name after the closing brace is, in fact, creating and naming of an instance of the struct. In this example, there is a structure type named struct_name defined, and an instance of struct_name called struct_instance is created. In a typedef: typedef struct struct_name {int a; int b;} typedef_name; You cannot create an actual instance of the structure, and the name after the closing brace is the name of the new type. So in the above typedef_name is an alias for "struct struct_name". Now that will work in both C and C++, but in C++ the struct defintion automatically creates a typename (the same as the structure name). So in either case, in C++, a type named struct_name will be created (and in the second example typedef_name will be created as well). In C++ you would usually avoid the explicit typedef. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment