Comparing D vs C++ (wierd behaviour of C++)
Patrick Schluter
Patrick.Schluter at bbox.fr
Tue Jul 24 20:59:22 UTC 2018
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:
>>>> I am not C++ expert so this seems wierd to me:
>>>>
>>>> #include <iostream>
>>>> #include <string>
>>>>
>>>> using namespace std;
>>>>
>>>> int main(int argc, char **argv)
>>>> {
>>>> char c = 0xFF;
>>>> std::string sData = {c,c,c,c};
>>>> unsigned int i = (((((sData[0]&0xFF)*256
>>>> + (sData[1]&0xFF))*256)
>>>> + (sData[2]&0xFF))*256
>>>> + (sData[3]&0xFF));
>>>>
>>>> if (i != 0xFFFFFFFF) { // it is true why?
>>>> // this print 18446744073709551615 wow
>>>> std::cout << "WTF: " << i << std::endl;
>>>> }
>>>> return 0;
>>>> }
>>>>
>>>> compiled with:
>>>> g++ -O2 -Wall -o "test" "test.cxx"
>>>> when compiled with -O0 it works as expected
>>>>
>>>> Vs. D:
>>>>
>>>> import std.stdio;
>>>>
>>>> void main(string[] args)
>>>> {
>>>> char c = 0xFF;
>>>> string sData = [c,c,c,c];
>>>> uint i = (((((sData[0]&0xFF)*256
>>>> + (sData[1]&0xFF))*256)
>>>> + (sData[2]&0xFF))*256
>>>> + (sData[3]&0xFF));
>>>> if (i != 0xFFFFFFFF) { // is false - make sense
>>>> writefln("WTF: %d", i);
>>>> }
>>>> }
>>>>
>>>> compiled with:
>>>> dmd -release -inline -boundscheck=off -w -of"test" "test.d"
>>>>
>>>> So it is code gen bug on c++ side, or there is something
>>>> wrong with that code.
>>>
>>> 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
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.
More information about the Digitalmars-d
mailing list