Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointers behaviour in different datatype

Tags:

c

pointers

struct

struct check{
unsigned short a;
unsigned short b;
};

static unsigned char v[5] = {1,2,3,4,5};
struct check *p = (struct check *)v;

printf("%d",p->a);
printf("\t%d",p->b);

The answer is 513 and 1027. I am not able to get why it is happening. Can anybody help me on understanding the concept.

like image 532
Rakesh_Kumar Avatar asked Feb 15 '23 21:02

Rakesh_Kumar


2 Answers

It's not a good idea to cast pointers like this.

Probably, unsigned short is 2 bytes on your machine, and after the cast, p->a gets the value 0x0201, which is decimal 513, and p->b gets the value of 0x0403, which is decimal 1027.

Note that the result will be different on a machine with different endianess. For example, on my machine, the output is 258 (0x0102) and 772 (0x0304).

Also note that you should use format specifier %u to print values of unsigned type:

printf("%u\t%u\n", p->a, p->b);
like image 147
Yu Hao Avatar answered Feb 17 '23 11:02

Yu Hao


Updated

Here's what appears to be happening... The array of characters is laid out in memory as follows:

v+0: 0x01
v+1: 0x02
v+2: 0x03
v+3: 0x04
v+4: 0x05

When you cast v to be of type struct check * and dereference it, this region of memory is being reinterpreted as follows:

p->a: 0x0201 (v+1, v+0)
p->b: 0x0403 (v+3, v+2)

0x0201 in hexadecimal is equal to 513, and 0x0403 is equal to 1027.

Additional thoughts...

It's important to note that you can't guarantee anything about the behavior of your code. For starters, dereferencing p is a strict aliasing violation. See What is the strict aliasing rule? for an explanation of the strict aliasing rule as well as a list of other factors that affect this type of code.

like image 26
godel9 Avatar answered Feb 17 '23 09:02

godel9