That's mostly true enough (especially about the satanic nature of macros), but point 2 is mushy because the C++ type system is designed to be broken anyway, and will remain so until C-style casts are removed from the language -- in other words, as long as earth and sky abide.

(That used to say "deprecated" instead of "removed from the language", but Furious George was kind enough to point out that they already are deprecated, and what I meant was something different -- and he was right, too. Ack!)

Secondly, sprintf() is indispensable because there's no other equally powerful way to format things. And how many people seriously use the iostream library? Not me. It's annoying and weak and it requires too much support in my own code for too little benefit. I'll give up my FILE * when you pry my cold dead fingers from it. Then again, I learned C first (not necessarily best) and that colors my view of things.

On the other hand, ever since I learned to use the varargs.h stuff, I've been looking for uses for it in my own code, and I've yet to find a compelling one1. Whenever it seems convenient, I aways run up against the problem of determining how many arguments are actually on the damn stack. The format string in the printf() family does the job nicely (assuming the programmer doesn't goof, which is a hell of a dangerous assumption), but without something like that, you're left with adding a dummy NULL or else making the first argument a count of the others. Both of the latter two solutions are dismal kludges. If anybody knows any others, I'd love to hear 'em.

Hm. Come to think of it, since you've got the address of the argument that was pushed last, I'm a bit fuzzy about why you can't just compare the address of any given argument to the stack pointer and know where you are without having to be told. You must be able to get the stack pointer somehow; I mean, it's C, right? So there's obviously something about that which eludes my grasp.

"there are always other, better ways"?

Them sounds like famous last words to me, ha ha.

1 The sole exception would be a sprintf()ish member of a string class, which would realloc() as needed, so it wouldn't be subject to buffer overruns. MFC's string class, CString, does that. The class is a dog in general, but boy that one feature is nifty as all heck. CString also has an odd and ill-advised kludge in it which addresses Gorgonzola's second point, and which is discussed in gruesome and drooling detail in the CString node.