Sign extension with unsigned length

We found that some strange values ​​are being created, a small test case below. It prints "FFFFFFFFF9A64C2A". The meaning of the unsigned long long seems to have been expanded. But why? All of the types below are unsigned, and what does a character extension do? The expected result will be "F9A64C2A".

#include <stdio.h>

int main(int argc,char *argv[])
{
    unsigned char a[] = {42,76,166,249};

    unsigned long long ts;
    ts = a[0] | a[1] << 8U | a[2] << 16U | a[3] << 24U;

    printf("%llX\n",ts);


    return 0;

}
+5
source share
3 answers

The expression a[3] << 24U a[1]has a type unsigned char. Now "whole promotion" converts it into int, because:

The following expressions may be used in an expression: intor unsigned int:

[...]

int , int; unsigned int.

(() ISO/IEC 9899: 1999, 6.3.1.1 2)

, ( ) " ", .

- .

(6.5.7 3)

32- 249 << 24 = 4177526784, int, .

ts = a[0] | a[1] << 8 | a[2] << 16 | (unsigned)a[3] << 24;

( U ).

+5
 ts = ((unsigned long long)a[0]) | 
    ((unsigned long long)a[1] << 8U) | 
    ((unsigned long long)a[2] << 16U) | 
    ((unsigned long long)a[3] << 24U); 

int .

+1

a [i], unsigned char int, .

6.3.1 , 6.3.1.1 , , N1570, , , : "2. : int unsigned int:... - ( int unsigned int) int unsigned int.... int ..., int; unsigned int. .... 3. , .

See for example www.open-std.org/JTC1/SC22/WG14/www/docs/n1570.pdf

You can use the following code that works fine:

      int i;
      for (i=3, ts=0; i>=0; --i) ts = (ts<<8) | a[i];
+1
source

All Articles