On Tuesday, 24 July 2018 at 20:59:22 UTC, Patrick Schluter wrote:
On Tuesday, 24 July 2018 at 19:24:05 UTC, Ecstatic Coder wrote:
On Tuesday, 24 July 2018 at 15:08:35 UTC, Patrick Schluter wrote:
On Tuesday, 24 July 2018 at 14:41:17 UTC, Ecstatic Coder wrote:
On Tuesday, 24 July 2018 at 14:08:26 UTC, Daniel Kozak wrote:
[...]

As the C++ char are signed by default, when you accumulate several shifted 8 bit -1 into a char result and then store it in a 64 bit unsigned buffer, you get -1 in 64 bits : 18446744073709551615.

That's not exactly what happens here. There's no 64 bit buffer.

Sure about that ? ;)

Yes, there are no "buffers" only register and a place on the stack for the variable i.

As said it's undefined behaviour so anything goes. I just checked on godbolt what code is generated. https://godbolt.org/g/wxqfmM
So with -O0 this happens:
From line 41 to line 77 the instruction to make the calculation. At line 78 mov DWORD PTR [rbp-40], eax which is writing out 32 bits to reserved space of i. At line 85 mov eax, DWORD PTR [rbp-40] reloads that value in eax, this annuls the high part of RAX => RAX contains 0x0000_0000_FFFF_FFFF

what I forgot to mention, for the compiler the type deduction for the >> operator is done with the i variable, so it chooses the right template with unsigned int. For the optimized code as the calculation is done during compilation and there is no spill to the variable the type deduction for the >> operator for cout is done with that internal promoted temporary value and it deduces it as long (funnily declaring i as volatile doesn't change that even if the value is spilled to the stack).


On the -O2 version it's even simpler. The calculation is done at compile time and the endresult -1 is put directly to the output. The test is even removed. Everything happens in the compiler.

Reply via email to