C语言 - 数据存储(整型数据存储)

目录

一、 数据类型详细介绍

1.类型的基本归类

二、 整形在内存中的存储

1.原码、反码、补码

 对于整形来说:数据存放内存中其实存放的是补码。

三、大小端字节序介绍及判断

1、大端小端:

2、写出一个判断大小端的程序

四、练习整型存储

8个练习题 - 详解

五、整型计算总结

1、输入时:

        1)char类型,则要注意截断和整型提升

        2)signed 和 unsigned 则要注意如果有整型提升.

无符号unsigned类型 ,默认补位0

有符号signed类型,需要根据截断后的二进制,补符号位;

(例如:截断后10000000 则补位1;截断后00000001 则补位 0)

        3)如果为正数,补码即为二进制原码,不需要额外计算。

        4)如果为负数,需要 原码 反码 补码 计算

2、输出时

        1)%d 打印有符号十进制数,记得把计算的补码,还原为原码

        2)%u 打印无符号十进制数,补码即为结果


一、 数据类型详细介绍

 以及他们所占存储空间的大小。

类型的意义:
1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。
2. 如何看待内存空间的视角

1.类型的基本归类

 

 

二、 整形在内存中的存储

变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。

1.原码、反码、补码

 

 

 

 对于整形来说:数据存放内存中其实存放的是补码。

为什么呢?
        在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统 一处理;
        同时,加法和减法也可以统一处理( CPU只有加法器 )此外,补码与原码相互转换,其运算过程 是相同的,不需要额外的硬件电路。
int main()
{
	//内存里1-1=0
	int a = 1;
	int b = 1;
	int c = a - b;
	printf("%d\n", c);
	//看似是1减去1得到的0,实际上是1+(-1)得到0
	//1
	//00000000000000000000000000000001  - 1的补码
	
	//-1
	//10000000000000000000000000000001
	//11111111111111111111111111111110
	//11111111111111111111111111111111 - -1的补码

	//1+(-1)
		//00000000000000000000000000000001  - 1的补码
		//11111111111111111111111111111111 - -1的补码
		//100000000000000000000000000000000 - 1+(-1)的补码
	//丢掉高位得到 0
	//00000000000000000000000000000000 

	
	return 0;
}

三、大小端字节序介绍及判断

1、大端小端:

大端(存储)模式 ,是指数据的 低位 保存在内存的 高地址 中,而数据的 高位 ,保存在内存的 低地址 中;
小端(存储)模式 ,是指数据的 低位 保存在内存的 低地址 中,而数据的 高位 , ,保存在内存的 高地址
int main()
{
	int a = 20;
	//00000000000000000000000000010100  -  二进制补码
	//00 00 00 14 - 16进制       调试监视内存可以看到 14 00 00 00
	
	int b = -10;
	//10000000000000000000000000001010 -  二进制原码
	//11111111111111111111111111110101 - 反码
	//11111111111111111111111111110110 - 补码
	//ff ff ff f6 -16进制		调试监视内存可以看到f6 ff ff ff
	return 0;
}

 右边的地址:&b举例,可以看出地址是由低到高变化的,(f6的地址为E0后面依次为 E1, E2,E3,第二行开始cc的地址为E4。地址依次增大)

我们换算的补码顺序为           ff  ff  ff  f6  (f6为低位)

地址里存储的补码顺序为       f6  ff  ff  ff  (地址低到高变化的

        根据大小端的概念,我们发现低位 f6 存储在低地址处,高位 ff 存储在高地址处,所以推测我们目前使用的机器为小端存储

2、写出一个判断大小端的程序

/*
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分)
*/
int main()
{
	int a = 1;
	//00000000000000000000000000000001 - 1的二进制
	//00 00 00 01 - 1的16进制,内存显示的是这样
	//如果是小端存储 - 01 00 00 00
	//如果是大端存储 - 00 00 00 01
	//第一个字节就会不同,比较第一个字节就可以区分了

	char* pa = (char*)&a;
	int i = 0;
	//for (i = 0; i < 4; i++)
	//{
	//	printf("%d ", *pa);
	//	pa++;
	//}
	//1 0 0 0 - 小端存储

	if (*pa)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}

	return 0;
}

 跟我们推测一致

四、练习整型存储
 

1.
int main()
{
	char a = -1;
	signed char b = -1;
	//char等同于siged char
	//10000000000000000000000000000001
	//11111111111111111111111111111110
	//11111111111111111111111111111111 - -1的补码
	//11111111 -  截断
	//整型提升 - 因为signed 有符号数,补符号位1 (11111111) 
	//11111111111111111111111111111111
	//11111111111111111111111111111110
	//10000000000000000000000000000001 - -1 的原码

	unsigned char c = -1;
	//10000000000000000000000000000001
	//11111111111111111111111111111110
	//11111111111111111111111111111111
	//11111111 - 截断
	//整型提升 - 因为unsigned char c是无符号整型,默认补0
	//00000000000000000000000011111111
	//由于最高位是0,为正数,正数的补码就是原码,于是转化为十进制就是 255
	printf("a=%d,b=%d,c=%d", a, b, c);//a=-1,b=-1,c=255
	return 0;
}

2.

int main()
{
	unsigned int num = -10;
	//10000000000000000000000000001010
	//11111111111111111111111111110101
	//11111111111111111111111111110110 - 补码
	printf("%d\n", num);//-10
	printf("%u\n", num);//打印无符号的十进制,符号位失去意义,当值数值计算了4294967286

	return 0;
}

 3.

int main()
{
	char a = -128;
	//10000000000000000000000010000000
	//11111111111111111111111101111111
	//11111111111111111111111110000000 - 补码
	//10000000 - 截断
	//整型提升 - 补符号位1 (10000000)
	//11111111111111111111111110000000 - 补码 
	
	printf("%u\n", a);//4294967168
	//打印无符号十进制数,则该补码的符号位没有意义,
	//变为数值位了,此时补码直接看作原码,化为十进制则为4294967168
	
	return 0;
}

4.

int main()
{
	char a = 128;
	//00000000000000000000000010000000
	//01111111111111111111111101111111
	//01111111111111111111111110000000 - 补码
	//10000000 - 截断
	//整型提升 - 有符号整型 补符号位1(10000000)
	//11111111111111111111111110000000 - 4294967168
	printf("%u\n", a);//4294967168

	return 0;
}

 

5.

int main()
{
	int i = -20;
	//10000000000000000000000000010100
	//11111111111111111111111111101011
	//11111111111111111111111111101100 -补码
	unsigned int j = 10;
	//00000000000000000000000000001010 - 10正数原反补相同
	//11111111111111111111111111101100 - -20
	//11111111111111111111111111110110 - 和(补码)
	//10000000000000000000000000001001
	//10000000000000000000000000001010 - -10(原码)
	
	printf("%d\n", i + j);//-10
	//按照补码的形式进行运算,最后格式化成为有符号整数
	return 0;
}

6.

int main()
{
	
	unsigned int i;
	//无符号整型,没有符号位,每一位都是数值
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);//死循环
		Sleep(1000);//为了方便看到每一步的变化,使用函数隔一秒打印
	}
	//9 8 7 6 5 4 3 2 1 0之后 i--得到-1
	//unsigned int i=-1
	//11111111111111111111111111111111 - -1的补码
	//由于无符号数,则该数的数值为4,294,967,295
	//以此类推i--得到-2
	//4,294,967,294
	return 0;
}

7.

int main()
{
	char a[1000];
	//char类型的取值范围-128~127 一共有255个数,
	//所以打印无法超过这个范围
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	//-1 -2 -3 ...-128  127 126 ....3 2 1 0
	printf("%d", strlen(a));//255
	//求数组a的字符串长度,遇到'\0'就停止,'\0'的ASCII码值就是 0
	//数组最后一个元素 0 即 '\0'
	//从-128~127,一共255个元素,所以strlen(a)值为255
	return 0;
}

 8.

unsigned char i = 0;
//范围-128~127
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	//0~127打印hello world
	//128~255也可打印
	//unsigned char i = 128
	//10000000 -补码
	//unsigned char i = 255
	//11111111 -补码
	//当i++得到 unsigned char i=256时
	//100000000 截断得到 00000000
	//又变回了0,开始死循环
	return 0;
}

五、整型计算总结

        在计算时,我们要看输入的数据的类型(有符号 signed / 无符号unsigned 和 char 等是否要整型提升)以及数据的值(正负),还需要看是以怎样的形式输出的(有符号十进制%d  / 无符号十进制 %u)

1、输入时:

        1)char类型,则要注意截断整型提升

        2)signed 和 unsigned 则要注意如果有整型提升.

无符号unsigned类型 ,默认补位0

有符号signed类型,需要根据截断后的二进制,补符号位;

(例如:截断后10000000 则补位1;截断后00000001 则补位 0)

        3)如果为正数,补码即为二进制原码,不需要额外计算。

        4)如果为负数,需要 原码 反码 补码 计算

2、输出时

        1)%d 打印有符号十进制数,记得把计算的补码,还原为原码

        2)%u 打印无符号十进制数,补码即为结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值