C语言中int类型存入long long类型时底层技术层面发生了什么?
底层运行逻辑说明
你遇到的现象本质是scanf格式说明符与传入参数类型不匹配触发的未定义行为,和正常场景下int转long long的隐式类型转换完全无关,具体执行过程如下:
- 64位编译环境下的基础长度约定:
int占4字节,long long占8字节。scanf的%d格式符要求传入int*类型的地址,只会向对应内存空间写入4字节的int数据。 - 代码中定义的局部变量
a、b为long long类型,存储在栈内存中,未手动初始化的前提下,初始值为栈空间残留的随机垃圾数据,8个字节全部为未知内容。 - 调用
scanf时你传入的是long long*类型的地址,与%d的要求不符:输入的123只会写入a对应的8字节内存的低4位,高4位仍然保留原有随机垃圾值;同理输入的-123只会写入b的低4位,高4位同样是随机值。 - 最后用
%lld输出a+b的结果时,程序会读取a和b完整的8字节值做计算,因为高4位都是随机垃圾值,最终的计算结果自然是随机乱码,且每次运行时栈内存的初始残留值不同,输出结果就会每次发生变化。
正常int存入long long的底层逻辑
如果是合法的int类型值赋值给long long变量,属于标准的隐式类型转换,编译器会自动做符号扩展,不会出现异常:
- 如果原int是正数,会把long long的高4位全部补0,低4位保留int的原值,最终值和原int值完全一致
- 如果原int是负数(采用补码存储),会把long long的高4位全部补1,低4位保留int的原值,最终值和原int值也完全一致
为什么没有编译报错
C语言标准没有强制要求编译器检查scanf格式符与参数的匹配性,这类问题属于运行期的未定义行为,不属于语法错误。部分编译器开启高警告等级时会给出对应提示(比如GCC添加-Wall编译参数),但不会直接阻断编译,你使用的在线编译器默认未开启高等级警告,因此不会给出任何错误提示。
内容的提问来源于stack exchange,提问作者dev-JasonYoo
相关产品推荐
相关产品推荐

