steveyyy steveyyy - 1 month ago 11
C Question

Why p &key3 + 2 and p (int*)&key3 + 2 will print different result in LLVM?

#include <stdio.h>
#include <stdlib.h>
void process_keys34 (int * key3, int * key4) {

*(((int *)&key3) + *key3) += *key4;
}
int main (int argc, char *argv[])
{
int key3, key4;
if (key3 != 0 && key4 != 0) {
process_keys34(&key3, &key4);//first time
}

if (true) {
process_keys34(&key3, &key4);
msg2 = extract_message2(start, stride);//jump to here
printf("%s\n", msg2);
}
}


I test these code on macOS 10.12 use the Xcode7.

The question can be described simply as

Why
&key3 == (int*)&key3


but
&key3 + 2 != (int*)&key3 + 2


and
&key3 + 2 == (int*)&key3 + 4


when using XCode7

I set the key3 and key4 from the argv, I want jump from
process_keys34(&key3, &key4);//first time
to

msg2 = extract_message2(start, stride);//jump to here
.

So I must change the value of the func process_key34's return address.
Because there is a var key4 between &key3 and return address, so i should add 2 to &key3, which means key3 should be 2.But the truth is that key3 must be 4, then the result is right.

Then do some test in lldb.
I found that

(lldb) p *(&key3 + 2)
(int *) $6 = 0x0000000100000ec3 //that's right.


but

(lldb) p *((int*)&key3+2)
(int) $8 = 1606416192// I dont know what does that mean.


then I test that

(lldb) p &key3
(int **) $5 = 0x00007fff5fbff6d8
(lldb) p (int*)&key3
(int *) $7 = 0x00007fff5fbff6d8


I found these two are same.

but
&key3 + 2 ,(int*)&key3 + 2
are different from each another.

(lldb) p &key3 + 2
(int **) $9 = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 2
(int *) $10 = 0x00007fff5fbff6e0


and
&key3 + 2 ,(int*)&key3 + 4
are the same

(lldb) p &key3 + 2
(int **) $9 = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 4
(int *) $14 = 0x00007fff5fbff6e8


I found that &key3 is int**, and (int*)&key3 is int* which is the only difference between these two commands. But I still cant understand why did that happen.

Because accroding to C99, the right part of the + will change to the same type of the left, which means intger 2 will chage to int* or int**. But I think these have no difference, because sizeof(int*) == sizeof(int**).

I don't know why did that happen. Can any one give me some help?

Answer

Cause &key3 and (int*)&key3 (note that i consider that key3 is type of int *) has not same type.

It's call pointer arithmetic.

On a 64bit system sizeof(int) != sizeof(int *). So add (int *) + 2 as not the same effect that (int **) + 2 because

(int *) + 2 ==> * + (2 * sizeof(int))

(int **) + 2 ==> * + (2 * sizeof(int *)).

doc here Pointer Arithmetic

Comments