C语言-------数据类型中signed、unsigned他们在不同数据类型中存储的不同体现并且与printf关系的总结。

数据类型中signed、unsigned他们在不同数据类型中存储的不同体现:

如:char a = -1;

在将-10放进内存中时,首先你需要知道内存中存的都是补码所以应该将-10换成补码即为:0x FF FF FF FF :11111111111111111111111111111111此时若要放进char中就要发生截断成8bit 即为 0x FF :11111111

 

unsigned char b = -1;

同理:最终放进内存中的值为:11111111

但是你需要知道此时的11111111中的第一位将不再看作符号位

 

signed char c = -1;

同理:11111111

第一位将看作符号位,当然光的char和此处也是一样的

因为unsigned存在时其符号位将不存在所以此时的unsigned char a = -1;存在内存中的数值已将变成一个正数也就是11111111(255) 所以unsigned char a = -1其实存的是char类型中最大的值(11111111,他不会再通过补变回原码

所以当我们在打印时会有:

int main()
{
	char a = -1;
	unsigned char b = -1;
	signed char c = -1;
	printf("%d %d %d", a, b, c);//-1 255 -1
	return 0;
}

那具体是如何实现打印的呢?

由前面我们可以知道,所有的数值都是以补码的形式存进内存中的。并且char 与 signed char 是相同的。所以,其实a、b、c存在内存中是一样的都是11111111,但是当我们在printf中进行使用时就会有不同(a、c一起看)

并且因为打印的是%d是有符号的整数所以在要打印的数据也应该为一个整形,所以如short、char这种小于int类型的就要进行整形提升(并且注意只要小于int类型的当遇到操作符时就会进行整形提升

a:的补码11111111,

首先,需要进行整形提升(隐式提升,若忘了可以看->操作符的目录进行查看)补符号位:11111111111111111111111 111111111

其次,再转化成原码(因为是负数):10000000 00000000 00000000 00000001

最终:再进行打印(原码转化成10进制的值): -1

b的补码11111111

首先,需要进行整形提升补符号位,因为此处的b是一个无符号的字符类型所以其为一个正数,补符号位0:000000000000000000000000 111111111

其次再转化成原码,但此时符号位为0即为正的所以原反补相同就不需要再进行改变;

最终:再进行打印: 255

所以在通过上面的代码我们还可以发现一个知识点就是:

printf中的 %d 与  数值的类型 在整形提升前相互不会影响,即 b处他的类型是无符号的字符类型,而%d为有符号的整形,b在整形提升时仍然时一个无符号的字符类型。

而在整形提升后就会有一定的影响,即他认为内存中存的是一个有符号/无符号的整形(%d/%u)当需要打印的是有符号的整形此时就需要变成原码进行打印,而若为无符号的整形就不再需要转变成。

再如:

char a = 128

printf("%u",  a )

此时先将128的补码存进char中也就是

10000000 然后整形提升后:11111111111111111111111110000000

再打印就将会打印 11111111111111111111111110000000 二进制对应的十进制:4,294,967,168

附:通过上面的习题,我觉得有必要在补充一定关于 char类型在内存中的取值范围 (另一篇blog)的知识

练习:

一、

int main()
{
    int a = -20;
    unsignde int = 10;
    printf("%d",a + b);
    return 0;
}

该题分析:

a、b两个变量中都要存数据进到内存,并且都是以补码的形式存进内存中

即a中存的是:-20 的补码

而b中存的是:10 的补码

在printf中%d和a+b无直接联系:所以直接相加即可:那就得到了-10的补码(虽然a+b因为算术转换变成了一个无符号的整形但是这和%d无关,当用%d打印时其仍然将你看成一个有符号的整形来进行打印)

最后通过,%d打印即可得到-10(原码)

 

二、

 #define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[1000] = { 0 };
	int i = 0;
	for (i = 0; i < 1000; i++)
	{
		arr[i] =  - 1 - i;
	}
	printf("%d", strlen(arr));
	return 0;
}

分析:

因为char类型的范围是从-128~127

所以arr的取值就也可以是从:-128~127

第一次:arr[0] = -1  第二次:...   =  -2   arr[127]  =-128   ...  arr[254]   = 1

后arr[255] = 0(此时因为strlen是遇到'\0'就会停止)

所以最终strlen最终有 0 ~ 254 (-1 到 -128 再从127 到 1  : 128 + 127)个元素 共并打印255个

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溟洵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值