Casey Muratori, who's a better C programmer than me, is of the opinion that you should check your compiler's behavior rather than read standards.
(Not that you should take his word as gospel, I don't fully agree myself, but it's worth considering.)
Casey Muratori, who's a better C programmer than me, is of the opinion that you should check your compiler's behavior rather than read standards.
(Not that you should take his word as gospel, I don't fully agree myself, but it's worth considering.)
It's much better to avoid undefined behavior entirely. The problem with this idea is that it's hard to learn and remember all the different kinds of undefined behavior.
>> Casey Muratori, who's a better C programmer than me, is of the opinion that you should check your compiler's behavior rather than read standards.
In Casey Muratori's case, he's the type of person who cares to understand what the compiler is actually generating under the hood. He doesn't exactly trust the compiler to always do the right thing.
There was an episode of Handmade Hero where he caught an optimization #fail of the compiler and tried to figure out what was going on (live). https://twitter.com/cmuratori/status/596775025023287297
Casey Muratori also has been developing in Visual Studio for a very long time. Visual Studio has a long, tortuous, history of being non-stanards compliant and buggy. And Microsoft until very recently, never cared to fix anything. (And it still doesn't conform to C99, let alone C11.)
Whatever C related updates you might see, are the ones required by the ANSI C++ for C compatibility.
For C99 and C11 support there is the clang frontend to C2, the Visual C++ backend, currently taking an LLVM role at Microsoft, being shared between clang, VC++ and .NET Native.
Given: 1) There are various optimizations that may kick in or not depending on UB. 2) The cleverness of the optimizer may and does(!) change between versions. 3) There's no "-warn-on-optimizer-changes" flag for any compiler.
Do you think it's realistic to compare compiler output whenever you upgrade your compiler? Do you think it's realistic for 1M SLoC projects? If not, do you take a statistical approach with random sampling? If so, I'd be very interested. If not... what exactly are you sure of and how?
Do both.
Disassemble your compiler's output to see what horrors the optimizer inflicted on your code to "break" it. Read the standard to understand why it thought it was an okay optimization to do in your case, to avoid running afoul of the same mistake again. Ask what other optimizations are enabled by this undefined behavior, the better to spot them when the code your coworker's former boss's roomate, who interned for a month or two, invokes undefined behavior.
Repeat.
(To be fair, I haven't read the standards cover to cover - perhaps I should, I'm still occasionally learning about new and exciting forms of UB...)
There is one thing I have noticed in gcc and clang which is done against the standards: The sign of bit sized int in a struct.
eg: In a struct with member 'int a:8', The standard says that 'a' can be signed or unsigned (based on the machines default of the sign of char). But In gcc and clang, this is signed always regardless of the machine.
Wait, are you saying gcc/clang's behaviour is permitted by the standard, or not?
It's permitted. The same way as a char can be signed or unsigned: Implementation defined. But in this case, it's always signed regardless of the architecture (against how a char is handled).
From c99 draft (n1570), J.3.9 (Implementation-defined behavior): Whether a ‘‘plain’’ int bit-field is treated as a signed int bit-field or as an unsigned int bit-field (6.7.2, 6.7.2.1).
But say, another compiler (ARM compiler) treats this differently [0]: Untill version 5 of the compiler, such an int was unsigned by default. Later versions defaulted to signed (as do gcc/clang).
[0] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc....