user1941580
user1941580

Reputation: 31

C pointers nested

I can't understand code from CCS C compiler. The code is:

addr[0] =  *(((char*)&block_number)+2);

I guess that "&block_number" is address of variable named "block_number". After that I get lost.

Upvotes: 3

Views: 92

Answers (4)

emil
emil

Reputation: 1700

It is a bit difficult to say when one do not know what block_number is. Let say it is a integer with the value 0xdeadbeef:

unsigned int block_number = 0xdeadbeef;

on a little endian architecture (i.e. x86):

*(char *)&block_number is 0xef, 
*(((char *)&block_number) + 1) is 0xbe and
*(((char *)&block_number) + 2) is 0xad.

While if block_number is a char then *(((char *)&block_number) + 2) could point to a adjacent variable, let say block_number is declared on the stack:

char a = 0xab, b = 0xbc, block_size = 0xcd, c = 0xde, d = 0xef;

Then ((char *)&block_size + 2 could point to i.e. a and *(((char *)&block_size + 2) would return 0xab. Because the stack is most commonly ordered from max address to lower addresses:

heap                                              stack
[... ->     <- d    | c    | block_size | b    | a    ]
[... ->     <- 0xef | 0xde | 0xcd       | 0xbc | 0xab ]

But this is never certain as C does not put any constraints on the compiler where to locate a and the location is probably undefined.

For sizeof(char) it is always 1. char is one character, that is why you do not need to specify length*sizeof(char) to malloc if you want to allocate memory. You only do:

int length = 20;
void *mem = malloc(length);

Upvotes: 1

Kerrek SB
Kerrek SB

Reputation: 477444

  1. &block_number is the address of the object block_number.

  2. (char*)&block_number treats that address as the address of the first element in an array of bytes. Let's call this pointer p, and it is a pointer-to-char.

  3. *(((char*)&block_number)+2) is thus *(p + 2), which is identical to p[2], i.e. it denotes the third element of the array.

In other words, you are obtaining the third byte of the binary representation of the object block_number (and storing it it addr[0]).

Upvotes: 0

loganfsmyth
loganfsmyth

Reputation: 161627

Let's split this up:

*(ptr+2)

is equivalent to:

ptr[2]

Here, ptr is a char* pointing to the address of block_number.

So say block_number is an instance of a struct like this:

struct {
  char a;
  char b;
  char c;
  char d;
} block_number

Then addr[0] will contain the value of c (assuming the values are packed with no space between them). This is because the pointer to block_number is converted to a char*, and then indexed like an array.

So basically, this reads the third byte in block_number.

Upvotes: 1

Gustavo Litovsky
Gustavo Litovsky

Reputation: 2487

You're correct. &block_number is the address of that variable and it is cast to a char and a 2 added to the value. For example if &block_number is 0x0000, then addr[0] after executing the line will contain 0x0002 if the sizeof(char) on the platform is 2, or whatever the size is.

Upvotes: 0

Related Questions