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.

Reply via email to