scanf中short指针地址异常:地址改变及长度差异原因问询
你的代码问题拆解:格式符误用导致的两个经典坑
嘿,咱们把你遇到的两个问题拆开说,其实都是格式符和变量类型不匹配惹的祸,属于C语言里很容易踩的栈溢出和未定义行为坑!
1. 为什么调用scanf后指针pt的地址变了?
先看你代码里的这行:
scanf("%d",&a);
这里a是short类型(通常占2字节),但你用了%d格式符——这个格式符要求读取的是int类型的数据(多数系统里int是4字节)。当scanf执行时,它会从输入读取4字节的int数据,然后往&a指向的内存地址里写。但a只有2字节的空间,剩下的2字节就会溢出到栈上紧跟在a后面的变量,也就是pt的内存区域里,直接把pt的指针值给改写了!
简单说:你用大尺寸的类型写入小尺寸的变量,溢出的内容破坏了相邻的指针变量,所以你看到pt的地址“变了”——其实是被非法覆盖了。
2. 为什么指针地址和short变量地址的输出长度有差异?
再看你的printf语句:
printf("%x, %p\n",&a,pt);
这里的问题出在格式符的选择上:
%x是用来打印unsigned int类型的(多数系统是4字节),但&a是一个指针(64位系统里指针是8字节,32位是4字节)。当你用%x打印指针时,只会输出指针的低4字节,相当于截断了高位,所以看起来长度短。%p是C标准里专门用来打印指针的格式符,它会根据系统位数输出完整的指针长度(64位是8字节,带0x前缀),所以和%x的输出长度不一样。
另外要注意:用%p打印指针时,标准要求把指针强制转换成void*类型,虽然有些编译器允许直接传,但严格来说要转,保证代码的可移植性。
修正后的代码
把格式符都改成匹配的类型,问题就解决了:
short a,*pt=&a; // 打印指针统一用%p,&a转成void*符合标准要求 printf("%p, %p\n", (void*)&a, pt); // 读取short用%hd,匹配变量类型 scanf("%hd",&a); printf("%p, %p\n", (void*)&a, pt);
这样修改后,scanf不会再溢出破坏pt,地址输出也会是一致的完整长度啦!
内容的提问来源于stack exchange,提问作者D.Joe
相关产品推荐
相关产品推荐

