3 ms·
> we're talking about what a standards conforming compiler can do No. You may be, I am not. I am talking about what a reasonable C compiler can do, and what t
by mpweiher 3y ago
> we're talking about what a standards conforming compiler can do
No. You may be, I am not.
I am talking about what a reasonable C compiler can do, and what the ANSI standards committee intended.
Adhering to the ANSI/ISO standard is at best a necessary condition for producing a useful C compiler. It is most definitely not a sufficient condition. As I've pointed out many times before, this was intentional.
And the existence of pre-standard C compilers that worked is, of course, clear evidence that it is not a necessary condition either. Or at least was not.
The C standard leaves a lot "undefined" or "implementation defined" that is actually well-defined on a concrete machine the compiled code runs on. If you seriously think the intention of all this was to allow demons to fly out of nostrils or for compilers to start mining bitcoins, which is all perfectly legal by the standard, well, I don't really know what to say.
Particularly because the creators of the standards clearly stated so. In the very standard itself. Now they didn't make that language mandatory, so yeah, you can make a "standards compliant" compiler that violates that intent. But it will be a sucky compiler.
C ≠ The ANSI/ISO C standard.
- muldvarp 3y ago> The C standard leaves a lot "undefined" or "implementation defined" that is actually well-defined on a concrete machine the compiled code runs on. This assumes there is a one-to-one correspondence between C constructs and machine code, which isn't true. C isn't a "portable assembler" and compilers are luckily able to choose whatever machine code they think will perform best under the assumption that there is no undefined behavior. > But it will be a sucky compiler. I don't think gcc or clang are sucky compilers at all. In fact, their ability to aggressively optimize valid code is extremely helpful for producing high-performance programs. > C ≠ The ANSI/ISO C standard So C is defined neither by the standard _nor_ by existing implementations and is instead defined to be whatever your headcanon is?
- mpweiher 3y ago> This assumes there is a one-to-one correspondence between C constructs and machine code No it does not. > which isn't true. Actually, it is true in a vast majority of cases. > C isn't a "portable assembler" Not sure why people keep repeating this despite it being so obviously and patently untrue: "Committee did not want to force programmers into writing portably, to preclude the use of C as a “high-level assembler:” https://www.open-std.org/JTC1/SC22/WG14/www/docs/n897.pdf https://www.open-std.org/JTC1/SC22/WG14/www/docs/n897.pdf p10, line 39 "C code can be portable. " line 30
- nlewycky 3y ago> And the existence of pre-standard C compilers that worked is, of course, clear evidence that it is not a necessary condition either. Or at least was not. The difference is that those compilers didn't have a spec to follow or disobey anyways. The can always just say "whatever happened is right" and you could argue that the compiler did something _unhelpful_ but the compiler broke no promise because it made no promise. > Particularly because the creators of the standards clearly stated so. In the very standard itself. They clearly stated the opposite: """ * Undefined behavior --- behavior, upon use of a nonportable or erroneous program construct, of erroneous data, or of indeterminately-valued objects, for which the Standard imposes no requirements. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message) """ from ANSI C89 (§1.6). The compiler may ignore the situation completely leading to unpredictable results. If the compiler ignores a situation, such as a signed integer overflow, and that leads to unpredictable results, such as "next time we see an if-statement, execute both the if-block and the else-block", then that's 100% conforming. That's exactly what was intended. This sort of thing can happen, suppose the evaluation of an if-condition ends up in some CPU flags, and the compiler knows the two flags are exclusive because the only way they wouldn't be is if the program had a signed integer overflow. FWIW, GCC 1.17, released in January 1988, would launch 'nethack' during the compile if it detected a #pragma that it didn't understand. The idea of interpreting it as "anything can happen" is neither incorrect nor new. (Technically in this case, an unknown pragma has implementation-defined behavior which is the same as UB plus a requirement that the behavior must be documented in the compiler's manual.) It was a bad idea though and they removed it because a compiler that does that is, well, not good. We call this property "quality of implementation", but it wasn't a correctness issue.
- mpweiher 3y ago> didn't have a spec to follow or disobey anyways. Exactly. Yet they were still C compilers. So the idea that "being a C compiler" is the same as "follows the spec" is clearly nonsense. You can follow the spec and not be a usable C compiler, and you can be a usable C compiler and not follow the spec. And the C spec not being complete was intentional, because otherwise too many already existing C compiler would have not had a chance of becoming ANSI compliant, and thus the spec would have been meaningless. > They clearly stated the opposite: > [..] > Permissible undefined behavior ranges from ignoring ... Very clearly gives a list of "permissible behaviors". Now if you believe that one of those options is "do anything you please" when it both clearly doesn't say that, it just "ignore with unpredictable results" AND it doesn't make logical sense, not sure how to help you. (The two other options for permissible behavior are clearly completely redundant if one of them permits you to do anything you want whatsoever). > "next time we see an if-statement, execute both the if-block and the else-block", then that's 100% conforming It is "conforming" to the spec that has made that part non-binding. It does not conform to "ignore the situation", because the unpredictable behavior mentioned in the spec is that of the environment, not the compiler.