数据的存储的那一点点
作者:互联网
目录
1.基本的内置类型
char //字符数据类型 (1字节)
short //短整型 (2字节)
int//整形 16位是2字节 32/64位是4字节
long //长整型 规定sizeof(long) >= sizeof(int)
long long //更长的整形 (8字节)
float //单精度浮点数 (4字节)
double //双精度浮点数 (8字节)
C语言没有字符串类型
冷门的布尔类型:
布尔类型:_Bool (C99才引入) 专门来表示真假
在C中,一般我们用0表示假,非0表示真,用 Bool 表示真假如下:
#include <stdio.h>
#include <stdbool.h> // 引入新的头文件
int main()
{
_Bool flag = false; //表示假
//_Bool flag = true; //表示真
if (flag)
{
printf("hello\n");
}
return 0;
}
本质上是对 int 类型进行重命名,在C中应用并不广泛,感兴趣的小伙伴可以深入了解一下。
更多类型可以上:cppreference.com 查看
1)基本归类
整型
char (因为字符对应的ASCII码位整数,因此char归入整型)
unsigned char
signed char
short
unsigned short [int]
signed short [int]
int
unsigned int 无符号整型
signed int 有符号整型
long
unsigned long [int]
signed long [int]
一般的: int 等价于 signed int
其他类型同理相同:long 等价于 signed long
short 等价于 signed short
注: char 不等于 signed char
char 等于 signed char 还是 unsigned char 取决于编译器的实现。
打印无符号整数是用 %u ,不用 %d
如果:
unsigned int num = -10; printf("%u\n",num);
浮点型
float 单精度浮点型
输入用 %f 输出用 %f
double 双精度浮点型 精度更高
输入用 %lf 输出一般用 %f
构造类型->自定义类型
-> 数组类型
int a[5]; //类型int [5] int b[10]; //类型int [10]
-> 结构体类型 struct
//自定义结构体类型 struct Water { int price; //价格 int num; //数量 };
-> 枚举类型 enum
-> 联合类型 union
指针类型
int *pi; 接收整型地址
char *pc; 接收字符地址
float* pf; 接收浮点型地址
void* pv; 接收空指针地址
空类型:
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型。
2.整形在内存中的存储
我们先来声明两个整型变量:
a=10;b=-10;
调试中监视他们的地址:
整型存储为四个字节,我们分析时只需对地址的前四列分析即可。
2.1 原码、反码、补码
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位负整数的三种表示方法各不相同。
原码:直接将二进制按照正负数的形式翻译成二进制。
反码:将原码的符号位不变,其他位依次按位取反。
补码:反码+1得到补码。
注:正数的原、反、补码都相同。
对于整形来说:数据存放内存中其实存放的是补码。
下面来分析上述a,b的内存:
由上述分析可知,整数在内存中的存储是以二进制补码转换为十六进制来进行的,但是我们发现我们分析出来的与编译器上显示出来的顺序好像不一样,这是为什么呢?那我们继续接下来的一个知识点。
2.2大小端介绍
1)什么是大端小端
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
内存中,地址由低----->高
我们分析的十六进制 由高位到低位。
因此这两个整型变量在内存中符合小端存储模式。
2)为什么会有大端小端
在计算机系统中,我们是以字节为单位的,每个地址单 元都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的 short型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位 或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
3)判断自己的编译器是大端存储还是小端存储
#include <stdio.h>
int main()
{
int a = 1;
char* p= (char*)&a;
if (*p==1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
我们不难看出
如果是大端存储:则应该是:00 00 00 01
如果是小端存储:则应该是:01 00 00 00
3.浮点型在内存中的存储
以下面案例来说明:
#include <stdio.h>
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
return 0;
}
我们可以看到*pFloat和num的值与我们常规思维计算出来的值不同,为了搞清楚原因,我们先要知道以下标准:
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
什么意思呢?以浮点数5.5为例
由于这个国际标准。因此我们在内存中存储浮点数时只需要存储它对应的S、M、E的值即可:
注意:1.因为M大于等于1,小于2,所以存储时只存储小数点后的数
2.IEEE 754规定,存入内存时E的真实值必须再加上一个中间数, 对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^3E时3,则存在8位上是是存127+3=130,则为10000010
3.E全为0 这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于 0的很小的数字
4.E全为1 这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)
那现在来分析开始时的案例:
上部分*pFloat:
9 -> 0 00000000 00000000000000000001001
S E M
则为(-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146) 显然,这是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000。
存进去时加上127才等于00000000=1,那取出来是则是1-127=-126
下部分num:
9.0 -> 1001.0 ->(-1)^01.0012^3 -> s=0, M=1.001,E=3+127=130
0 10000010 00100000000000000000000
S E M
0x 4 1 1 0 0 0 0 0
由图可得为小端存储
换算为10进制即 1091567616
标签:小端,存储,int,char,一点点,内存,类型,数据 来源: https://blog.csdn.net/weixin_53316121/article/details/121707424