1613551 发表于 2022-6-9 20:56:07

为什么变量 a 和 b 的值会变成 1 和 2

小甲鱼这个解释把我看懵了,什么叫做p 指针的 “眼界” 被强制调整为一个整形变量的宽度?

#include <stdio.h>

int main(void)
{
      char a = 0, b = 0;
      int *p = (int *)&b;

      *p = 258;

      printf("%d %d\n", a, b);

      return 0;
}

jackz007 发表于 2022-6-9 21:21:40

本帖最后由 jackz007 于 2022-6-9 23:34 编辑

       一个字节的表达范围限于 0 ~ 255(0x00 ~ 0xff),258 的十六进制形式是 0x0102,也就是说已经超出了单个字节的表达范围,p 指向了char 型的变量 b,而 char a 与 char b 各占用一个字节空间,而且,两个变量占用的存储空间相邻,当执行
* p = 256
       时,会写 4 个字节到变量 b 开始的内存位置,由于 Intel 采用 Little Endian 编码格式,组成 258(0x0102) 的 4 个字节的顺序是 0x02 、0x01、0x00、0x00,这样,变量 b 的所属存储首先获得字节 0x02,其余字节继续侵入后续存储空间,这样,变量 a 获得后续字节 0x01,当然,其余两个 0x00 侵占的是位于变量 a 以后的存储空间。这样,a 的值变成了 1(0x01),b 的数值变成了 2(0x02)。

风车呼呼呼 发表于 2022-6-10 10:51:14

解析上的三个表描述的是同一片内存空间,地址从左到右是由低向高,一共四字节。
想要完全理解,需要有一些额外知识,比如函数调用栈,大小端模式。具体只言片语讲不清楚,远不如你直接查相关资料配合示意图理解来得轻松。

了解函数调用栈,你会知道为什么表一中,变量a、b的内存位置会是那样。
将变量b的地址赋值给int指针p,而p指针指向的是一个int型变量(4字节),这个int型变量的内存空间就是表二那样,它包含了原本char型变量a、b的内存空间,以及其往后的两字节空间(如果最后两字节存着其他变量,那事实上其他变量的数据也会被破坏)
258二进制码为:1 0000 0010一共9位,字节是内存分配的最基本单位,所以需要两字节,即 0000 0001 0000 0010. 了解大小端模式,你会知道为什么这两字节会以表三的样子存在原本a、b的内存空间中,为什么看起来是 0000 0010 0000 0001 “反着”放的。

最后,虽然说是两字节,但因为int占4字节,后面另两字节并不是不管,而是全为0,如果变量声明是这样:char c = 1, d = 1, a = 0, b = 0;
那么除了a、b的值改变外,c、d的值同样会变为0
页: [1]
查看完整版本: 为什么变量 a 和 b 的值会变成 1 和 2