提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
了解了数据在内存中如何存储,如何取用,对我们修改bug很有帮助
提示:以下是本篇文章正文内容,下面案例可供参考
一、数据类型基本归类
1.C语言中给的基本内置类型与归类
(1)整型家族
int----------------------------4个字节
char-------------------------1个字节(内存中以ASCII值存放,所以算是整型家族的1一员)
short------------------------2个字节
long-------------------------4 / 8个字节
long long------------------8个字节
== 注:这些数据类型又分为signed和unsigned两种类型。==
(2)浮点型家族
float
double
== 两种类型的精确度不同,后面会谈到 ==
(3)构造类型
数组类型
结构体类型(struct)
枚举类型(enum)
联合类型(union)
(4)指针类型
int*
char*
float*
void*
(5)空类型
void
二、整型在内存中的存储
int x=10;
int y=20;
类似x,y这样的变量在内存中会开辟四个字节的空间,那么会如何存储呢?
2.1原码,反码,补码
计算机中的整数通过原码,反码,补码存放在内存中。
对于signed类型的数据来说,这三种表示方法通常都有符号位和数值位两部分。
符号位是二进制的第一个数字,用1表示正,用0来表示负。
正数的原,反,补都是一样的
负数的原码可以直接通过数值翻译
反码将符号位不变,其他位取反得到
补码课通过将反码加一得到
计算机中整型在内存中存储的都是补码
运用补码可以将符号位和数值位进行统一处理,而不需要拆开分别计算
2.2大端存储和小端存储
大端存储就是将数据的低位存放到内存高地址处,数据的高位放在内存的低地址处
小端存储就是将数据的高位存放到内存高地址处,数据的低位放在内存的低地址处
#include<stdio.h>
int main()
{
int a = 10;
int b = -10;
return 0;
}
a的值是10,转化为十六进制为0x0000000a,如图就是小端的存储模式
那么如何用代码进行大端小端的判断呢
以int a = 1来计算
以十六进制存放为0x00000001
大端中00 00 00 01
小端中01 00 00 00
可以通过内存中数据的第一个字节可以判断出是大端还是小端
所以可以通过以下代码来求出
#include<stdio.h>
int main()
{
int a = 1;
char b = *((char*)&a);
printf("%d\n", b);
return 0;
}
取出a的地址,进行强制类型转化,取出第一个字节内的数值,赋给b,进行打印
2.3练习
(1)
//输出什么?
#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;
}
打印时要进行整型提升
-1作为整型,补码为11111111111111111111111111111111,截断后,变成11111111
通过a,b,c的不同类型来进行判断值的大小
(2)
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
-128的补码为:11111111111111111111111110000000,截断后10000000
因为a是一个char类型的数据,所以整型提升后为11111111111111111111111110000000
以无符号形式打印出来
(3)
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
解释过程同(2)
(4)
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
strlen这个函数会从给出的地址往后读,直到遇到‘\0’,那么当a[i]=='\0’时,就停止
如图所示,a[i]的数值会随着圈的逆时针变化
(5)
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
unsiged char类型最大值就是128,所以会打印死循环
三:浮点数在内存中的存储
3.1浮点数在内存中的存储规则
任一个二进制浮点数在内存中存储的形式为
V=(-1)^S* M *2 ^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
就比如5.0,二进制为101.0==>(-1)^0 * 1.010* 2^2
对于一个32位的平台来说:
对于一个64位平台来说:
== 注:对于有效数字M,由于它的大小为1~2,所以系统默认将第一位的1舍去不存,在使用时加上(如1.001在存储时只放001)。
对于无符号E来说,可能存在负数的情况,所以我们就在存储时给它加上一个中间数。32位平台加127,64位平台加1023
3.2练习
下面给一道例题解释
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;
}
n的十六进制表示为0x00 00 00 09
转化为二进制为0 00000000 00000000000000000001001
这里的指数位置全为0,我们上面有介绍到,指数位置需要加一个中间数127,所以原本的指数是很小的,所以以浮点数打印出来是很小的,直接为0
再以浮点数9.0,来存放进去,二进制形式为1001.0==>(-1) ^ 01.00102^3
所以放进去为01000001000100000000000000000000
再把这个二进制换成整数,就是结果
总结
数据在内存中如何存储,有助于我们深度了解bug的成因,这也是我的第一次写博客,有什么不对的地方欢迎指出。