#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编译它。
答案 0 :(得分:5)
在堆栈上分配了两个变量y
和p
。它们的存储彼此相邻,看起来像这样:
y: <addr1> <val1> 4 bytes
p: <addr2> <val2> 8 bytes
请注意,<addr2>
为<addr1> + 4
。
对于您的示例,实际地址如下所示:
y: 0x00007ffe2368f2e4 <value1> 4 bytes
p: 0x00007ffe2368f2e8 <value2> 8 bytes
在y = 1
和p = &y
之后,内存如下所示:
y: 0x00007ffe2368f2e4 0x00000001 4 bytes
p: 0x00007ffe2368f2e8 0x00007ffe2368f2e4 8 bytes
p + 1
的值为p
+ sizeof(int)
,即0x00007ffe2368f2e4 + 4
,即0x00007ffe2368f2e8
,即p
的地址。
*(p + 1) = 10
在0x00007ffe2368f2e8
到10
设置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,则0x7ffe2368f2e4
是y
的地址,0x7ffe2368f2e8
是被覆盖的指针p本身占用的内存的地址。
答案 4 :(得分:0)
另一种思考方式是因为y就像一个1整数的数组(只有y [0]存在。代码:
*(a+i) equals a[i]
按定义。所以,从那以后:
p = &y
然后:
*(p+1) equals y[1]
并访问不存在的行为是未定义的行为。这意味着任何事情都可能发生,但最可能发生的两件事是:(1)您访问其他变量(发生在您身上的事情)或(2)程序出现分段错误。