"Thou shalt not, in the language of C, under any circumstances, on the pain of death, declare or define a function with an empty set of parentheses, for though in the language of C++ it meaneth the same as (void), in C it meaneth (...) which is of meaningless as there be no anchor argument by which the types of the varadic arguments can be expressed, and which misleadeth the compiler into allowing unsavory code and in some cases generate really ugly stuff for varadic handling." -hpa
Here's a historical C quirk that I didn't know about (one with all sorts of fun potential side-effects - a function would take any number of parameters). Thankfully this is one place where C++ makes a very sensible decision to deviate from C in that f() meaneth f(void).
Both gcc and llvm will allow passing of arguments to a function defined f(), though clang will issue a "warning: too many arguments in call to 'f" when you have -Wall enabled. Both will error if it's f(void).
Matt Giuca
Yep. It's a throwback to K&R C, I think, where it was common to just leave off arguments if they were all ints. Remember they had a different syntax for slurping in the arguments after the header (though I can't really remember it now).
This is why some time ago I got into the habit of writing int main(void) instead of int main(). Good job C++.
Matt Giuca
+Bruce Cran Why? Just so that C programmers aren't confused? It seems like () is perfectly clear as long as you don't have C preconceptions. If you do have C preconceptions, the worst you may think is "ugh, this guy forgot to use void" -- there is no actual bugs that could fall out of it. On the other hand, (void) is pretty confusing if a C++ programmer doesn't understand this wacky rule in C. I would use () unless I was writing C/C++ dual code.
Torgeir Hagland
in all seriousness, people should just stop writing plain C code...
Matt Giuca
+Bruce Cran Heh, I love the footnote on that FAQ: "Actually this f() thing is all you need to know about C++. That andusing those new fangled // comments. Once you know those two things,you can claim to be a C++ expert. Go for it: type those magical "++" marks onyour resumé. Who cares about all that OO stuff — why should you botherchanging the way you think? After all, the really important thingisn't thinking; it's typing in function declarations and comments. (Sigh; Iwish nobody actually thought that way.)"
I think POC (plain old C) has its place. An important sticky point for me is that libraries should be written in C unless there is a damn good reason. C is the "lowest common denominator" for language interchange -- all serious modern languages have a way to talk to C. C++ is much harder to plumb through to a high-level language. So if you are writing a useful library, it is better for it to be written in C unless the whole point of the library is to provide a high-level programming interface in a high-level language. (So for example, Boost is in C++ because the whole point of it is to provide high-level features for C++. OpenGL is written in C because then everything else can interface to it.)
David Coles
Yeah. The C++ FAQ is excellent. I honestly learnt most of my C++ from it (all the tricky - how do I do X and more importantly what not to do).
C has a an almost beautiful simplicity too it - no name managing, everything has file scoping and relatively close to the machine. It's hardly perfect - the syntax can be a bit dinky, headers are only slightly better than macros and type system is a bit weak, but it's still the one true system language. C++ introduces... a lot more complexity which can interact badly if you start combining STL, classes, templates and classic C all at once.
I'd still love it if C had a simple namespaces feature though.
David Coles
+Bruce Cran Sorry. Mixed two thoughts at once. Headers are really just macro code inclusion (to the detriment of compile times) - in many ways the preprocessor is kind a of a weird (though useful) feature of the language.
Matt Giuca
+David Coles "no name managing" (do you mean mangling?) ... "I'd still love it if C had a simple namespaces" I think namespaces are part of the reason C++ has to have name mangling. You can't really have namespaces when you're programming direct into object files.
David Coles
+Matt Giuca A very simple kind of managing such as `foo { int x; }` being equivalent to `int foo_x;`. Sadly that probably still introduces all sorts of issues for when you write `x = 3` did you mean `foo_x` or `x`. C will probably never have function overloading (because of the non-trivial mangling required) but type generic expressions (compile time feature) can be used to get similar features.
Matt Giuca
Yeah that mangling (wait.. you're still saying "managing", do you mean mangling or are you referring to something different?) is simple, but still it takes the language out of the "high-level assembly language" category, because the identifiers no longer reflect the names in the object file. I don't think that would be an appropriate C feature.
What is "generic expressions"?
David Coles
Mangling is probably the wrong word. Think of it more like syntactic sugar you could implement in the preprocessor. It's a short way of defining the kind of "libfoo_dofoo()" people tend to do by hand in library interfaces.
Type-generic expressions <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1441.htm> are a way of defining a macro which uses type to select the correct function at compile time. For example sin(x) would be replaced with sin(x) if x was a double; or sinf(x) if x was a float.
I also see there's now some Unicode literals - `char c8 = u8"UTF8"`; char16_t c16 = u"UTF-16"; char32_t c32 = U"UTF-32"`.
Yeah, I consider the name mangling thing and cleanup functions to be too automagical for C. The Unicode strings are a fine addition, and I suppose the type-generic expressions are fine since they're a preprocessor thing.