数据在内存中的存储(练习题篇)

 已经介绍过了整数和浮点数在内存中的存储方式,接下来我们通过一些具体的代码分析巩固

例1: 

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

输出如下:

分析:

char可以表示的数值范围:-128~127

在当前VS环境下,signed char和char相同,所以a和b的结果相同

unsigned chark可以表示的数值范围:0~255

-1的原码:10000000 00000000 00000000 00000001

-1的反码:11111111 11111111 11111111 11111110

-1的补码:11111111 11111111 11111111 11111111

因为a的类型是char,所以存入数据时,会发生截断,我们操作的序列变为11111111

但是打印数据时以%d的形式打印,所以又会发生整型提升

char 是有符号的,所以整型提升补1

11111111---->11111111 11111111 11111111 11111111  补码

反码:10000000 00000000 00000000 00000000

原码:10000000 00000000 00000000 00000001----> -1

所以最终打印a = -1(a和b一样)

对于c,在整型提升之前与a和b相同

整型提升时,由于c是一个无符号数,所以最高位不代表符号位,提升补0

11111111---->00000000 00000000 00000000 11111111 

很明显这是一个正数,原码,反码,补码相同  所以c = 255

例2: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	char a = 128;

	printf("%u\n", a);

	return 0;
}

输出如下: 

分析:

我们已经知道char可以表示的数据范围是-128~127

很明显,初始化一个char型的变量为超过其表示范围的数值会发生错误

128的原码/反码/补码:00000000 00000000 00000000 10000000

截断:10000000

整型提升:11111111 11111111 11111111 10000000  补码

以%u,即无符号整型看待这个时,它的最高位不是符号位,是有效数字位,且这个数的原码,反码,补码相同,所以这是一个很大的正数

例3: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int i = -20;
	unsigned int j = 10;

	printf("%d\n", i + j);

	return 0;
}

输出如下: 

分析:

-20的原码:10000000 00000000 00000000  00010100

-20的反码:11111111 11111111 11111111 11101011

-20的补码:11111111 11111111 11111111 11101100

10的原码/补码:00000000 00000000 00000000  000 01010

补码相加:11111111 11111111 11111111 11101110    补码

反码:10000000 00000000 00000000 00010001 

原码:10000000 00000000 00000000 00010010----> -10

例4: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}

	return 0;
}

输出为打印9,8,7,6,5,4,3,2,1,0后死循环: 

分析:

unsigned int类型的数据永远大于0

当i=0时,满足循环条件i>=0,进入循环,打印0

接着i--,此时,i=-1,但是我们知道i是一个无符号整数

-1的补码:11111111 11111111 11111111 11111111

这串二进制序列对于unsigned int来说,最高位不是符号位,而是有效数字位

所以这是一个很大的正数,满足i>=0,所以继续进入循环打印这个正数

例5: 

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

	return 0;
}

输出如下:

分析:

strlen函数:求字符串中\0之前出现多少字符,\0的ASCII码值是0

char型的数据范围-128~127

a[0]=-1-0=-1

a[1]=-1-1=-2

a[2]=-1-2=-3

... ... ... ...

a[127]=-1-127=-128

a[128]=-1-128=-129 这个数据超出了char的数据范围

-129的原码:10000000 00000000 00000000 10000001

-129的反码:11111111 11111111 11111111 01111110

​​​​​​​-129的补码:11111111 11111111 11111111 01111111

要存入char类型的数组,会发生截断:01111111

01111111 -----> 127

所以a[128]=127

a[129]=126

... ... ... ...

a[254]=1

a[255]=0

在0之前,字符的个数是255个,所以strlen(a)的结果是255

实际上,char型的数据在内存中存储的数据可以可视化为下图:

例6: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	

	return 0;
}

输出死循环如下:

 

分析:

对于一个unsigned char型的是数据来说,它的范围永远是0~255,所以循环的条件i<=255 恒成立,最终导致了死循环

例7: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	if (strlen("abc") - strlen("abcdef") >= 0)
	{
		printf(">\n");
	}
	else
	{
		printf("<\n");
	}
	

	return 0;
}

输出如下: 

分析: 

正常情况下,strlen("abc") =3; strlen("abcdef") = 6,结果应该是“<"

strlen库函数

我们可以看到,对strlen库函数,它的返回值是一个size_t类型的数据,其实,size_t就是unsigned char,所以,它的返回值用于是一个无符号数据,俩个无符号数据相加减得到的数据还是一个无符号类型的数据,恒大于零,所以输出为“>”

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值