C语言void指针经(unsigned int*)与(unsigned int**)强转的结果差异
测试代码
unsigned int num = 101; void * p = # void ** pp = &p; unsigned int *get_data_1 = NULL; unsigned int *get_data_2 = NULL; get_data_1 = *((unsigned int *)pp); get_data_2 = *((unsigned int **)pp);
两种强转的行为差异与结果区别
首先明确C语言指针强转的核心逻辑:对指针做强制类型转换,本质是告诉编译器「按照转换后目标类型的规则访问这个指针指向的内存」,解引用时读取的字节长度、对读取内容的解释规则,完全由转换后的指针类型决定。
两个变量的结果和系统类型长度直接相关:32位环境下指针和unsigned int长度都是4字节,两个变量可能碰巧值相等,但代码逻辑本质完全不同;64位环境下指针长度为8字节、unsigned int长度为4字节,二者值存在本质区别:
get_data_2的赋值是符合类型逻辑的正确行为
把pp转为unsigned int **,相当于告诉编译器这个地址存放的是一个unsigned int*类型的指针。后续解引用时,会读取对应内存位置完整指针长度的内容,也就是指针变量p存储的值——即num的内存地址。最终get_data_2会正确指向num,解引用*get_data_2就能拿到值101。get_data_1的赋值是存在未定义风险的错误写法
把pp转为unsigned int *,相当于告诉编译器这个地址存放的是一个unsigned int类型的整数。后续解引用时,只会读取对应内存位置4字节长度的内容,拿到的是指针p存储的地址值的一部分(小端系统取低4字节、大端系统取高4字节),本质是被截断的地址碎片。把这个碎片值赋值给get_data_1后,它根本不指向num的合法地址,直接解引用大概率触发程序崩溃。
提醒:不要依赖32位环境下的偶然正确结果,这种截断指针的写法违反C语言类型访问规则,完全不可移植,生产代码中绝对不能使用。
内容的提问来源于stack exchange,提问作者Tinchu
相关产品推荐
相关产品推荐

