为什么p& key3 + 2和p(int *)& key3 + 2会在LLVM中打印出不同的结果?

时间:2016-10-27 05:50:53

标签: c++ c pointers xcode7 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的返回地址的值。 因为&amp; key3和返回地址之间有一个var key4,所以我应该将2添加到&amp; key3,这意味着key3应该是2.但事实是key3必须是4,那么结果是正确的。

然后在lldb做一些测试。 我找到了

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

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

然后我测试了

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

我发现这两个是相同的。

&key3 + 2 ,(int*)&key3 + 2彼此不同。

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

&key3 + 2 ,(int*)&key3 + 4是相同的

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

我发现&amp; key3是int **,而(int *)&amp; key3是int *,这是这两个命令之间的唯一区别。但我仍然无法理解为什么会这样。

因为累加到C99,+的右边部分将改为左边的相同类型,这意味着intger 2将变为int *或int **。但我认为这些没有区别,因为sizeof(int *)== sizeof(int **)。

我不知道为什么会这样。任何人都能给我一些帮助吗?

2 个答案:

答案 0 :(得分:3)

您看到的结果没有意义(除非我们查看生成的程序集,但这不在问题范围内)。

代码有两种未定义的行为。

变量key3和key4未初始化使用:

int key3, key4;
if (key3 != 0 && key4 != 0) {

以下行重新解释了对象key3的存储值,该对象具有类型int *且类型不兼容的int:

*(((int *)&key3) + *key3) += *key4;

换句话说,类型int被写入key3,其类型为int *。

答案 1 :(得分:0)

原因&key3(int *)&key3(请注意,我认为key3int *)的类型不同。

这名为pointer arithmetic

在某个系统sizeof(int) != sizeof(int *)上。因此,(int *) + 2(int **) + 2的效果不同,因为

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

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