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);
}
}
int promotion rule. char is signed. The 256 are signed. When the
result goes above INT_MAX it overflows (i.e. we're in UB
territory) and the result can be anything. The registers of the
CPUs are 64 bit wide so it sign extends the calculation and as
the optimization removes the truncating memory write and reload,
the value of the complete register is then printed by the cout>>.
Conclusion: typical C(++) undefined behavior due to signed value
overflow.
Fix: 256u
and always compile with -ftrapv . In your case it would have
catched the overflow.
In D, signed overflow is not UB so everything works as planned.
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.