tags:

views:

84

answers:

4

So my code has in it the following:

unsigned short num=0;
num=*(cra+3);
printf("> char %u\n",num);

cra is a char*

The problem is that it is getting odd output, sometimes outputting numbers such as 65501 (clearly not within the range of a char). Any ideas?

Thanks in advance!

+6  A: 

Apparently *(cra+3) is a char of value '\xdd'. Since a char is signed, it actually means -35 (0xdd in 2's complement), i.e. 0x...fffffdd. Restricting this to 16-bit gives 0xffdd, i.e. 65501.

You need to make it an unsigned char so it gives a number in the range 0–255:

num = (unsigned char)cra[3];

Note:
1. the signedness of char is implementation defined, but usually (e.g. in OP's case) it is signed.
2. the ranges of signed char, unsigned char and unsigned short are implementation defined, but again commonly they are -128–127, 0–255 and 0–65535 respectively.
3. the conversion from signed char to unsigned char is actually -35 + 65536 = 65501.

KennyTM
hurrr, of course, thank you. will be accepting in 9 minutes.
Cenoc
A `char` may also be unsigned. In this case it is not, but in general it may.
Roland Illig
If the char really had the *value* `0xdd`, which is 221, then it would simply remain as 221 when converted to `unsigned short`. It likely actually has the value -35 (which in two's complement would have the same representation as the unsigned 8 bit value `0xdd`).
caf
@caf: excellent point about *value* versus *representation*.
R..
A: 

cra is just a pointer.

It hasn't been allocated any space, by way of malloc or calloc. So its contents are undefined . *(cra + 3) will evaluate to the contents of the location 3 bytes ahead of the location cra (assuming char occupies 1 byte). I believe that its contents are also undefined.

unsigned short takes up 2 bytes, atleast on my system. Hence it can hold values from 0 to 65536. So, your output is within its defined range

Kedar Soparkar
+2  A: 

char is allowed to be either signed or unsigned - apparently, on your platform, it is signed.

This means that it can hold values like -35. Such a value not within the range representable by unsigned short. When a number out of range is converted to an unsigned type, it is brought into range by repeatedly adding or subtracting one more than the maximum value representable in that type.

In this case, your unsigned short can represent values up to 65535, so -35 is brought into range by adding 65536, which gives 65501.

caf
@Hogan: This doesn't actually rely on the internal representation of the numbers - it's how C is specified to work, regardless of internal representation. It's a no-op on two's complement machines, but sign-magnitude and ones' complement implementations have to do extra work on signed-to-unsigned conversions to be correct.
caf
A: 

unsigned short has a range of (at least) 0 .. 65535 (link), the %u format specifier prints an unsigned int with a range of (commonly) 0 .. 4294967295. Thus, depending on the value of cra, the output appears to be completely sensible.

Chris