将一级指针*赋值给二级指针**时的运行原理是什么?
一级指针转二级指针的运行逻辑解释
核心本质
你遇到的现象本质是强制类型转换篡改了指针的类型语义,指针的取值行为完全由它的类型决定,和它存储的地址值本身无关。
逐行代码运行拆解
我们先假设测试环境为64位系统,int占4字节,指针占8字节,value变量的栈地址为0x7ffdabcdef10,逐行看运行逻辑:
int value = 100;
在栈上申请4字节内存,存储二进制值0x00000064(对应十进制100),这块内存的起始地址为0x7ffdabcdef10。
int *ptr = &value;
定义一级int指针ptr,它的类型语义是「指向一块存储int类型的内存」,它本身存储的值就是value的地址0x7ffdabcdef10。
int **p_to_p = (int**)ptr;
这是出现异常的核心行:
- 你通过C风格强制转换,把
int*类型的ptr强转成int**类型,直接赋值给二级指针p_to_p - 赋值操作仅拷贝地址值,所以
p_to_p存储的值和ptr完全相同,都是0x7ffdabcdef10 int**的类型语义是「指向一块存储int*类型指针的内存」,这个语义已经和实际内存存储的内容(int类型的100)不匹配了。
cout << p_to_p << " " << ptr << endl;
这里输出的是两个指针本身存储的地址值,因为赋值时直接拷贝了数值,所以二者输出完全一致。
cout << *p_to_p << " " << *ptr << endl;
解引用时会严格按照指针类型读取、解析内存,所以二者输出差异极大:
*ptr:ptr是int*类型,解引用时会从地址0x7ffdabcdef10读取4字节,解析为int类型,结果就是100*p_to_p:p_to_p是int**类型,解引用时会从地址0x7ffdabcdef10读取8字节(64位系统下指针长度),前4字节是100的二进制值,后4字节是栈上的随机垃圾数据,最终解析出的指针值是一个和100无关的随机大数。
正确的二级指针赋值方式
如果要让二级指针正常指向一级指针,应该把一级指针本身的地址赋值给二级指针:
int **p_to_p = &ptr;
此时:
p_to_p存储的是ptr变量本身的栈地址*p_to_p就是ptr存储的值,也就是&value**p_to_p就是value的值100
注意
你代码中的强制类型转换属于C++标准规定的未定义行为,实际输出结果会随系统位数、字节序、栈内存布局的变化而变化,没有固定结果。
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

