整数在内存中的存储(附详细例题讲解)

整数在内存中的存储

例题一

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

这段代码中char 和signed char都代表有符号的char并没有区别,而unsigned代表无符号,但输出语句中的%d要求传一个int类型,此时unsigned char会将char类型隐形类型转换转为int类型,因为unsigned没有符号位无法在短数据转为长数据时补符号位,只能被迫补0.
a和b都可表示为1111 1111 1111 1111 1111 1111 1111 1111
而c表示为0000 0000 0000 0000 0000 0000 1111 1111

此处引入类型转换的规则:
1.如果是把长的数据转换为短的数据,高位就舍弃,直接"截断".
2如果是把短的数据转化为长的数据,高位要补符号位.

运行结果如下图:
在这里插入图片描述

例题二

#include<stdio.h>

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

而%u代表打印一个无符号的十进制的整数,与unsigned int相对应.
这个代码需要我们将char类型转换为unsigned int类型,而-128的二进制表示为1111 1111 1111 1111 1111 1111 1000 0000(先将一个字节补充到四个字节,高位补1符号位)然后将其转为为unsigned int类型,符号位不再是负数,整个数字也不是补码了,而是将前面这些1当成高位的数据,所以最终输出结果会是一个很大的数字
首先确定由int转换到unsigned int这个过程之中数据的二进制表示在内存中不会发生变化.
在这里插入图片描述
当改为char a=128时会发生溢出现象(char的范围为-128~+127).
由0111 1111进位变为1000 0000.进位导致符号位被强行设置成了1,于是计算机会把这个数字当成负的,运行结果也如上图所示.

例题三

#include<stdio.h>

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

此时需要将两个不同类型变量相加需要做类型转换,而根据操作符方面的知识得知应该将int转为unsigned int类型.
j的值0000 0000 0000 0000 0000 0000 0000 1010
再看i -20的原码1000 0000 0000 0000 0000 0000 0001 0100
求其补码1111 1111 1111 1111 1111 1111 1110 1100
(求补码:首位不变之后的每一位0变1,1变0,最后再在末尾加一即可)
又因为由int转换到unsigned int这个过程之中数据的二进制表示在内存中不会发生变化,所以两数相加即可为1111 1111 1111 1111 1111 1111 1111 0110
再将此补码转为原码,取反加一1000 0000 0000 0000 0000 0000 0000 1010 答案为-10
在这里插入图片描述

例题四

#include<stdio.h>

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

正常理解应该只运行十次,但因为unsigned的原因导致并非如此.
前几次循环都正常,但由0转为-1的这一次-1表示为1111 1111 1111 1111 1111 1111 1111 1111因为是unsigned的缘故把这个数字理解成无符号的话,符号位就不是负数了,整个数字也不是补码了这么多1表示的都是一些数字的高位,就能看到一个很大的整数,这个整数也正是unsigned int能表示的最大数值!

由0到-1的过程,-1被计算机理解为一个很大的整数,而很大的整数也正好符合大于0的要求,所以不跳出循环,从而变成一个经典的死循环.
unsigned更容易溢出,只要小于0了就会溢出
在这里插入图片描述

例题五

#include<stdio.h>


int main()
{
	char a[1000];
	int i;
	for (i = 0; i <= 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}

int 赋值给char会出现截断情况
-1的补码1111 1111 1111 1111 1111 1111 1111 1111减去0000 0000 0000 0000 0000 0000 1111 1111为1111 1111 1111 1111 1111 1111 0000 0000(将这个数转为char 表示\0)
而0000 0000 0000 0000 0000 0000 1111 1111这个数字十进制为255,即i=
255时正好-1再减255为\0,就相当于给数组下标为255的设置设为了\0,此时求字符串的长度,也正好就是0~254即255.
在这里插入图片描述
此处我们写一段代码来验证是否高位会截断,代码如下

#include<stdio.h>

int main()
{
	char a = -1 - 255;
	printf("%x\n", a);
	return 0;
}

在这里插入图片描述

例题六

#include<stdio.h>

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

代码运行后表现为一直打印hello world!
此代码是一个死循环,unsigned char只能表示到255无法表示到256,而代码中的循环需要i达到256方可跳出循环,此时陷入死循环.
255二进制表示为 1111 1111 而1表示为0000 0001
二者相加进为 1 0000 0000 但是因为数据只有八个比特位,最高位溢出了不在数据表示范围之内,当i达到255时在+1得到的不是256而是0此时继续循环,这是一个明显的数据溢出情况

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值