概述
剖析各种数据类型在内存中是怎样储存的?
家人们集美们,就是说咱们接下来会有一个大动作,那咱们先来浅读一下吧
推荐使用电脑端观看!手机端观感很差!
学习重点:
- 各种数据类型的具体介绍
- 整数在内存中存储:原码,反码,补码
- 大小端字节序
- 浮点数在内存中的存储
数据类型的介绍
-
各种数据类型
-
char //字符数据类型
char类型其实是属于整型家族中的,因为char类型实际存储的是ASCII码,ASCII为整数,所以char类型属于整形家族
-
short //短整型
-
int //整形
在早期的16位机器上是2个字节,在现在的32、64位机器上是4字节
-
long //长整型
C语言规定,sizeof(long)>=sizeof(int)
-
long long //更长的整形
-
float //单精度浮点数
-
double //双精度浮点数
-
_Bool //布尔类型:专门用来判断真假的
但其实在C语言中,对于布尔变量用的不多,其实本质就是把int进行了重命名
使用布尔类型要引用头文件:
#include<stdbool.h>
举个例子:
#include <stdbool.h> #include<stdio.h> int main() { _Bool flag = true; if (flag)//flag为真时打印 { printf("hehen"); } return 0; }
-
-
类型的基本归类
-
整形家族:
char
-
unsigned char
-
signed char
char到底是unsigned char还是signed char是取决于编译器的,常见的编译器中char是signed
char的
short
- unsigned short
- signed short
short是signed short
int
- unsigned int
- signed int
long
- unsigned int
- signed int
long是signed long
-
注:无符号数不应该用%d打印,应该用==%u==打印
举个例子:
#include<stdio.h> int main() { //正数:打印用%d %u都没问题 unsigned int num = 10; printf("%dn", num); printf("%un", num); //负数:打印用%d没问题,用%u会错误 unsigned int n = -10; printf("%dn", n); printf("%un", n); return 0; }
-
浮点数家族:
- float 单精度浮点数 4个字节
- double 双精度浮点数 8个字节
-
构造类型(自定义类型)
-
数组类型
数组的类型:去掉数组名(可以通过更改数据类型,元素个数来改变数据类型)
-
结构体类型 struct
-
枚举类型 enum
-
联合类型 union
-
-
指针类型
-
int* pi;
-
char* pc;
-
float* pf;
-
void* pv;
空类型:void表示空类型,即无类型
举个例子:
//返回值类型为空 参数为空 指针类型为void* void test(void) { void* p; } int main() { test(); return 0; }
-
-
整数在内存中的存储
-
原码 反码 补码
-
原码 反码 补码都由符号位 数值位组成
-
符号位:0正1负
-
数值位:
- 原码:直接将二进制按照正负数的形式翻译成二进制就可以。
- 反码:将原码的符号位不变,其他位依次按位取反就可以得到了。
- 补码:反码+1就得到补码。
-
正数的原反补相同,负数的原反补需要计算
-
在内存中其实存放的是补码
原因:
接下来,我们讲解几个例子
例子1:内存在VS2019怎么进行查看
-
按下键盘上的F10开始调试(部分笔记本用户需要按住Fn+F10,不过你也可以把Fn键锁上,方法:Fn+Esc,这时候你的Fn键就被锁了,直接按F10开始调试)
-
调试->窗口->内存->随便选择一个
-
输入&a,然后回车
-
我们需要关注的区域
例子2 :15与-15的原码 反码 补码
例子3 :10和-10的原码 反码 补码
-
-
大小端字节序
-
什么是大端小端:
-
举例:
int a = 1; ->0x 00 00 00 01
-
一道笔试题:来自百度2015年系统工程师笔试题
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。
大端字节序存储: 当一个数据的低字节的数据存放在高地址处,高字节序的内容放在了低地址处,这种存储方式就是大端字节序存储
小端字节序存储:当一个数据的低字节的数据存放在低地址处。高字节序的内容,放在了高地址处,这种存储方式就是小端字节序存储
代码实现:
思路:
#include<stdio.h> int check_sys() { int a = 1; char *p = (char*)&a;//char类型的指针一次能访问一个字节,访问一次就是访问了第一个字节的内容 if (1 == *p) return 1;//小端 else return 0;//大端 } int check_sys() { int a = 1; char* p = (char*)&a; return *p; } int check_sys() { int a = 1; return *(char*)&a;//強转之后解引用,解引用访问一个字节 } int main() { int ret = check_sys();//返回1是小端,返回是大端 if (1 == ret) { printf("小端n"); } else { printf("大端n"); } return 0; }
-
-
八道练习题,让你直接起飞,芜湖~
-
下面程序输出什么?
#include <stdio.h> 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; }
-
下面程序输出什么?
#include <stdio.h> int main() { char a = -128; printf("%un", a); return 0; }
-
下面程序输出什么?
#include <stdio.h> int main() { char a = 128; printf("%un",a); return 0; }
-
下面程序输出什么?
#include <stdio.h> int main() { int i = -20; unsigned int j = 10; printf("%dn", i + j); //按照补码的形式进行运算,最后格式化成为有符号整数 return 0; }
-
下面程序输出什么?
#include <stdio.h> int main() { unsigned int i; for (i = 9; i >= 0; i--) { printf("%un", i); } return 0; }
-
下面程序输出什么?
#include <stdio.h> int main() { char a[1000]; int i; for (i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d", strlen(a)); return 0; }
-
下面程序输出什么?
#include <stdio.h> unsigned char i = 0; int main() { for (i = 0; i <= 255; i++) { printf("hello worldn"); } return 0; }
-
下面程序输出什么?
#include <stdio.h> int main() { unsigned char a = 200; unsigned char b = 100; unsigned char c = 0; c = a + b; printf("%d %d", a + b, c); return 0; }
-
-
经历了这死亡八道题,你的表情是如何呢?是 ฅ՞•ﻌ•՞ฅ?是 (-̩̩̩-̩̩̩-̩̩̩-̩̩̩-̩̩̩___-̩̩̩-̩̩̩-̩̩̩-̩̩̩-̩̩̩)?是 Σ(-`Д´-ノ;)ノ?还是 ∑(O_O;)呢?选择你的答案吧。
浮点型在内存中的存储
常见的浮点数:
- 字面型浮点数:3.14159
- 1E10->1.0*10^10
- 浮点数家族包括: float、double、long double 类型。
- 浮点数表示的范围:float.h中定义
在VS2019中输入#include<float.h>,然后右键->转到文档
从第85行开始就有关于float类型的具体内容了
-
一个浮点数存储的例子
#include<stdio.h> int main() { int n = 9; float* pFloat = (float*)&n; printf("n的值为:%dn", n); printf("*pFloat的值为:%fn", *pFloat); *pFloat = 9.0; printf("num的值为:%dn", n); printf("*pFloat的值为:%fn", *pFloat); return 0; }
运行结果:
震惊!第一个打印的*pFloat怎么不是9.000000?第二个人打印的n怎么不是9.0?
那么其实整数与浮点数的存储方法不同
-
浮点数的存储规则
浮点数无原码 反码 补码
-
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。举个例子:5.5写成IEEE754形式
-
IEEE 754规定:
-
对于32位(float)的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。
-
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
-
IEEE 754对有效数字M和指数E,还有一些特别规定。
- 存进去:
- 有效数字M:前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。 - 指数E:IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。
- 有效数字M:前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
- 拿出来:
- E不全为0或不全为1:指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
- E全为0:浮点数的指数E等于==1-127(或者1-1023)==即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。
- E全为1:如果有效数字M全为0,表示±无穷大(正负取决于符号位S)(不做深入研究)
- 存进去:
-
-
-
刚开始的例子讲解:
通过这一篇文章,相信你已经对数据在内存中的存储已经得心应手了,下一篇文章,我们会进行高难度指针的探索,希望你不要害怕做好准备!加油 !
喜欢这篇文章的话,请一件三连!感谢!!!
最后
以上就是害怕过客为你收集整理的浅学C语言-精准分析各种数据在内存中的存储篇剖析各种数据类型在内存中是怎样储存的?的全部内容,希望文章能够帮你解决浅学C语言-精准分析各种数据在内存中的存储篇剖析各种数据类型在内存中是怎样储存的?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复