1. printf将二进制转换成字符串
printf函数从参数中获取二进制数据,并将它根据转换规范转换成字符串,并打印在控制台上。
让我们运行以下代码,并根据其结果,分析其中原理,从而理解为什么将以%开始的一串字符
称作转换规范?
#include <stdio.h>
int main()
{
int aNum = 2147483647;
unsigned int aBiggerNum = 4294967295;
printf("%d %u\n", aNum, aNum);
printf("%d %u\n", aBiggerNum, aBiggerNum);
return 0;
}
在上面的代码中,整型int
变量aNum
,数值为2147483647
,使用%d
或%u
均能输出正确的结果。
但是无符号整型unsigned int
,数值为4294967295
,使用%d
无法正确输出结果,%u
却可以正确输出结果。
下面我们通过它们的二进制表示来分析问题出现的原因,在这之前我们先回忆一个知识点。
整型在计算机中的存储为补码表示法。设一个十进制数为n
,模为mod
。若n
为正数,n
的补码为n
的二进制。若n
为负数,设dec = mod - |n|
,n
的补码为dec
的二进制。(具体的文章,可参考:整型数据类型)
1.1 aNum进入printf后的转换情况
我们先观察aNum进入printf函数后的情况。
aNum的值为十进制2147483647,正数的补码为它本身的二进制。因此,aNum的补码为01111111 11111111 11111111 11111111
。
在aNum进入printf函数后,由于aNum的类型为int,所以类型并不会发生转换,仍然为4个字节。
当我们使用%u
来做转换规范时,printf会获取4字节的数据,并认为其为无符号整数。它没有符号位,因此肯定为一个正数的补码。可以直接将它转换为十进制,转换结果为字符串"2147483647"。
当我们使用%d
来做转换规范时,printf会获取4字节的数据,并认为其为有符号整数。最高位看做符号位,其余为数据位。而在这个二进制中最高位为0,因此它是一个正数的补码,可以直接将它转换为十进制,转换结果为字符串"2147483647"。
在这种情况下,使用%u
或%d
均可以得到正确的转换结果。
由于,以%开始的一串字符
指示printf函数如何转换二进制数据,所以将其称为转换规则更为准确。