lifthrasiir 4 days ago

> the most recent C standard was supposed to mandate two’s complement.

While that's true, overflows are not automatically wrapping because they instead may trap for several reasons. (C++ does require wrapping now in comparison. [1])

[1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2412.pdf

> memcpy is allowed to start reading early as a performance optimization, [...]

Most modern memcpy implementations would branch on the length anyway, because word-based copying is generally faster than byte-based copying whenever possible. Also many would try SIMD when the copy size exceeds some threshold for the same reason.

>> read an unitialized object, even if I "don't care" what value I get

> You are probably doing something wrong if you do this.

The GP meant the case like this. Consider `struct foo { bool avail; int value; } foos[100];` where `value` would be only set when `avail` is true. If we are summing all available `value`s, we may want to avoid a branch misprediction by something like `accum += foos[i].avail * foos[i].value;` for each `foos[i]`, since the actual `value` shouldn't matter when `avail` is false. But the current specification prohibits this construction because it considers that each read from `foos[i].value` may be different from each other (!). In reality, this kind of issues is so widespread that LLVM has a special "poison" value which gets resolved to some fixed value after the first use.

1
ryao 4 days ago

Thanks for the explanations.

As for the last one, I would probably bzero() that structure, as it is faster than setting just 1 field to zero in a loop, which presumably is what you would do until you have some need to “allocate” a value. That would avoid the problem entirely.

I know bzero() was removed from POSIX, but “bzero()” is nicer to write than “memset() it to zero”.