数据的存储-整形篇习题

在本文中,我会举例一些有关整形数据存储的典型的例题,并详细讲解。

阅读本文前,建议阅读一下之前的知识点部分博客:
【c语言】内存的世界,数据何以为家(一)—整形篇

  • 题目一

 #include<stdio.h>
 int main()
 {
	 char a = -1;
	 signed char b = -1;   //有符号字符型
	 unsigned char c = -1; //无符号字符型
	 printf("a=%d,b=%d,c=%d", a, b, c);  //以整形输出
	 return 0;
 }

在这里插入图片描述


 对于 signed char b = -1,我们这样理解:
	 
	 1.对于char型,我们可以先假设为普通整形数据,写出补码
	    10000000 00000000 00000000 00000001
	    11111111 11111111 11111111 11111110
	    11111111 11111111 11111111 11111111
	 2.由于char型只占8个bit,所以对上面的补码进行截断,只留下后811111111
	 3.由于以“%d”输出,所以我们将补码进行整形提升
	    11111111 11111111 11111111 11111111
	 4.所以我们得到了整形下的a的补码,还原为原码,再还原位十进制为-1   
        
对于  unsigned char c = -1,我们这样理解:

    1.前两步与signed char b 相同,截断留下后八位补码
        11111111
    2.由于以“%d”输出,所以我们将补码进行整形提升
        00000000 00000000 00000000 11111111  
    3.所以我们得到了整形下的a的补码,补码与原码一致,还原位十进制为255
        2^7 + 2^6 + 2^5 + 2^4 + 2^3 + 2^2 + 2+1 = 255    

看到这里,大家可能会有一些疑问:
1.整形提升是什么,为啥有时候补0,有时候补1?

整型提升是指在输出或者计算变量时,变量大小不够整型(int型)的大小,则需要把变量的大小提升至整型再进行输出或者计算。
对于有符号数:如果符号位为1,则补1,否则补0
对于无符号数:补0

2.char类型算作是signed char还是unsigned呢?

其实在c语言中,并没有明确规定,所以看编译器而定,在vs环境中,可以
看到,a与b的结果相同,所以vs中char默认为signed char.

ps: int 是signed int 还是unsigned int ? signed int

  • 题目二

	#include<stdio.h>
int main()
{
	char a = -128;
	printf("%u\n", a);//以无符号整形%u打印
	printf("%d\n", a);//以有符号整形%d打印
	return 0;
}

在这里插入图片描述

  对于以无符号整形%u打印的情况:

	   1.与上题类似,求补码,再截断,再整形提升,不再赘述。
	    10000000 00000000 00000000 100000000   -128的原码
		11111111 11111111 11111111 011111111   反码
		11111111 11111111 11111111 100000000   补码
		10000000                               char截断
		11111111 11111111 11111111 100000000   整形提升
		
	   2.提升后,以无符号整形%u打印,此时认为没有符号位的概念了
	     那么该数就是正数了,补码等于原码。
	    11111111 11111111 11111111 100000000
	    
	   3.将原码转化为十进制,得到 4294967168,很大的一个数。
  对于以有符号整形%d打印的情况:
  
	  1.与上题类似,求补码,再截断,再整形提升,不再赘述。
	    10000000 00000000 00000000 100000000   -128的原码
		11111111 11111111 11111111 011111111   反码
		11111111 11111111 11111111 100000000   补码
		10000000                               char截断
		11111111 11111111 11111111 100000000   整形提升
	  2.把得到的补码转回原码
	    11111111 11111111 11111111 011111111   反码
		10000000 00000000 00000000 100000000   原码
	  3.转化为10进制:-128	
	
  • 题目三
#include<stdio.h>
int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}
//得到结果:4294967168
     1.求补码,再截断,再整形提升
	     00000000 00000000 00000000 100000000   //原反补相同
		 10000000                               //截断
		 11111111 11111111 11111111 100000000   //整形提升
	 
	 2.提升后,以无符号整形%u打印,此时认为没有符号位的概念了
	     那么该数就是正数了,补码等于原码。
	     11111111 11111111 11111111 100000000
	    
	 3.将原码转化为十进制,得到 4294967168,很大的一个数。
		//与练习二得到的结果相同
  • 题目四

#include<stdio.h>
int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	printf("%u\n", i + j);
}

在这里插入图片描述


  在之前的博客中讲过,我们使用补码进行计算:
       1.分别计算得到i,j的补码:
	        10000000 00000000 00000000 00010100
			11111111 11111111 11111111 11101011
			11111111 11111111 11111111 11101100   i的补码
	
			00000000 00000000 00000000 00001010   j的补码
	   2.将补码相加 
	        11111111 11111111 11111111 11110110   补码相加后  
	   3. 
	         3.1若以%d形式打印,则将首位1看作符号位,求原码:
			        11111111 11111111 11111111 11110101   反码
				    10000000 00000000 00000000 00001010   原码
				    转化为十进制:-10
		    
	         3.2若以%u形式打印,此时没有符号位的概念了,那么
	         该数就是正数了,补码等于原码: 
			        得到一个很大的数字:4294967286
  
  • 题目五
#include<stdio.h>
int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
}
//运行结果:死循环
这道题很简单,因为很显然,无符号型整形的值恒大于等于0,所以i>=0的循环条件无效,
程序陷入死循环
  • 题目六
#include<stdio.h>
#include<string>
int main()
{
	char a[600];
	int i;
	for (i = 0; i < 600; i++)
	{
		a[i] = -1 - i;
		//printf("%d ", a[i]);
		
	}
	printf("%d", strlen(a));
	return 0;
}

在这里插入图片描述

这里的结果看上去很奇怪,其实这与char类型变量的取值范围有关。

char类型的取值范围(十进制)是 -128 ~ 127
在这里插入图片描述

char类型变量在内存中占8个bit位,内存中补码由00000000 -> 11111111;

其中00000000 ->01111111 对应十进制为1 -> 127
而从10000000 ->11111111 对应十进制为-128 -> -1
  • 题目七
#include<stdio.h>
int main()
{
		unsigned char i = 0;
		for (i = 0; i <= 255; i++)
		{
			printf("hello world\n");
		}
}
这题在知道char类型数据的取值范围后就很明显了:

对于无符号char型,同理,从00000000 ->11111111,无符号位,
所以直接可以算出十进制为0 ->255。所以恒小于等于255,故死循环。
  • 题目八
int main()
{
	unsigned char a = 200;
	unsigned char b = 100;
	unsigned char c = 0;
	c= a+b;
	printf("%d, %d ",a+b,c);
	return 0;
}
a 的二进制是 11001000
b 的二进制的 01100100

当a+b的时候,需要进行整形提升,相当于两个 int 相加
00000000 00000000 00000000 11001000 +
00000000 00000000 00000000 01100100 
= 00000000 00000000 00000001 00101100

但是 c显然放不下,需要进行截断: 00101100

所以 a+b=300 ,c=44
  • 题目九
32 位大端处理器上 变量b等于_______.

int main()
{
	unsigned int a = 0x1234;
	unsigned char b = *(unsigned char*)&a;
}

答案:0x00

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ornamrr

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

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

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

打赏作者

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

抵扣说明:

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

余额充值