学完了整型提升?来做做这几道题吧。

在这里插入图片描述

1.求输出结果

//输出什么?
#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;
}

解答:

int main()
{
	char a = -1;
	//-1
	//10000000 00000000 00000000 00000001——原码
	//11111111 11111111 11111111 11111110——反码
	//11111111 11111111 11111111 11111111——补码,-1实际存储于计算机中的二进制形式
	//a的类型为有符号字符型,故须将-1的补码进行截断,由低地址开始取8个bit位,得到
	//11111111

	signed char b = -1;
	//b与a同理,得到
	//11111111

	unsigned char c = -1;
	//c虽然为无符号数,但是其补码形式与有符号的-1仍然一致,区别在于如何解读补码(是否承认符号位)
	//11111111 11111111 11111111 11111111
	//截断后得到c的补码 :11111111 ——255(10进制)

	//但是%d为有符号的int类型输出,所以需要将a,b,c整型提升为int
	
	//a为有符号char 需按符号位(1)提升,提升后得到
	//11111111 11111111 11111111 11111111——补码
	//10000000 00000000 00000000 00000000——原码 -> -1(10进制)
	
	//b同理 得到原码为-1

	//c为无符号char,按0进行提升得到
	//00000000 00000000 00000000 11111111——补码,正数的原反补相同,->255(10进制)
	printf("a=%d,b=%d,c=%d", a, b, c);
	return 0;
}

在这里插入图片描述


2.看看下面程序输出什么?

int main()
{
	char a = -128;
	printf("%u\n", a);
	return 0;
}

解答:

int main()
{
	char a = -128;
	//-128
	//10000000 00000000 00000000 10000000 ——原码
	//11111111 11111111 11111111 01111111 ——反码
	//11111111 11111111 11111111 10000000 ——补码
	//随后截断 得到 10000000
	//%u为无符号的int输出 ,则需将a先整型提升
	//这里要注意,如何提升依据的是a的类型,而非输出的形式!
	//a为有符号char,则需要根据符号位进行提升,得到
	//11111111 11111111 11111111 10000000 (无符号的原反补码相同)
	//然后以无符号整型的眼光看待这串数字
	//得到4294967168(10进制)
	printf("%u\n", a);
	return 0;
}

在这里插入图片描述


3.求输出结果

int main()
{
	char a = 128;
	printf("%u\n",a);
	return 0;
}

解答:

int main()
{
	char a = 128;
	//00000000 00000000 00000000 10000000 ——正数128的原反补码一致
	//截断8个bit位得到 10000000
	//a为有符号char,这里依然是按符号位提升为整型,得到
	//11111111 11111111 11111111 10000000
	//以无符号整型输出,故原反补码相同就无需将其转换为原码,结果与上题相同。
	printf("%u\n", a);
	return 0;
}

在这里插入图片描述


4.当一个符号数与无符号数相加

int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	return 0;
}

解答

int main()
{
	int i = -20;
	//-20
	//10000000 00000000 00000000 00010100——原码
	//11111111 11111111 11111111 11101011——反码
	//11111111 11111111 11111111 11101100——补码

	unsigned int j = 10;
	//10
	//00000000 00000000 00000000 00001010——原反补码相同

	//-20+10:计算机内的计算均为补码的运算
	//将两者的补码相加,得到
	//11111111 11111111 11111111 11110110——补码
	//我们以有符号int进行打印,则需将补码装换为原码
	//10000000 00000000 00000000 00001010——原码 -10(10进制)
	printf("%d\n", i + j);
	return 0;
}

这里需要注意一个问题,当一个无符号数与有符号数相加时,系统会以unsigned int的形式看待结果,而第4题则以%d的视角看待了这串补码,使其以带符号输出,可以看下面的代码,想一想输出的是什么?

int main()
{
	int a = -20;
	unsigned b = 10;
	if ((a + b) > 0)
	{
		printf(">0");
	}
	else
	{
		printf("<0");
	}
	return 0;
}

这里的a+b视为无符号数,于是将补码直接视为原码,结果将是一串很大的数字
a+b的补码由第4题给出:11111111 11111111 11111111 11110110
在这里插入图片描述
可以看到十进制处的答案为4294967286,这必然是大于0的
在这里插入图片描述

5.

求输出结果

int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}

解答:
这是一个死循环,因为当i=0进入i–时,i 变为了-1,而 i 为无符号char,范围处于0~(2^32-1),实际上 i 变为了2 ^ 32-1,于是就进入了死循环。


6.

#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;
}

解答:
strlen函数为求字符串的长度,即计算字符’\0’(ascll值为0)前的字符的个数,那我们就看a数组何时到0。

这里要注意char能表达的数字的范围是-128~127.

a[0]= -1 补码:11111111
a[1]= -2 补码:11111110


a[127]= -128 补码:10000000
a[128]= 127 补码:01111111


a[254]=1 补码:00000001
a[255]=0 补码:0000000
负数有128个char,正数有127个char,长度为255.
在这里插入图片描述


7.

unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

解答:
unsigned char 的范围是0~255,当i=255 后执行i++,那么i就又返回到0,进入死循环,我们可以看下补码(无符号的原码和补码相同)
i=255 补码/原码:11111111
执行:i++
得到补码 1 00000000
unsigned char类型长度为1字节,需要截断
于是得到的补码为 00000000=0(10进制)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值