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