前言
在C语言中,数据类型的不同,他们在内存中所开辟的空间大小也有所不同,因此,一个变量的创建是需要在内存中开辟空间的,而空间的大小是根据不同的类型决定的。那么数据在内存中又是怎样来存储的呢?今天博主就带大家来一探究竟。
数据类型的介绍
基本的数据类型我们都知道有这几种:
数据类型 | 类型名称 |
---|
char | 字符数据类型 | short | 短整型 | int | 整形 | long | 长整型 | long long | 更长的整形 | float | 单精度浮点数 | double | 双精度浮点数 |
除了基本的数据类型还有构造类型,指针类型和空类型 构造类型:
数组类型
结构体类型 struct
枚举类型 enum
联合类型 union
指针类型:
int* pi;
char* pc;
float* pf;
void* pv;
空类型:
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型。
基本的数据类型,他们又可以被细分为整形家族和浮点数家族。 整形家族:
char short int long
浮点数家族:
float double
可能会有小伙伴问,char 不是字符型数组吗?为什么会被划分在整形家族里,而不是单独为他开一个家族。
char 不是字符型数组吗?
因为我们的C语言是有一张ASKI I 码表的,所有的字符,都可以在里面找到用对应的数字来表示
除此之外,整形家族还可以再次细分为有符号数和无符号数 有符号数:
signed char
signed short
signed int
signed long
无符号数
unsigned char
unsigned short
unsigned int
unsigned long
这里的有符号数和无符号数有什么区别吗?答案是有的。 有符号数和无符号数数据类型的范围是不一样的。 以char 型为例:
char的无符号数的范围:0~255
char的有符号数的范围:-128~127
注意:在计算机中存储的二进制码是整数原来的二进制码的补码。
原码、反码、补码
在计算机中的整数有三种表示方法,即原码、反码和补码。 三种表示方法均有符号位和数值位两部分,符号位都是用“0”表示“正”,用“1”表示“负”,而数值位负整数的三种表示方法各不相同。
原码
直接将二进制按照正负数的形式翻译成二进制就可以
反码
将原码的符号位不变,其他位依次按位取反就可以得到了。
补码
反码+1得到补码
正数的原、反、补码都相同。 对整形来说:数据存放内存中其实存放的都是补码。 原因:
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理。 同时,加法和减法也可以统一处理(CPU只有加法器),此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
然后我们再来看看再内存中的存储: 这里我们可以很明显的看到,对于a 和b 分别存储的是补码,但是顺序不对,这是为什么? 这就是我们接下来要谈到的大小端了。
大小端介绍
什么是大端,小端? 大端模式:指数据的低位(比如个位)保存在内存的高地址中,而数据的高位(比如十位),保存在内存的低地址中。 小端模式:指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。 如何判断当前机器的字节序(大小端)?
#include<stdio.h>
int main()
{
int a=1;
char* p=(char*)&a;
if(*p==1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
为什么要有大小端? 在计算机中,我们都是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编译器) 另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。 可能有人会说为什么他不是这样:
假设我们还没有规定内存数据该怎么存,这种存储方式也是可以的,但是,这种存储方式不利于你取出,你把数据存放进去了是不假,问题是你怎么取出来,你是用的一种什么样的规律来将它存进去的?所以说最后只留下了大小端,原因就是方便且简单。
|