【C语言】char类型如何在内存中存储?
@[toc]
引子
上篇博客向大家介绍了int类型在内存中的存储方式【链接】
本篇博客我们继续往后,看看整形家族里的char类型是如何在内存中存储的吧!
char类型
字符类型包括以下两种形式
unsigned char 无符号
signed char 有符号
用一个简单的printf来看看它们在打印上的区别
1 |
|
打印结果为
1 | a=-1 b=-1 c=255 |
这里我们可以得出两个结论
1.在VS编译器下,char默认为signed char
2.unsigned char的处理方式和signed不同
无符号数的处理可以看我之前写的这一篇博客👉【链接】
存放和提升
例一:-1
先写出-1的原反补码
1 | 10000000 00000000 00000000 00000001 -1原码 |
在内存中存放的时候,a、b、c存放的都是补码的最后一个字节,即11111111
而当我们用%d打印的时候,会发生整型提升
整型提升的概念我写过另外一篇博客👉【点我】
这里就是有符号和无符号处理不同的地方了
因为a、b都是有符号的char,所以编译器会将最高位视为符号位进行提升
所以a、b进行整型提升后的结果如下
1 | 11111111 11111111 11111111 11111111//提升后a、b的补码 |
而c是无符号char类型,编译器会在最高位补0
1 | 00000000 00000000 00000000 11111111//提升后c的补码 |
此时最高位为0,编译器将其视为正数,此时补码就是原码,打印255
符号位 0为正,1为负
正数的原码、反码、补码相同
例二:-128
1 |
|
打印的结果并不是-128
1 | 4294967168 |
-128的原反补码
1 | 10000000 00000000 00000000 10000000 -128原码 |
a中存放的是1000 0000
最高位视为符号位,整型提升后
1 | 11111111 11111111 11111111 10000000//新的补码 |
但因为这里是**%u打印,视作无符号数**
此时原反补码一致,直接视作原码进行计算
打印结果即为4294967168
如果我们让a等于128,结果相同
char变量中存放数值的范围
先来看看这样一串代码
1 |
|
代码的结果如下:255
在初始化的时候,我们设定了a[1000],a数组里面理应有1000个元素
那strlen函数求得的结果为何是255,而不是1000呢?
实际char类型中的数据范围分为有符号和无符号两种
- signed char 1byte-8bit,取值范围-128~127
- unsigned char 1byte-8bit,取值范围0~255
以二进制表示,如下图所示
因为无符号char类型中,八位补码视作原码进行计算
而有符号char类型中,在计算的时会将首位视为符号位
1 | 11111111 //补码 |
1 | 10000001//补码 |
1 | 10000000//补码 |
下面这幅图可以形象地表示出char类型数据范围
1 | char a[1000]; |
上面那串代码里面的for循环,实则是一直给数组a中从-1开始赋值到-128,再从127赋值到1,0……如此循环赋值,直到i=1000跳出循环。
而我们的strlen函数在计算数组长度的时候,遇到第一个0就会停止计算
这样我们就得出了答案为255!
如何查询范围定义?
我们可以通过头文件<limits.h>来查找范围定义
在VS2019里面右键该头文件,点击“转到文档”
这里我们就能看到各种数据类型的数据范围
我们还可以看看其他的数据类型
以有符号short为例,它的范围是-32678到32767
结语
以一串代码示例结束本篇博客吧!
感谢你看到最后!
点个赞呗,这对我灰常重要!!😘