RLH
RLH

Reputation: 15698

How can I cast a char to an unsigned int?

I have a char array that is really used as a byte array and not for storing text. In the array, there are two specific bytes that represent a numeric value that I need to store into an unsigned int value. The code below explains the setup.

char* bytes = bytes[2];
bytes[0] = 0x0C; // For the sake of this example, I'm 
bytes[1] = 0x88; // assigning random values to the char array.

unsigned int val = ???; // This needs to be the actual numeric 
                        // value of the two bytes in the char array.  
                        // In other words, the value should equal 0x0C88;

I can not figure out how to do this. I would assume it would involve some casting and recasting of the pointers, but I can not get this to work. How can I accomplish my end goal?

UPDATE

Thank you Martin B for the quick response, however this doesn't work. Specifically, in my case the two bytes are 0x00 and 0xbc. Obviously what I want is 0x000000bc. But what I'm getting in my unsigned int is 0xffffffbc.

The code that was posted by Martin was my actual, original code and works fine so long as all of the bytes are less than 128 (.i.e. positive signed char values.)

Upvotes: 12

Views: 43380

Answers (6)

xanatos
xanatos

Reputation: 111940

unsigned int val = (unsigned int)(unsigned char)bytes[0] << CHAR_BIT
                   | (unsigned int)(unsigned char)bytes[1];

This if sizeof(unsigned int) >= 2 * sizeof(unsigned char) (not something guaranteed by the C standard)

Now... The interesting things here is surely the order of operators (in many years still I can remember only +, -, * and /... Shame on me :-), so I always put as many brackets I can). [] is king. Second is the (cast). Third is the << and fourth is the | (if you use the + instead of the |, remember that + is more important than << so you'll need brackets)

We explicitly cast the unsigned chars to unsigned ints because if we didn't, C would automatically promote them to signed ints instead. The extra cast avoids some signed overflow headaches, especially if this code ever gets modified to use 4 chars instead of 2.

I'll add that if you want less headaches:

unsigned int val = (unsigned int)(unsigned char)bytes[0] << CHAR_BIT;
val |= (unsigned int)(unsigned char)bytes[1];

Upvotes: 17

Ian Proctor
Ian Proctor

Reputation: 1

I never know quite what the compiler is going to do behind the scenes with implicit casting, so I generally try to use explicit bitwise operations. eg:

unsigned int val = 0;
val |= bytes[0]<<8;
val |= bytes[1];

here I'm using the bitwise or, which basically copies the bits in when used on a variable holding the value 0. You can mess around with this to change endianness or any other formatting you want to do.

Upvotes: 0

Chuck
Chuck

Reputation: 237110

I think this is a better way to go about it than relying on pointer aliasing:

union {unsigned asInt; char asChars[2];} conversion;
conversion.asInt = 0;
conversion.asChars[0] = 0x0C;
conversion.asChars[1] = 0x88;
unsigned val = conversion.asInt;

Upvotes: 0

Jens Erat
Jens Erat

Reputation: 38732

unsigned int val = (unsigned char) bytes[0]<<8 | (unsigned char) bytes[1];

Upvotes: 4

TJD
TJD

Reputation: 11896

The byte ordering depends on the endianness of your processor. You can do this, which will work on big or little endian machines. (without ntohs it will work on big-endian):

unsigned int val = ntohs(*(uint16_t*)bytes)

Upvotes: 1

Martin Beckett
Martin Beckett

Reputation: 96167

unsigned int val = bytes[0] << 8 + bytes[1];

Upvotes: 0

Related Questions