栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

剖析数据在内存中的存储

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

剖析数据在内存中的存储

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录
  • 前言
  • 一、数据类型基本归类
    • 1.C语言中给的基本内置类型与归类
      • (1)整型家族
      • (2)浮点型家族
      • (3)构造类型
      • (4)指针类型
      • (5)空类型
  • 二、整型在内存中的存储
    • 2.1原码,反码,补码
    • 2.2大端存储和小端存储
    • 2.3练习
      • (1)
      • (2)
      • (3)
      • (4)
      • (5)
  • 三:浮点数在内存中的存储
      • 3.1浮点数在内存中的存储规则
      • 3.2练习
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

了解了数据在内存中如何存储,如何取用,对我们修改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

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

int main()
{
	int a = 1;
	char b = *((char*)&a);
	printf("%dn", b);

	return 0;
}

取出a的地址,进行强制类型转化,取出第一个字节内的数值,赋给b,进行打印

2.3练习 (1)
//输出什么?
#include 
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 
int main()
{
  char a = -128;
  printf("%un",a);
  return 0;
}

-128的补码为:11111111111111111111111110000000,截断后10000000
因为a是一个char类型的数据,所以整型提升后为11111111111111111111111110000000
以无符号形式打印出来

(3)
#include 
int main()
{
  char a = 128;
  printf("%un",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这个函数会从给出的地址往后读,直到遇到‘’,那么当a[i]=='’时,就停止

如图所示,a[i]的数值会随着圈的逆时针变化

(5)
#include 
unsigned char i = 0;
int main()
{
  for(i = 0;i<=255;i++)
 {
    printf("hello worldn");
 }
  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的值为:%dn",n);
printf("*pFloat的值为:%fn",*pFloat);
*pFloat = 9.0;
printf("num的值为:%dn",n);
printf("*pFloat的值为:%fn",*pFloat);
return 0;
}

n的十六进制表示为0x00 00 00 09
转化为二进制为0 00000000 00000000000000000001001
这里的指数位置全为0,我们上面有介绍到,指数位置需要加一个中间数127,所以原本的指数是很小的,所以以浮点数打印出来是很小的,直接为0
再以浮点数9.0,来存放进去,二进制形式为1001.0==>(-1) ^ 01.00102^3
所以放进去为01000001000100000000000000000000
再把这个二进制换成整数,就是结果

总结

数据在内存中如何存储,有助于我们深度了解bug的成因,这也是我的第一次写博客,有什么不对的地方欢迎指出。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1019013.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号