I just ran into a compile error on code that has been just fine for 18 years. The only reason I'm compiling it is just to be sure on a new computer/Linux install. With gcc 4.8.3 I do not get the warnings, with gcc 13.3.0 I get the warnings shown below the code below. The char string being converted is hex, data returned from a solar inverter. And like I said it's been fine and I suspect the program will run fine just cannot fully test it yet until data collect is moved to this new server. *-------------------------------------------------------------------------- szCvrtLong Converts a 4 char string to a long. ----------------------------------------------------------------------------*/ unsigned long szCvrtLong(char *Buffer) { unsigned char cValue[4]; unsigned long *value = 0; if (! bSwapEndian) { cValue[0] = Buffer[aParam4] & 0xff; cValue[1] = Buffer[aParam3] & 0xff; cValue[2] = Buffer[aParam2] & 0xff; cValue[3] = Buffer[aParam1] & 0xff; } else { cValue[0] = Buffer[aParam1] & 0xff; cValue[1] = Buffer[aParam2] & 0xff; cValue[2] = Buffer[aParam3] & 0xff; cValue[3] = Buffer[aParam4] & 0xff; } value = (unsigned long *)cValue; if (bVerbose) fprintf(stderr, "szCvrtLong %12lu 0x%02x%02x%02x%02x\n",*value & 0xffffffff,cValue[3],cValue[2],cValue[1],cValue[0]); return(*value & 0xffffffff); } ----------- comm.c: In function 'szCvrtLong.constprop': comm.c:1906:77: warning: array subscript 'long unsigned int[0]' is partly outside array bounds of 'unsigned char[4]' [-Warray-bounds=] 1906 | if (bVerbose) fprintf(stderr, "szCvrtLong %12lu 0x%02x%02x%02x%02x\n",*value & 0xffffffff,cValue[3],cValue[2],cValue[1],cValue[0]); | ^~~~~~ comm.c:1890:19: note: object 'cValue' of size 4 1890 | unsigned char cValue[4]; | ^~~~~~ comm.c:1908:12: warning: array subscript 'long unsigned int[0]' is partly outside array bounds of 'unsigned char[4]' [-Warray-bounds=] 1908 | return(*value & 0xffffffff); | ^~~~~~ comm.c:1890:19: note: object 'cValue' of size 4 1890 | unsigned char cValue[4]; | ^~~~~~
The warning is correct. sizeof(long) on x86_64 is 8 rather than 4 that it was on i686. So when you do this: unsigned char cValue[4]; unsigned long *value = 0; value = (unsigned long *)cValue; *value & 0xffffffff You get undefined behavior because you are reading 8 bytes from a 4 byte array.
Note this code also violates C/C++ aliasing rules but that is a different issue.
Note there is also an alignment requirement that you violate with the assignment and access of the char array too.
Thank you the information. So I should use unsigned int now on x86_64? Where can I read more on the rule violations and what would be the proper so do this?