深度解析C语言之数据在内存中的存储1

目录

数据的类型及类型的基本归类

数据类型及所占存储空间的大小

类型的意义

1、决定了开辟空间的范围

2、决定了如何看待内存空间的视角

类型的基本归类

整型家族

signed与unsigned的意义

浮点数家族

构造类型

 指针类型

空类型

整型在内存中的存储

数值的进制

二进制的不同表现形式

原码,反码,补码

为什么用补码

大小端字节序

练习


数据的类型及类型的基本归类

数据类型及所占存储空间的大小

内置类型单位32位64位备注
char字节11
short字节22
int字节44
long字节48
long long字节88C99类型
float字节44
double字节88

类型的意义

1、决定了开辟空间的范围

每个类型所占据字节的大小;

注意点:  C语言规定,sizeof(long)>=sizeof(int);

2、决定了如何看待内存空间的视角

给a赋一个整型值,内存空间中存储的是整型的数据,以整型和浮点型读取数据,会得到不同的结果。

int main()
{
	int a = 20;
	printf("%d\n", a);//结果为20
	printf("%f\n", a);//结果为0.000000
	system("pause");
	return 0;
}

类型的基本归类

整型家族

char具体类型由编译器决定
signed char有符号
unsigned char无符号
short默认有符号
signed short有符号
unsigned short无符号
int默认有符号
signed int有符号
unsigned int无符号
long默认有符号
signed long有符号
unsigned long无符号
long long默认有符号
signed long long有符号
unsigned long long无符号

注意:C语言标准并未定义char类型默认是signed或者unsigned,具体是由编译器指定

有符号与无符号的作用:

signed与unsigned的意义

C语言中有正数与负数,为了方便使用,C语言规定了有符号类型与无符号类型,它们的区别在于最高位,有符号类型最高位是符号位,0代表正数,1代表负数,无符号位最高位不是符号位,是数值位无论0还是1代表的都是数值

浮点数家族

float单精度浮点型精度低,存储数值范围小
double双精度浮点型精度高,存储数值范围大

构造类型

数组类型type  [num]
结构体类型struct
枚举类型enum
联合类型union

 指针类型

普通指针类型int *,char *,float *等等
空指针类型void *

空类型

void表示空类型(无类型)

通常应用于函数的返回类型,函数的参数,指针类型。

下面的代码中,第一个void表示test函数不需要返回,第二个函数(void)表示整个函数不需要传递参数,如果传参会有警告

void test(void)
{
	printf("hehe\n");
}

int main()
{
	test();
	return 0;
}

整型在内存中的存储

数值的进制

进制范围
二进制0,1
八进制0~7
十进制0~9
十六进制0~9,a~f

 注意:实际在内存中,内存都是以二进制的形式保存,但是编译器以十六进制的形式表现

整型值为10

二进制       0b00000000 00000000 00000000 00001010

十六进制   0x00 00 00 0a

二进制的不同表现形式

原码,反码,补码

注意:三种表示方法,均有符号位和数值位两部分,符号位用0表示正,用1表示负;正数的原码、反码、补码都相同;负数的原码、反码、补码是按照计算取得;整型数据存放在内存中是以补码的形式存放;

为什么用补码

原因1:CPU中只有加法器,没有减法器,使用补码能够将减法做加法处理(原码无法进行负数的加法运算),此外补码与原码互换,其运算过程是相同的,不需要额外的硬件电路(原码取反加1得到补码,补码取反加1得到原码;

注意:1000 0000(直接赋值-128),10000000 00000000 00000000 00000000(直接赋值-2,147,483,648))

以整数20为例:

原码:00000000 00000000 00000000 00010100

反码:00000000 00000000 00000000 00010100

补码:00000000 00000000 00000000 00010100

以整数-20为例

原码:10000000 00000000 00000000 00010100

反码:11111111  11111111    11111111   11101011(原码除符号位取反)

补码:11111111  11111111    11111111   11101100(反码+1)

为什么二进制中要存放补码

以1-1为例

1-1=1+(-1)

原码运算(错误)

00000000 00000000 00000000 00000001 (1的二进制)

10000000 00000000 00000000 00000001 (-1的二进制原码)

结果

10000000 00000000 00000000 00000010 (-2)

补码运算

00000000 00000000 00000000 00000001 (1的二进制)

11111111   11111111   11111111   11111111   (-1的补码)

结果

1 00000000 00000000 00000000 00000000

因为是整型,最多只能有32位,所以最高位被丢弃,结果为0

原因2

使用补码能将符号位和数值位统一处理(运算时可以同时考虑数值位和符号位)

大小端字节序

硬件决定了大小端的存储方式

以0x11 22 33 44为例

大端字节序存储:数字的高位存储在低地址中,低位存储在高地址中是大端存储

小端字节序存储:数字的低位存储在低地址中,高位存储在高地址中是小端存储

如何区分电脑是大端存储还是小端

注意:判断大小端一定需要指针,char指针取地址时,取得的是int类型的首地址

int check_sys()
{
	int num = 1;
	char *pc = #
	return *pc;

}

int main()
{
	if (check_sys())
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	system("pause");
	return 0;
}

练习

输出什么
int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d\nb=%d\nc=%d\n", a, b, c);
	system("pause");
	return 0;
}

解题思路
-1是整型
二进制补码
11111111 11111111 11111111 11111111
存入char中发生截断,只取最后八位
11111111
char与 signed char 是有符号类型,提升时以符号位为准
11111111 11111111 11111111 11111111
%d是有符号打印
所以打印时结果为-1

无符号类型提升
11111111前全加0
00000000 00000000 00000000 11111111
打印结果为255

题目2

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

解题思路
- 128的整型是1000 0000(注意这个数不是计算的而是规定的,有符号位见到就是-128)
-128补码是
原 10000000 00000000 00000000 10000000
反 11111111 11111111 11111111 01111111
补 11111111 11111111 11111111 10000000
存入时发生截断
10000000
打印时进行提升,因为是有符号位
11111111 11111111 11111111 10000000
%u是无符号类型打印,不用转为补码,打印结果是
4294967168

题目3

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


解题思路与上面相同
128的补码
00000000 00000000 00000000 10000000
存入时截断
10000000
因为时有符号位,提升时
11111111 11111111 11111111 10000000
无符号打印
4294967168

int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	system("pause");
	return 0;
}
解题思路
-20补码
原:10000000 00000000 00000000 00010100
反:11111111 11111111 11111111 11101011
补:11111111 11111111 11111111 11101100
10补码
补:00000000 00000000 00000000 00001010

相加
11111111 11111111 11111111 11101100
00000000 00000000 00000000 00001010
11111111 11111111 11111111 11110110
有符号打印(读取数据时需要转换位原码)
10000000 00000000 00000000 00001001(取反)
10000000 00000000 00000000 00001010(加1)结果为-10

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值