Re:How to Get Fired Using Switch Statements and Statement Ex...
by wahern on Sunday October 30, 2016 @12:41AM
(#12828201)
Statement expressions have been supported by GCC for almost two decades. Maybe more than two decades. Most C compilers support them, including clang, Sun Studio, Intel, and many others. In fact, MSVC is the only compiler I've used that doesn't support them.
As for whether they were well thought out, consider that you have the same initialization scoping problem with C99's compound literals, and more generally with any automatic-storage variables. You cannot jump over (using goto or switch) the declaration or definition statement that instantiates the variable. It's doubly stupid when you do it with statement expressions because the warning is right there in the very small, concise section of the GCC manual explaining them. And nobody should be using a construct without understanding the rules for using it, which typically means reading the rules.
You can't fix stupid.
I was actually bit by a scoping issue like this a year or two ago. I was using a compound literal in some code that a drive-by patch submitter made work with C++. Now, I'm not a C++ programmer, but I knew that C++ didn't support C99 compound literals. Yet I stupidly assumed that because GCC and clang accepted the construct syntactically (and without warning) they'd implemented the same semantics. Well, they didn't, at least not after somebody "fixed" those compilers to give that syntax the semantics of C++ temporaries. (Which made no sense to me; it's a parse error in standard C++, and subtly changing the semantics like that was bound to break code.) The difference was important, because compound literals have block-scoped lifetimes, whereas C++ temporary objects only have expression-scoped lifetimes. In short, this caused perfectly legal C code to scribble over stack memory when compiled as C++.
I must assume at least some of the blame because I should have known better than to continue using a compound literal in header code that purported to support C++. OTOH, I had zero intention of ever using that code as C++; I just thought I was doing somebody a favor by accepting their patch. No favor goes unpunished, I guess.
As for Duff's Device... I love using the Duff's Device to implement a poor man's coroutine in standard C. You can write very clean and concise code this way. For example, here's a re-entrant implementation of POSIX getopt I wrote. It's probably the shortest correct implementation of getopt in C or most any other language.
As for whether they were well thought out, consider that you have the same initialization scoping problem with C99's compound literals, and more generally with any automatic-storage variables. You cannot jump over (using goto or switch) the declaration or definition statement that instantiates the variable. It's doubly stupid when you do it with statement expressions because the warning is right there in the very small, concise section of the GCC manual explaining them. And nobody should be using a construct without understanding the rules for using it, which typically means reading the rules.
You can't fix stupid.
I was actually bit by a scoping issue like this a year or two ago. I was using a compound literal in some code that a drive-by patch submitter made work with C++. Now, I'm not a C++ programmer, but I knew that C++ didn't support C99 compound literals. Yet I stupidly assumed that because GCC and clang accepted the construct syntactically (and without warning) they'd implemented the same semantics. Well, they didn't, at least not after somebody "fixed" those compilers to give that syntax the semantics of C++ temporaries. (Which made no sense to me; it's a parse error in standard C++, and subtly changing the semantics like that was bound to break code.) The difference was important, because compound literals have block-scoped lifetimes, whereas C++ temporary objects only have expression-scoped lifetimes. In short, this caused perfectly legal C code to scribble over stack memory when compiled as C++.
I must assume at least some of the blame because I should have known better than to continue using a compound literal in header code that purported to support C++. OTOH, I had zero intention of ever using that code as C++; I just thought I was doing somebody a favor by accepting their patch. No favor goes unpunished, I guess.
As for Duff's Device... I love using the Duff's Device to implement a poor man's coroutine in standard C. You can write very clean and concise code this way. For example, here's a re-entrant implementation of POSIX getopt I wrote. It's probably the shortest correct implementation of getopt in C or most any other language.
https://github.com/wahern/lunix/blob/rel-20161026/src/unix-g...