当任何值分配给*(p + 1)时,为什么指针p的值发生了变化?

时间:2016-01-10 20:57:29

标签: c pointers

#include <stdio.h>
int main(void){
    int* p = NULL;
    int y = 1;
    p = &y;
    printf("%p\n",p);
    *(p+1) = 10;
    printf("%p\n",p);
    return 0;
}

输出:

  

0x7ffe2368f2e4
  0x7ffe0000000a

我不知道为什么p在这里被改变而第二个有&#34; 0000000a&#34;这到底是10,你能帮帮我吗?谢谢。我在linux中用gcc编译它。

5 个答案:

答案 0 :(得分:5)

在堆栈上分配了两个变量yp。它们的存储彼此相邻,看起来像这样:

y: <addr1> <val1>  4 bytes
p: <addr2> <val2>  8 bytes

请注意,<addr2><addr1> + 4

对于您的示例,实际地址如下所示:

y: 0x00007ffe2368f2e4 <value1>  4 bytes
p: 0x00007ffe2368f2e8 <value2>  8 bytes

y = 1p = &y之后,内存如下所示:

y: 0x00007ffe2368f2e4 0x00000001          4 bytes
p: 0x00007ffe2368f2e8 0x00007ffe2368f2e4  8 bytes

p + 1的值为p + sizeof(int),即0x00007ffe2368f2e4 + 4,即0x00007ffe2368f2e8,即p的地址。

*(p + 1) = 100x00007ffe2368f2e810设置4个字节。

这将覆盖0x00007ffe2368f2e8处8字节值的4个字节,这是p值的4个字节。

0x7ffe 2368f2e4
0x7ffe 0000000a ------> this is the lower 4 bytes set to 10 i.e. 0xa

答案 1 :(得分:3)

  

指针指向的地址变化是什么原因?

TL; DR - Evaluate

在您的代码中详细说明

void*
当您尝试访问超出范围的内存时,

会调用undefined behavior。请注意,只有 UB 的许多可能副作用之一的分段错误。

一旦你的代码调用UB,没有任何东西,绝对没有任何保证。

另外,FWIW,要打印指针,您应该将指针转换为%p,然后再将其作为SELECT `b`.*, COUNT(`bl`.`broadcast_id`) AS `total_likes`, COUNT(`bv`.`broadcast_id`) AS `total_viewers` FROM `broadcasts` `b` LEFT JOIN `broadcasts_likes` `bl` ON `b`.`broadcast_id` = `bl`.`broadcast_id` LEFT JOIN `broadcasts_viewers` `bv` ON `b`.`broadcast_id` = `bv`.`broadcast_id` GROUP BY `b`.`broadcast_id`; 的参数。

答案 2 :(得分:2)

正如其他人所说,这句话引用了未定义的行为:

*(p+1) = 10;

自此声明之前,p包含y的地址,其类型为int。所以上面的语句写入了一个不是y的内存区域。

至于实际发生的事情的解释,似乎p出现在堆栈上的y之后。因此,当您执行*(p+1) = 10;时,它会在堆栈上的sizeof(int)之后写入y个字节,这恰好是p所在的位置。

基于p的初始值为0x7ffe2368f2e4的事实,它告诉我们sizeof(int *)至少为6个字节,最可能为8个(即64位)。在赋值后,值变为0x7ffe0000000a,我们看到p的4个低位字节被修改。如果sizeof(int)为4并且您正在使用小端架构,那么这将是有意义的。因此,赋值最终将p的前4个字节(低位字节)设置为值10,而其余的(高位字节)保持不变。

这就是你的具体情况。无法保证此行为在不同的计算机,编译器或操作系统中保持一致。换句话说,未定义的行为。

答案 3 :(得分:0)

本声明

*(p+1) = 10;

更改指针,因为它会覆盖指针占用的内存。

从输出值中可以看出

0x7ffe2368f2e4 0x7ffe0000000a

0x0000000a的此部分0x7ffe0000000a恰好等于10,分配给地址p + 1的内存

所以在地址p + 1处有指针p本身。

如果sizeof( int )等于4,则0x7ffe2368f2e4y的地址,0x7ffe2368f2e8是被覆盖的指针p本身占用的内存的地址。

答案 4 :(得分:0)

另一种思考方式是因为y就像一个1整数的数组(只有y [0]存在。代码:

*(a+i)  equals  a[i]

按定义。所以,从那以后:

p = &y

然后:

*(p+1)  equals  y[1]

并访问不存在的行为是未定义的行为。这意味着任何事情都可能发生,但最可能发生的两件事是:(1)您访问其他变量(发生在您身上的事情)或(2)程序出现分段错误。