Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> a simple statement like `a = b++;` can mean multiple constructors being called, hidden allocations, unexpected exceptions [...]

Yes, nothing like that is possible in C

https://godbolt.org/z/Ge4EqzznT



The difference is that in C++ it's expected that you'll overload operators, provide implicit conversions and throw exceptions. Of course you can write terrible code in C but it is not common accepted practice to hide a longjmp in a macro disguised as an identifier.


Indeed, you hide longjump in a #define macro instead, with a do while block trick.


The funny thing is, examples of macro craziness only strengthen my point, because C++ inherits all of that in addition to its hidden behaviors and magical semantics. It’s rare to find serious C code doing a lot of crazy things behind macros. In my experience, the few exceptions I can think of include the GMP library and data structure-related code trying to emulate generics (mostly hash tables).


Yes, C++ is a larger language for sure. But because it has better abstraction facilities, macro hackery is less common.


pthread_cleanup_{push,pop}


Haha. You can’t be serious—what’s the likelihood of running into C code like this in anything remotely serious (compared to the millions upon millions of lines of innocent-looking C++ code that does like a dozen different things under the hood)?


No true Scotsman.

I assume you haven't looked at the expansion of errno lately?

edit: also

https://github.com/KxSystems/kdb/blob/master/c/c/k.h


that's a deliberately unfair comparison. operator overloading, constructors, assignments, etc. happen "under-the-hood" in c++ and are standard language features.

whereas you can see the user-defined macro definition of "b" at the top of the file. you can't blame the c language for someone choosing to write something like that. sure it's possible, but its your choice and responsibility if you do stupid things like this example.


Macros are also standard C features, and good luck figuring out that an identifier is a macro without IDE help when the definition is buried in some header.


what you say is partially true (you can also of course use -E to check macros) but:

- macros are also standard C++ features too, so this point doesn't differentiate between those languages

- i'm failing to adequately communicate my point. there's a fundamental difference practically and philosophically between macro stupidity and C++ doing things under-the-hood. of course a user (you, a co-developer, a library author you trusted) can do all sorts of stupid things. but it's visible and it's written in the target language - not hard-coded in the compiler.

yes - sure, good luck finding the land-mine "b" macro if it was well buried. but you can find it and when you do find it, you can see what it was doing. you can #undef it. you can write your own version that isn't screwed up, etc.

you can do none of those things for operations in c++ that occur automatically - you can't even see them except in assembly.


> there's a fundamental difference practically and philosophically between macro stupidity and C++ doing things under-the-hood. of course a user (you, a co-developer, a library author you trusted) can do all sorts of stupid things. but it's visible and it's written in the target language - not hard-coded in the compiler

I specifically reject this. Constructors, exceptions, and so on are as similarly visible at the source level as macro definitions.

And thanks to macros, signal handling, setjmp, instrumentation, hardening, dynamic .so resolution, compilers replacing what look like primitive accesses with library functions, any naïve read of C code, is, well, naïve.

I'm not claiming C++ superiority here [1], I'm trying to dispel the notion that C is qualitatively different from C++ form a WYSIWYG point of view, both theoretically and in practice.

[1]although as I mentioned else, other C++ features means that macros see less use.


to be clear, i'm neither defending nor bashing either language. i use and like both as appropriate. and it's fine to disagree, btw. please do not read "good" or "bad" into my attempt to describe either.

but i will also emphatically reject your position: "Constructors, exceptions, and so on are as similarly visible at the source level as macro definitions"

no they are not. you can certainly see what the macro is doing - you see it's definition, not just it's existence. whereas in c++ you have to trust that language/compiler to:

- build a vtable (what exactly does this look like?)

- make copy ctors

- do exception handling.

- etc.

none of these are explicit. all of them are closed and opaque. you can't change their definition, nor add on to it.

at issue at hand is both "magic" and openness. c gives relatively few building blocks. they are simple (at least in concept). user libraries construct (or attempt to construct) more complex idioms using these building blocks. conversely c++ bakes complex features right into the language.

as you note, there are definitely forces that work against the naïve original nature of c. macros, setjmp, signal handling, instrumentation, hardening, .so resolution, compilers replacing primitive accesses, etc. but all of those apply equally to c and c++. they are also more an affect of the ABI and the platform/OS than either language. in short, those are complaints and complexities due to UNIX, POSIX, and other similar derived systems, not c or c++ the language itself.

c has relatively few abstractions: macros, functions, structured control flow, expressions, type definitions. all of these could be transformed into machine code by hand, for example in a toy implementation. sure a "good" compiler and optimizer will then mangle that into something potentially unrecognizable, but it will still nearly always work the way that the naïve understanding would. that's why when compilers do "weird" things with UB, it gets people riled up. it's NOT what we expect from c.

c++ on the other hand has, in the language itself, many more abstractions and they are all more complex. you aren't anywhere near the machine anymore and you must trust the language definition to understand what the end effect will be. how it accomplishes that? not your problem. this makes it squarely a high-level language, no different than java or python in that facet.

i explicitly reject your position that "that C is qualitatively [not] different from C++ from a WYSIWYG point of view, [either] theoretically [or] in practice."

to me, it absolutely is. it represents at lower level interface with the system and machine. c is somewhere between a high-level assembler and a mid-level language. c++ is truly high-level language. yes, compilers and os's come around and make things a little more interesting than the naïve view of c in rare cases . but c++? everything is complex - there is not even workable illusion of simplicity. to me this is unfortunate because, c++ is still burdened by visible verbosity, complexities, land-mines, and limitations due to the fact that it is probably not quite high-level enough.

this is all very long winded. you and many other readers might think i'm wrong. the reason i'm responding is not to be argumentative, but because it is that it's by no means a "settled" question and there are certainly also plenty of people that see it a very different way. which i think is fine.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: