Question

I have this program:

#include <stdio.h>

int main(void)
{
    unsigned char unit_id[] = { 0x2B, 0xC, 0x6B, 0x54}; // 8-bit (1 byte)
    unsigned long long int unit_id_val; //64-bit (8 bytes)
    int i;

    // loops 4 times
    for(i=0;i<sizeof(unit_id)/sizeof(char);i++){
      unit_id_val |= unit_id[i] << (8 * i);
    }

    printf("the unit id is %llu\n", unit_id_val);
    return 0;
}

hex to binary conversions:

0x2B = 00101011
0xC  = 00001100
0x6B = 01101011
0x54 = 01010100

unit_id_val is 8 bytes (I use 5 bytes for unit_id_val below to simplify things)

1) first iteration 8*0=0 so no left shift occurs:

00101011 = 00101011 << 0
00000000 00000000 00000000 00000000 00000000 |= 00101011

So the result should be:

00000000 00000000 00000000 00000000 00101011

2) Second iteration 8*1=8, so left shift all bits of unsigned char 0xC by 8:

00000000 = 00101011 << 8
00000000 00000000 00000000 00000000 00101011 |= 00000000

So the result should be:

00000000 00000000 00000000 00000000 00101011

3) Third iteration 8*2=16, so left shift all bits of unsigned char 0x6B by 16:

00000000 = 01101011 << 16
00000000 00000000 00000000 00000000 00101011 |= 00000000

So the result should be:

00000000 00000000 00000000 00000000 00101011

4) Fourth iteration 8*3=24, so left shift all bits of unsigned char 0x54 by 32:

00000000 = 01010100 << 32
00000000 00000000 00000000 00000000 00101011 |= 00000000

So the result should be:

00000000 00000000 00000000 00000000 00101011 

00101011 is 43

But when you run this program you get

1416301611

which is binary:

00010100 00010110 00110000 00010110 00010001

I am not understanding something here. I am following the precedence chart by evaluating primary expression operator () before evaluating left shift operator << before evaluating assignment operator !=. Yet I am not understanding why I get the response I get.

Was it helpful?

Solution

00000000 = 00101011 << 8

Ok first your second element is 0x0C (i.e., binary 00001100 not 00101011), so you are actually doing:

(unsigned char) 0x0C  << 8

and the result of this expression is not 0 but 0x0C00 as the bitwise << operator does an integer promotion of its left operand, so it is actually equivalent to:

(int) (unsigned char) 0x0C << 8

OTHER TIPS

You never initialize unit_id_val, and then you |= your shifted byte values into it, so whatever bits happened to be set in the uninitialized value will still be set, so your output will look like random garbage. Add

unit_id_val = 0;

before your loop.

In addition, whenever you do ANY operation in C, the operands are always converted by the standard conversions. In particular, that means any integer type smaller than an int will first be converted to int. So even though unsigned char is only 8 bits, when you do unit_id[i] << (8 * i), the 8-bit value from unit_id[i] will be converted to int (presumably 32 bits on your machine) before the shift. There's no way to do any sort of computation on integers smaller than an int in C -- even if you cast them, they'll be implicitly converted back to int.

see in this line

unit_id_val |= unit_id[i] << (8 * i);
unit_id_val = unit_id_val | unit_id[i] << (8 * i);

the problem is you are using a variable which is only declare but not initialized and we know that in c uninitialized variable default value is garbage or junk. So each and every time without any doubt you will get some unpredictable value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top