C语言中void指针两种取值方式的差异与段错误原因解析
两种写法的本质差异
先明确调用时的关键细节:你调用函数时传入的(void*)40是把整数40直接当作指针值传递,而非传递一个指向存储着40的内存地址的指针。
原写法触发段错误的原因
原代码:
unsigned int roll_no = *(unsigned int*)(key);
这里的key是void*类型,存储的数值是40。你把它强转成unsigned int*后解引用,相当于试图访问内存地址0x28(40的十六进制)。这个地址属于操作系统保留或无效内存空间,程序无权限读写,因此触发段错误。
修改后写法能运行的逻辑
修改后的代码:
unsigned int roll_no = *(unsigned int*)(&key);
这里的&key取的是函数参数key本身在栈上的内存地址。key是一个void*变量,里面存储着你传入的40。把&key强转成unsigned int*再解引用,本质是把key这个指针变量里的数值(40)当作unsigned int读取出来——多数系统中void*和unsigned int的字节长度一致(比如32位系统均为4字节),因此能正确拿到目标roll_no值,不会触发段错误。
额外提醒:这种写法的隐患
虽然当前运行正常,但*(unsigned int*)(&key)依赖void*与unsigned int的字节长度匹配,在64位系统搭配32位int的架构下会出问题。更规范的写法有两种:
- 直接把
key强转为unsigned int:unsigned int roll_no = (unsigned int)key; - 调用时传递真正的指针:
此时原写法的解引用逻辑就能正常工作。unsigned int target_roll = 40; check_student_by_roll_number(john, &target_roll);
内容的提问来源于stack exchange,提问作者stardep
相关产品推荐
相关产品推荐

