4 ms·
I think C has broken that promise since. It now targets an abstract machine, and a lot of behavior that would make sense for a light wrapper compiles to somethi
by boomlinde 8y ago
I think C has broken that promise since. It now targets an abstract machine, and a lot of behavior that would make sense for a light wrapper compiles to something counter-intuitive in an optimizing compiler.
In a different time, that something was left undefined by the standards might have meant that the result might be some artefact of the target machine architecture, but with aggressively optimizing C compilers the undefined behavior is more likely to be an artefact of the optimizer.
A thin light wrapper wouldn't compile this:
static int doub(i) { return i + i; }
int main(void)
{
int i;
int sum;
sum = 0;
i = 5;
while (i--)
sum += doub(i);
return sum;
}
into this:
movl $20, %eax
ret
I'm not programming memory or registers, I'm instructing an optimizer.
- janekm 8y agoWhat compiler does that? None of the ones I tried on god bolt seem to (after fixing the missing type on the function parameter)? And what's the undefined behaviour here?
- foldr 8y agoYou're probably not turning on optimization. For example, gcc 8.3 with -O3 gives the result that the OP posted. There's no undefined behavior in that example, as far as I can see. The point is that the compiler optimizes away all of the actual computation, since it's able to determine at compile time that the result will always be 0x20.
- boomlinde 8y agoI genuinely forgot to specify the type of the function argument, but that's not considered an error in C which will default to int when the type is omitted. If the compiler you're using objects to that it's probably for the better, but it's still legal C. There is no undefined behavior in the example. It's meant to further illustrate my point that C is not a light wrapper around memory and registers. In the example, it's just a deceptively imperative looking way of describing the return value to the optimizer. The compiler in this case was gcc with -O3. For an example of behavior that is straight forward in the machine but is undefined in C, try signed integer overflow. Intuitively on x64 it should behave just like ADD, possibly adjust the carry and overflow flags and wrap around. In C, the behavior is entirely undefined. Some operation that results in UB is low hanging fruit for the optimizer. If it can deduce that the operation will result in UB, in this case signed integer overflow, it might omit the operation altogether.