数据的存储:整型

整型

要理解整型是如何在内存中存储,我们必须先认识原码、反码和补码。
正数的原码补码反码一样
原码:按二进制翻译,最高位为符号位,0代表正数,1代表负数。

在计算机中只有加法没有减法,减一个数相当于加一个负数。

如果我们用原码来计算 例:2+2 正数加正数
0000 0010 + 0000 0010 = 0000 0100 =4 没有问题
如果我们用来计算负数: 2+ (-2) 正数加负数
0000 0010 + 1000 0010 = 1000 0100 = -4
看来用原码计算是有问题的,既然只能用加法来计算,我们考虑把负数除符号位全部
取反(补码),再来计算试一试
补码:符号位不变,其余位置按位取反.
0000 0010 + 1111 1101(即-2)=1111 1111
再把1111 1111取反回来 为 1000 0000 = - 0 这样似乎 2 + (-2)= 0,虽然得到的是-0。

再试一试其他的数相加 2 + -3
0000 0010 +1111 1100 = 1111 1110(补码)=1000 0001(原码) = -1 没有问题

再试一试 -2+ -2
1111 1101 +1111 1101 = 1111 1010(补码)= 1000 0101(原码)= -5 不对
再试一试 -3 + -1
1111 1100 +1111 1110 = 1111 1010 (补码)=1000 0101(原码)= -5 不对

发现用反码计算正数+负数时结果正确,负数+负数时不正确,于是出现了补码。

补码:负数的补码等于他的原码自低位向高位,尾数的第一个‘1’及其右边的‘0’保持不变,左边的各位按位取反,符号位不变。 这里刚好与反码+1相同

至于为何这样这里不作讨论,补码的出现使计算机可以通过加法来实现减法运算。

数据中的存储

int i = 10,int类型32位i的二进制补码如下
00000000 00000000 00000000 00001010
监视 i 的内存
在这里插入图片描述
可以看出,此计算机是小端模式,十六进制的0a对应二进制的1010十进制的10。

监视 j 的内存
在这里插入图片描述
内存中的数都是以补码的形式存储的 -20的补码如下
11111111 11111111 11111111 11101100
ff     ff    ff    ec
六进制中的ec对应二进制中的11101100;ff对应二进制中的11111111 。

练习

1.输出结果为a = -1,b = -1,c = 255

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

分析:在visual 中char和signed char都是有符号类型,unsigned char是无符号类型,char类型为一个字节,而%d为4个字节,所以要进行整型提升,整型提升时看自身类型

char和signed char都为有符号类型,a和b 整型提升
11111111-------->>>11111111 11111111 11111111 11111111 以%d(有符号整型十进制)输出 为-1
注意:这里如果用%u输出,结果会不同,下面例子中会具体分析。

unsigned为无符号类型,c整型提升,整型提升时看自身类型
11111111----->>>>00000000 00000000 00000000 11111111 以%d输出为255。


2.输出结果为4294967168

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

在这里插入图片描述
分析:a在内存中的存储为十六进制的80 转换为二进制
1000 0000
a以%u类型输出,需要整型提升,看a自身类型char,为有符号类型,前面24位补1
11111111 11111111 11111111 1000 0000
再以%u类型输出,因为%u为无符号类型十进制输出,故结果为 4294967168。

把-128改成128

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

在这里插入图片描述
a的二进制没变,输出结果也不会变。


int main()
{
	int i = -20;
	unsigned int j = 10; 
	printf("%u\n", i + j);//按照补码的形式进行运算,最后格式化成为有符号整数
	system("pause");
	return 0;
}

i 与 j 以补码形式相加
结果为
11111111 11111111 11111111 11110110
再将 11111111 11111111 11111111 11110110以%u无符号输出。


4

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

运行结果如下
在这里插入图片描述
分析:当 i = 0时,其在内存中的存储如下
在这里插入图片描述
此时的二进制为
00000000000000000000000000000000

i --后
在这里插入图片描述
此时的二进制为
11111111111111111111111111111111
因为i为无符号类型,最高位不是符号位,故一直满足i>=0的条件
再按%u无符号类型输出,得到以上结果。



如果将%u换成%d结果会怎么样呢?
分析:换成%d只是输出会有影响,i在内存中的存储是不会有变化的。
当 i=0,i-- 后,i在内存中的存储为
11111111111111111111111111111111以%d输出结果为-1.
继续,i–,其在内存中的存储为
11111111111111111111111111111110以%d输出为-2.
继续,i–,
11111111111111111111111111111101以%d输出为-3

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

对应%d输出的-1和%u输出的429497295,他们的输出对象i在内存中的存储都是
11111111 11111111 11111111 11111111 ,只是以不同方式输出结果不同罢了。


5

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

分析:
char型数组,a[i] = -1-i ;i ++,因此数组中应该依次存放
-1 -2 -3 -4 -5 …但是char类型存储范围是-128~127,超出这个范围,数据溢出。
再来看看输出
strlen记录字符串长度,以’\0’结束,此题中即遇到数组中的‘0’结束
所以这里打印的是数组中字符‘0’,前面一共有多少个数。
先看看数组中的存储情况
在这里插入图片描述

在这里插入图片描述
我们可以看到,从-128开始变为127随后一次递减一直到0。


分析:从i = 128开始,arr[i]= -1 -i,因为数组类型char存储范围为-128~127,因此此时会发生数据的溢出。
-1 - 128 = -129
-129对应二进制补码形式:
1 0111 1111,因为char一个字节,只能存储8位,故存在arr[i] 中的为 0111 1111即 127
继续
-1 - 129 = -130
1 0111 1110 存储在arr [i] 中的为 0111 1110 即 126
依次…直到0
最终结果为255.


6

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

分析:死循环,i = 255时,i++溢出,i =0。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值