定义一个long long类型,用%d打印的结果

这几天复习了一下整形提升,正好发现一个令我非常困惑的问题:

#include <stdio.h>
int main()
{
	long long a = 1, b = 2, c = 3;
	printf("%lld %lld %lld\n", a, b, c);
	printf("%d %d %d\n", a, b, c);
	return 0;
}

输出结果:
在这里插入图片描述
那么问题来了,%lld输出没问题,就是long long int类型,但是为什么%d输出就成了1 0 2了呢?
我们先来看如下代码:

#include <stdio.h>
int main()
{
	long long a = 1, b = 2, c = 3;
	printf("%lld %lld %lld\n", a, b, c);
	printf("%d %d %d %d %d %d\n", a, b, c);
	return 0;
}

输出结果:
在这里插入图片描述
我们好像发现了什么,我对上面的现象解释如下:
因为a、b、c是long long类型,所以为64位数,在打印的时候,分割成6个32位数,%d每次只能读取其中的32位,第一个%d读第一个32位数,也就是1的低32位(1),第二个%d读第二个32位数,也就是1的高32位(0),第三个%d读第三个32位数,也就是2的低32位(2),所以结果就是1 0 2。
因为是小端存储,低位放在低地址处,高位放在高地址处,而指针是从低地址增加,所以先读到低32位,后读到高32位。
这里需要注意的是分割的时候针对的是补码,但是正数原反补相同。
请看如下代码:

#include <stdio.h>
int main()
{
	long long a = -2;
	printf("%lld\n", a);
	printf("%d %d\n", a);
	return 0;
}

因为-2是负数,所以在a中存储补码为:
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111110。
分割为两个32位数,最后输出结果如下:
在这里插入图片描述
正好低32位11111111 11111111 11111111 11111110对应int为-2,高32位11111111 11111111 11111111 11111111对应int为-1。

再看一个例子:

#include <stdio.h>
int main()
{
	int a = 1, b = 2;
	printf("%d\n", a, b);
	printf("%hd %hd\n", a, b);
	return 0;
}

按照上面的推理,short int对应两个字节,int对应4个字节,那打印的时候应该把a和b分割成两个双字节的数,然后结果应该是1 0。也就是a的低16位和a的高16位,但是请看结果:
在这里插入图片描述
为什么和预想的不一样呢?
我给出的解释是:不管是什么类型,最后分割的时候都分割成32位,如果原来不够32位(比如说char类型),那么就进行整形提升变成32位,然后在读取并且打印的时候,%lld是读取两个32位,也就是读取了long long类型,%d、%hd、%c读取的则是32位,也就是不管是百分号什么,读取的都是32的整数倍。假若说是%d,则先读取一个32位数,然后取这个32位数的低8位,下一次读取的时候则接着读取下一个32位数。

上面的现象是在vs2013中发生的,在linux的gcc编译器可以正确打印,我认为linux的gcc编译器对于long long类型直接每次读64位了,不管格式控制符是不是%d,最后再将低32位打印。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值