前言
今天在重新学习C语言的途中遇到了关于数据类型本质的问题
当我输入 :
char c = -1;
printf("%u" ,c);
按我的理解char是1个字节,那么就应该是0xFF,输出就应该是255(FF)但结果确实4294967295(FFFF FFFF)。
这说明char类型以无符号类型输出的时候输出最大是int的四个字节。
数据类型
我们应该知道,数在计算机中都是以二进制的方式进行存储的,最高位代表符号位(0为正,1为负)而负数都是以补码的形式进行存储的。
其实我们很容易想到如果不用补码的形式能不能存储负数,答案当然是可以的,如(1 0000 0001)我们再用一位1表示负号。但是我们习惯上知道1+(-1)=0,如果我们用这种方法来表示负数,显然需要先判断多出的那一位的符号,再决定计算是“+”还是“-”。为了能直接使计算机进行二进制计算,补码也就应运而生。
那么我们开始介绍数据类型,不同的数据类型关键字表示了我们能表示的不同类型的数字。如:浮点数和整数。在其中我们又根据能表示的数的字长或精度做了区分
例如:
int = 4字节(由编译器决定)
long = 4/8字节(由编译器决定)
long long = 8字节
所以int最大能表示的无符号整形就是2^32(4,294,967,295)而不是65535即使现在我想都有很多人认为int最大是65535。
关于不同关键字所表示的字长我们可以用**sizeof()**来计算,如下:
整数越接问题
char 表示范围是-128~127
unsigned char 表示范围是0~255
int 表示范围是-2,147,483,648 到2,147,483,647
unsigned int 表示范围是0 ~4,294,967,295
我们常见的这种说法其实会有一点点误导,因为这个范围并不是我们常用的数轴来表示的,更像是一个首位连接的圆圈来表示。如下:
顺时针走的话就是加法,逆时针走的话就是减法,这样相信整数的溢出也就好理解了许多。
printf()
在理解我最开始遇到的问题之前,我们必须要简单提一下printf()函数
1.调用格式
printf("格式化字符串",输出表列)
格式化字符串类型如下
字符 | 对应数据类型 | 含义 | 示例 |
---|---|---|---|
d | int | 输出十进制有符号32bits整数 | printf("%i",123);输出123 |
u | unsigned int | 无符号10进制整数 | printf("%u",123);输出123 |
o | unsigned int | 无符号8进制(octal)整数(不输出前缀0) | printf(“0%o”,123);输出0173 |
x/X | unsigned int | 无符号16进制整数,x对应的是abcdef,X对应的是ABCDEF | printf(“0x%x 0x%X”,123,123);输出0x7b 0x7B |
f/lf | float(double) | 单精度浮点数用f,双精度浮点数用lf(printf可混用,但scanf不能混用) | printf("%.9f %.9lf",0.000000123,0.000000123);输出0.000000123 0.000000123。注意指定精度,否则printf默认精确到小数点后六位 |
c | char | 字符型。可以把输入的数字按照ASCII码相应转换为对应的字符 | printf("%c\n",64)输出A |
s | char* | 字符串。输出字符串中的字符直至字符串中的空字符(字符串以空字符’\0‘结尾 | printf("%s",“测试test”);输出:测试test |
p | void* | 以16进制形式输出指针 | printf("%010p",“lvlv”);输出:0x004007e6 |
% | 字符% | 输出字符‘%’(百分号)本身 | printf("%%");输出:% |
本表仅列出了本人认为用的较多的,更完善的推荐大家在https://cloud.tencent.com/developer/article/1176463进行查看。
printf与char
现在回到我在最初遇到的问题,其实存入变量的二进制数在不变的情况下,我们看的方式决定了最终显示的方式,而我们看的方式就是格式化字符串类型为了方便起见我将最开始的代码搬到这里。
char c = -1;
printf("%u" ,c);
c是一个有符号的8位数,所以c也确实应该是FF但是通过上面的表格我们知道%u表示的是无符号整形(32位数)所以计算机就需要将char转换为unsigned int也就是8位转换位32位。
计算机的做法就是将剩下的位用1补齐(-1 = FFFF FFFF)又因为符号位不起作用,在将32位补齐后的数就为4294967295(FFFF FFFF)。