6 ms·
No maliciousness is required. "1 + 2" produces "3" only because the standard defines it so -- it is therefore required that 1 + 2 produce 3. When the standard d
by nlewycky 3y ago
No maliciousness is required. "1 + 2" produces "3" only because the standard defines it so -- it is therefore required that 1 + 2 produce 3. When the standard does not say what to do, there is no requirement.
You said "it's not a license to do whatever" which is only true because it isn't a license. The code can still do whatever, because there is no requirement that it do anything other than "whatever".
You seem to be arguing from a position that the code has meaning unless somehow UB gets involved, but the reality is that these bits and bytes don't mean anything until the spec tells us what meaning it has.
- mpweiher 3y ago> until the spec tells us what meaning it has. That's a commonly held belief, but wrong. My first C compiler predated the ANSI C standard. Yet the code very much had meaning, just not in terms of the C standard. The C standard defines the minimum a C compiler has to do to be in compliance with the C standard. It is not a complete definition, and this is intentional.
- nlewycky 3y ago> > until the spec tells us what meaning it has. > That's a commonly held belief, but wrong. My first C compiler predated the ANSI C standard. Yet the code very much had meaning, just not in terms of the C standard. Much like /* plain English comments */ have meaning, just not in terms of the C standard. Talking about prestandard C isn't relevant because we're talking about what a standards conforming compiler can do with undefined behaviour per the text of the standard. I do not find your counterexample compelling. > The C standard defines the minimum a C compiler has to do to be in compliance with the C standard. The standard does not define what a compiler has to do. Instead, it defines the C abstract machine as well as syntax attached to behaviour in terms of that abstract machine. When a program which is restricted to that syntax is executed, it must have the effects (upon the C abstract machine*) as specified in the standard. Sometimes the standard doesn't specify anything for a given syntax in a given abstract machine state, and sometimes the standard explicitly specifies that "the behavior is undefined". > It is not a complete definition, and this is intentional. I'm not sure what you mean. Compiler extensions exist (and are generally regarded as a necessary evil), is that what you're referring to? Or are you referring to implementation-defined things (all of which are explicitly called out in the standard)? Or something else? A citation, if you can? * Notably the C language says nothing about the real machine. Supposing you have an I/O port at address 0x9000, accessing "*((char*)0x9000) = 1;" does not need to access memory address 0x9000 at all. Of course, compiler engineers are not silly and implemented it as accessing 0x9000 on the underlying machine. Similarly the standard committee is careful to ensure that the language it defines can be implemented without needed the overhead of a VM or interpreter, though sometimes they get that wrong. (For example, see the issues combining multiple alloca() and C99's "int foo[*];" in the same function.)*
- 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