剖析数据在内存中的存储(上)

简介: 剖析数据在内存中的存储(上)

数据类型的介绍

我们知道一些基本数据数据类型的使用,例如

类型的意义:

  1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。
  2. 如何看待内存空间的视角

类型的基本归类:

整形:

浮点型:

还有一些构造类型、指针类型、空类型等。

整形在内存中的存储

我们知道过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。

那接下来我们谈谈数据在所开辟内存中到底是如何存储的`

int a=20;
int b=-10;

可以知道a和b都是整形分配了4个字节,那么他们是如何存储的呢?

原码、反码、补码

在此之前我们需要了解一下计算机中整数的三种二进制的表示方法。相信大家一定有所了解,在这里给大家简单介绍一下。

三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位

正数的原、反、补码都相同。

负整数的三种表示方法各不相同。

所以我们在此只说一下负数的情况

对于原码来说,正负数都是直接转化为二进制数即可得到该数的原码。

对于反码来说,原码的符号位不变,其他位取反即可得到。

对于补码来说,给反码+1即可得到补码。

对于整形来说:数据存放内存中其实存放的是补码。

为什么呢?

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统

一处理;

同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程

是相同的,不需要额外的硬件电路。

那么我们了解了之后看一下在内存中a和b的存储情况

int a=20;
//正数的原码补码相同
//00000000000000000000000000010100  在内存中存储是16进制我们将其转化为16进制
//0000  0000  0000  0000  0000  0000  0001  0100
//00 00 00 14  (16)

再看一下b的情况

int b=-10;
//原码 10000000000000000000000000001010
//反码 11111111111111111111111111110101
//补码 1111 1111 1111 1111 1111 1111 1111 0110
//十六进制ff ff ff f6

但这种情况似乎和存储的情况不太一样。

大小端介绍

什么大端小端:

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址 中;

小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地 址中。

为什么有大端和小端:

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元

都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short

型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32

位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因

此就导致了大端存储模式和小端存储模式。

例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为

高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高

地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51 则

为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式

还是小端模式。

我常用的编译器是vs,那么我们来验证一下,使用vs验是大端存储还是小端存储

#include<stdio.h>
int check_sys()
{
  int i = 1;//定义一个变量i=1
  return (*(char*)&i);//取出变量i的地址强制转化为(char*)类型 返回首字节的值
}
int main()
{
//1的16进制为00 00 00 01
//若小端存储则首字节为01即为1
  int ret = check_sys();
  if (ret == 1)
  {
    printf("小端存储");
  }
  else
  {
    printf("大端存储");
  }
  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;
}

我们刚刚已经了解了整形的存储方式那么不妨来试一下这样一道题。

运行结果是 -1 -1 255

相信大家能知道为什么a和b是-1,那么接下来来分析一下为什么是255

unsigned char c=-1;
//原码    10000000000000000000000000000001
//反码    11111111111111111111111111111110
//补码    11111111111111111111111111111111
//因为unsigned char 仅一个字节所以截取8个bit位即为
//        11111111
//对于unsigned来说没有符号位则将111111111转化为10进制即为255

那么我们再来看另一道题

#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0;
}

我们来逐步分析一下

char a=-128;
//原码  10000000000000000000000010000000
//对于char型只能取一个字节也就是10000000
//打印为整形对其作整形提升也就是
//      11111111111111111111111110000000
//%u 打印无符号的整数,也就是将补码11111111111111111111111110000000
//转化为10进制

结果是一样的,说明确实是这样进行存储的,如果大家不懂如何整型提升的话,向大家推荐一篇文章给大家详细了解整型提升:

http://t.csdn.cn/RfDIU 原作者:@bit_Sakura

那么我们来分析一下char——假设 是有符号的char

所以signed char的范围是-128~127

如果是无符号的unsigned char

所以unsigned char的范围是0·255

目录
相关文章
|
7天前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
28 11
|
30天前
|
监控 算法 应用服务中间件
“四两拨千斤” —— 1.2MB 数据如何吃掉 10GB 内存
一个特殊请求引发服务器内存用量暴涨进而导致进程 OOM 的惨案。
|
29天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
60 1
|
1月前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
1月前
|
监控 Java easyexcel
面试官:POI大量数据读取内存溢出?如何解决?
【10月更文挑战第14天】 在处理大量数据时,使用Apache POI库读取Excel文件可能会导致内存溢出的问题。这是因为POI在读取Excel文件时,会将整个文档加载到内存中,如果文件过大,就会消耗大量内存。以下是一些解决这一问题的策略:
102 1
|
1月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
1月前
|
缓存 安全 Java
使用 Java 内存模型解决多线程中的数据竞争问题
【10月更文挑战第11天】在 Java 多线程编程中,数据竞争是一个常见问题。通过使用 `synchronized` 关键字、`volatile` 关键字、原子类、显式锁、避免共享可变数据、合理设计数据结构、遵循线程安全原则和使用线程池等方法,可以有效解决数据竞争问题,确保程序的正确性和稳定性。
41 2
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
385 0
|
1月前
|
存储 编译器
数据在内存中的存储
数据在内存中的存储
42 4
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
56 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配