You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:06:45