C语言字符在内存中的存储

1.存储方式

首先先看一段代码

int main()
{
	if ('a' == 97)
		printf("=");
	return 0;
}

这段代码的输出是

  =

这里我们知道 ‘a’ 是一个字符,97是一个整数,但它们却是相等的,说明在计算机内部,它们两个的本质其实是一样的,也就是它们储存方式在本质上是一样的。
而以一个整型数据为例,它在计算机中会先被被转化成二进制数据,在以其补码的形式储存在计算机内存中。
关于二进制转化以及原码、反码、补码的概念我已在之前的博客中讲述过,这里就不再赘述。
字符也一样,它也会被转化成二进制数据,在以其补码形式存储。既然这样,字符又是如何转化成二进制数字呢?
再看看上方的代码,答案就在其中。
字符a与整数97是相等的。
其实在计算机中,为了存储字符,我们创造了编码表,在这种表中,每个字符都有与其对应的数字,借此我们就可以通过数字来代替字符。正因如此,字符和整数在
内存中都是以数字的形式存储,它们的本质都是数字,只是输出方式不同。但值得注意的是,随着时代的发展,我们创造了很多不同的编码表,有ASCII码UTF-8GBK……其中c语言所使用的编码形式就是ASCII码。
我们再次重申一下,字符与整数在内存中都是以二进制存储的,它们本质一样。

2. c语言字符内存大小

一个整数所占字节数一般是2个字节或是4个字节,这和使用的编译器有关。而字符一般只占一个字节的空间,也就是8个比特位。

3. 字符类型

字符一共有三个类型,char(这个比较特殊)、signed char(有正负)、unsigned char(全正)。其中char可以是signed char类型,也可以是unsigned char,究竟是哪个要看编译器,这里以vs2022来讲。在vs中,char就是
signed char,也就是有符号型字符。

1. unsigned char

这个是无符号字符,八个比特位全用来存放大小,因此其最小值就是(二进制)
00000000(十进制中是0),最大值是(二进制)11111111(十进制就是2^8-1=255).

2.signed char

这个是有符号字符,其二进制最高位表示符号(正负),1就是负,0就是正数,其余七个位置来存放大小,因此其最大值就是01111111(127),最小值就是-128。
细心的人发现-128我并没有用二进制来表示,这是因为-128比较特殊。127的补码是01111111,我们在+1,就得到10000000,我们规定这个值就是-128的补码。

4. 溢出

字符只占8个字节,这是非常小的,那它溢出了会发生什么呢?

1. unsigned char

我们慢慢来推算
0——00000000
1——00000001
……
255——11111111
255+1——100000000
这里已经有九个字节了,它就会发生截断,取最后八位,也就是00000000,十进制就是0。
因此,其内容是在不断地循环在这里插入图片描述

2.signed char

我们也慢慢来推算(这里的二进制都显示的是其补码)
0——00000000
1——00000001
……
127——01111111
127+1——100000000—— 规定是-128
-127——10000001
-126——10000010
-125——10000011
……
-1——11111111
-1+1=0——100000000发生截断取后八位00000000
这也是一个循环
在这里插入图片描述

5.截断和整型提升

char n=51757;

这里我们赋予n一个远超于其范围的值,因此会发生截断
先看看51757的二进制数据:
00000000 00000000 11001010 00101101
转换补码
00000000 00000000 11001010 00101101
保留后八位,也就是 00101101
再转到原码
00101101也就是45
因此n实际的值是45。

char n=-45;
printf("%d",n);

这里将字符n以十进制有符号形式打出,会发生整型提升
先看看n的原码
10101101
转换成补码
11010011
因为整数占4个字节的空间,而11010011只占一个字节,因此会 ’扩展‘,其扩展方式是
1.无符号字符,其余位补0.如10101010提升成00000000 00000000 00000000 10101010.
2.有符号字符,其余为补符号位。如10101010提升成11111111 11111111 11111111 10101010
01010101提升成00000000 00000000 00000000 01010101
而n是有符号字符,因此11010011提升成11111111 11111111 11111111 11010011
转化成原码10000000 00000000 00000000 00101101也就是-45。
虽然在这里和其原本的值没区别,但我们要明白运行原理

  • 27
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值