数据的存储

整形家族

char 

signed char         无符号的char

unsigned char     有符号的char

short

signed short

unsigned short

int 

signed int 

unsigned int

long

signed long

unsigned long

long long

signed long

unsigned long

 

浮点型

float

double 

long double

 

 

构造类型

数组

结构体  struct

枚举     enum

联合体  union

 

指针类型

int *

char*

...

void*(空类型)

 

整形在内存中的存储

三个相关概念:原码,反码,补码

计算机中有符号的数有三种表示方法:即原码,反码和补码

三种表示方法均由符号位和数值位组成,符号位用0表示正,1表示负。而数值位三种方法表示各不相同

 

注意:正数(无符号位)的原码、反码和补码相同,而有符号的数的三种码表示形式不同

 

原码:直接按十进制转换成二进制

反码:符号位不变,其他位依次按位取反

补码:反码+1得到补码

 

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

 

当我们写了以下的代码

int main()
{
	int a = 0x11223344;
	return 0;
}

编译后进行调试,点开内存,在搜索栏中取a的地址

我们不难发现,数据在内存中居然是倒着存储的,这是为什么呢?

这里就要引入大小端概念的介绍

 

大端小端的介绍

大端存储模式,是指数据的低位保存在高地址中,高位保存在低地址中

小端存储模式,是指数据的低位保存在低地址中,高位保存在高地址中

 

因此通过内存栏可以看出,我此时用的机器采用的是小端存储模式,这也就解释了为什么数据存储的顺序是反过来的了

 

这里可以设计一个程序来判断机器的字节序,代码如下

#include<stdio.h>
//设计一个小程序来判断当前机器的字节序
int check_sys(char *p);
int main()
{
	int a = 1;
	char *p = (char*)&a;//将a的地址强制类型转换成char*类型,目的是改变指针的访问权限,使得指针能访问1字节的内容
	if (check_sys(p) == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}
int check_sys(char *p)
{
	if (*p == 1)
		return 1;
	else
	    return 0;
}

思路:十进制的1转换成16进制为00000001,若为小端存储:01 00 00 00,若为大端存储:00 00 00 01,通过强转指针类型来改变指针的访问权限,使得指针可以访问第一个字节中的内容。若为小端,则解引用为01,若为大端,则解引用为00。

 

来看一段代码,这段代码包含了整形提升,原反补码计算等知识点

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

以下是答案与解析(解析在注释中)

int main()
{
	char a = -1;
	//10000000000000000000000000000001 - 原码
	//11111111111111111111111111111110 - 反码
	//11111111111111111111111111111111 - 补码
	//而a是一个char类型的变量,所以存储在char类型中的a是所占内存大小是1字节,也就是8bit,所以只取补码的最后8位
	//即11111111
	//但是当a要被打印出来时,它是整形打印,1个整形是32bit,但这里只有8bit,所以要进行整形提升
	//整形提升按照符号位进行整形提升,11111111的最高位(符号位)是1,所以整形提升后结果如下
	//11111111111111111111111111111111 - 整形提升后的补码
	//10000000000000000000000000000001 - 补码转换成的原码(补码-1后符号位不变其余位取反得到原码)
	//而打印在屏幕上的就是原码,也就是-1
	signed char b = -1;
	//-1就是有符号的变量,signed char b = -1和char a = -1相同,所以打印出来的b和a一样,都是-1
	unsigned char c = -1;
	//c与ab有一些不同
	//c和ab一样,在内存中存储的补码都为11111111
	//但当要进行整形提升时,因为c是无符号变量,所以最高位(符号位)的1是无符号的,所以整形提升是无符号的整型提升,即前面补0
	//00000000000000000000000011111111 - 无符号整形提升后的补码
    //此时的最高位是0,0表示正数,所以原反补码相同,所以c打印出来是255
	printf("a=%d,b=%d,c=%d", a, b, c);//-1 -1 255
	return 0;
}

 

再看一段代码

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

答案和解析如下(解析在注释中)

int main()
{
	char a = 128;
	//00000000000000000000000010000000 - 原码
	//01111111111111111111111101111111 - 反码
	//01111111111111111111111110000000 - 补码
	//10000000 - char 类型取1个字节
	//11111111111111111111111110000000 - 整形提升(补码)
	//因为按照 unsigned int 打印,所以原反补相同,所以最高位1不是符号位,而被认为是数值位
	printf("%u\n", a);//4294967168
	return 0;
}

 

再看一段代码

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

答案和解析如下(先挖个坑)

 

再看一段

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

这段代码打印结果是hehe死循环,原因如下:

当i=256时,存在unsigned int 中的原码为

00000000000000000000000100000000

补码为

01111111111111111111111100000000

因为时char类型的变量,所以要进行截断,截断后补码为

00000000

意思就是255+1=0,因此i会如此往复循环下去

 

 

浮点型在内存中的存储(先挖个坑,之后补上)

常见的浮点数:3.14,1E10(科学计数法,表示1.0×10^10)

浮点数家族包括:float,double,long double类型

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值