为什么 p &key3 + 2 和 p (int*)&key3 + 2 会在 LLVM 中打印不同的结果?
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);
}
}
我在 macOS 10.12 上使用 Xcode7.
测试了这些代码
问题可以简单描述为
为什么&key3 == (int*)&key3
但是&key3 + 2 != (int*)&key3 + 2
和&key3 + 2 == (int*)&key3 + 4
使用 XCode7
时
我从 argv 设置了 key3 和 key4,我想从 process_keys34(&key3, &key4);//first time
跳到
msg2 = extract_message2(start, stride);//jump to here
.
所以我必须更改 func process_key34 的 return 地址的值。
因为&key3和return地址之间有一个var key4,所以我应该给&key3加2,也就是说key3应该是2.But其实key3一定是4,那么结果就对了。
然后在 lldb 中做一些测试。
我发现
(lldb) p *(&key3 + 2)
(int *) = 0x0000000100000ec3 //that's right.
但是
(lldb) p *((int*)&key3+2)
(int) = 1606416192// I dont know what does that mean.
然后我测试一下
(lldb) p &key3
(int **) = 0x00007fff5fbff6d8
(lldb) p (int*)&key3
(int *) = 0x00007fff5fbff6d8
我发现这两个是一样的。
但&key3 + 2 ,(int*)&key3 + 2
彼此不同。
(lldb) p &key3 + 2
(int **) = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 2
(int *) = 0x00007fff5fbff6e0
和&key3 + 2 ,(int*)&key3 + 4
是一样的
(lldb) p &key3 + 2
(int **) = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 4
(int *) = 0x00007fff5fbff6e8
我发现 &key3 是 int**,而 (int*)&key3 是 int*,这是这两个命令之间的唯一区别。但是我还是不明白为什么会这样。
因为按照C99,+右边的部分会变成左边的同一类型,也就是说intger 2会变成int*或者int**。但是我觉得这些没有区别,因为sizeof(int*) == sizeof(int**).
我不知道为什么会这样。谁能帮帮我?
因为 &key3
和 (int *)&key3
(注意我认为 key3
是一个 int *
)没有相同的类型。
这个名字叫pointer arithmetic.
在某个系统上 sizeof(int) != sizeof(int *)
。所以,(int *) + 2
与 (int **) + 2
的效果不同,因为
(int *) + 2 ==> * + (2 * sizeof(int))
(int **) + 2 ==> * + (2 * sizeof(int *)).
您看到的结果没有意义(除非我们查看生成的程序集,但这不在问题范围内)。
该代码有两种未定义行为的情况。
变量 key3 和 key4 未初始化使用:
int key3, key4;
if (key3 != 0 && key4 != 0) {
下一行重新解释了一个对象 key3 的存储值,该对象的类型为 int* 且类型不兼容:
*(((int *)&key3) + *key3) += *key4;
换句话说,一个int类型被写入了一个int*类型的key3。
#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);
}
}
我在 macOS 10.12 上使用 Xcode7.
测试了这些代码问题可以简单描述为
为什么&key3 == (int*)&key3
但是&key3 + 2 != (int*)&key3 + 2
和&key3 + 2 == (int*)&key3 + 4
使用 XCode7
时我从 argv 设置了 key3 和 key4,我想从 process_keys34(&key3, &key4);//first time
跳到
msg2 = extract_message2(start, stride);//jump to here
.
所以我必须更改 func process_key34 的 return 地址的值。 因为&key3和return地址之间有一个var key4,所以我应该给&key3加2,也就是说key3应该是2.But其实key3一定是4,那么结果就对了。
然后在 lldb 中做一些测试。 我发现
(lldb) p *(&key3 + 2)
(int *) = 0x0000000100000ec3 //that's right.
但是
(lldb) p *((int*)&key3+2)
(int) = 1606416192// I dont know what does that mean.
然后我测试一下
(lldb) p &key3
(int **) = 0x00007fff5fbff6d8
(lldb) p (int*)&key3
(int *) = 0x00007fff5fbff6d8
我发现这两个是一样的。
但&key3 + 2 ,(int*)&key3 + 2
彼此不同。
(lldb) p &key3 + 2
(int **) = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 2
(int *) = 0x00007fff5fbff6e0
和&key3 + 2 ,(int*)&key3 + 4
是一样的
(lldb) p &key3 + 2
(int **) = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 4
(int *) = 0x00007fff5fbff6e8
我发现 &key3 是 int**,而 (int*)&key3 是 int*,这是这两个命令之间的唯一区别。但是我还是不明白为什么会这样。
因为按照C99,+右边的部分会变成左边的同一类型,也就是说intger 2会变成int*或者int**。但是我觉得这些没有区别,因为sizeof(int*) == sizeof(int**).
我不知道为什么会这样。谁能帮帮我?
因为 &key3
和 (int *)&key3
(注意我认为 key3
是一个 int *
)没有相同的类型。
这个名字叫pointer arithmetic.
在某个系统上 sizeof(int) != sizeof(int *)
。所以,(int *) + 2
与 (int **) + 2
的效果不同,因为
(int *) + 2 ==> * + (2 * sizeof(int))
(int **) + 2 ==> * + (2 * sizeof(int *)).
您看到的结果没有意义(除非我们查看生成的程序集,但这不在问题范围内)。
该代码有两种未定义行为的情况。
变量 key3 和 key4 未初始化使用:
int key3, key4;
if (key3 != 0 && key4 != 0) {
下一行重新解释了一个对象 key3 的存储值,该对象的类型为 int* 且类型不兼容:
*(((int *)&key3) + *key3) += *key4;
换句话说,一个int类型被写入了一个int*类型的key3。