数据在内存中是如何存储的?(上)

news2025/1/11 18:31:56

C语言进阶——数据在内存中是如何存储的?

  • 一. 整型数据的二进制表示
  • 二.数据类型详细介绍
    • 1.1 类型的基本归类
    • 1.2认识有无符号的区别( signed 和 unsigned )
    • 1.3代码理解一:
    • 1.4代码二理解:
    • 1.5代码三理解:
    • 1.6代码四理解:
    • 1.7代码五理解:
  • 三. 大小端字节序介绍及判断

一. 整型数据的二进制表示

整型数据的二进制表示形式有三种:原码,反码,补码
1.原码:根据类型来表示二进制位数,最高一位为符号位(1表示负数,0表示正数)
2.反码:原码的符号位不变,其余按位取反;
3.补码:反码 + 1

注意一点:正数和负数的原码,反码,补码有区别!!!
正数:原码,反码,补码是相同的。
负数:原码,反码,补码按上面条件改变

上面三种是怎样表示呢?举一个简单例子

`创建一个整型变量num,在内存中开辟了四个字节的空间存放数据,四个字节 = 32 个比特位,也就是32位二进制

int num = 10;

原码:
00000000000000000000000000001010
反码:
00000000000000000000000000001010
补码:
00000000000000000000000000001010

int num = -10;
原码:
10000000000000000000000000001010
反码:(符号位不变,其余按位取反)
1111111111111111111111111111111110101
补码:(反码 + 1)
1111111111111111111111111111111110110

注意三点:
1.内存中存储的是补码。

为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统
一处理;
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程
是相同的,不需要额外的硬件电路。

2.在内存中用一般用十六进制来表示的。

因为1个十六进制位可以表示4个二进制位,那在内存查看变量时,只用看(32 /4)8位即可,方便查看。
在这里插入图片描述

3.内存中补码是倒着存储的。
在这里插入图片描述

二.数据类型详细介绍

C语言有哪些基本数据类型?

char         //字符数据类型,      1个字节大小(以64平台为例)
short        //短整型             2个字节大小
int          //整型               4个字节大小
long long    //更长的整型         8个字节大小
float        //单精度浮点型       4个字节大小
double       //双进度浮点型       8个字节大小
char*        //字符型指针类型     8个字节大小
int*         //整型指针类型       8个字节大小
double       //双精度型指针类型   8个字节大小

1.1 类型的基本归类

整型家族

char
    unsigned char
    signed char
short
    unsigned short
    signed short
int 
    unsigned int 
    signed int
long
    signed long
    unsigned long
long long
    unsigned long long
    unsigned long long

为什么char类型属于整型呢?
因为字符存储的时候,存储的是ASCII码值,是整型,所以在归类位整型家族

浮点型家族:

float
long float
double
long double

指针类型家族:

int*
char*
float*
double*
void*

空类型:

void //表示空类型(无类型)
     //一般用于函数的返回类型,函数的参数,指针类型

构造类型:(自定义类型和变量)

数组类型 类型 数组名[]
结构体类型 struct
枚举类型 enum
联合类型 union

1.2认识有无符号的区别( signed 和 unsigned )

对于整型家族的类型来说,有符号和无符号是由区别的,不同的的编译器识别在区分char时也所有不同,有些是定义成signed
char,有些是定义成unsigned char; char 在VS2019上是 signed char。但是可以确定的是,

short == signed short;int ==signed int等

signed char 和 unsigned char的区别是什么呢?

signed char

我们知道char类型是一个字节(8个比特位)
假设它的二进制位是:01010111
首位就是它的符号位。
下图是八个比特位存放在二进制中的所有可能,因为首位是符号位,所以我们由此可知,
sigened char的取值范围是 -128 ~ 127而且只会在这个范围,超出的部分进行下一次循环。
在这里插入图片描述
在这里插入图片描述

unsigned char

二进制的每一位都是数值位,没有符号位。
假设unsigned char的二进制位是:10010101
则unsigned char八比特位二进制位取值范围:0 ~ 255
同理,即使数值递增也不会超出这个范围,超出部分进行下一次循环。

在这里插入图片描述

在这里插入图片描述

理解到这里,我们看些代码强化一下,尤其注意无符号类型(unsigned)。

1.3代码理解一:

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;
}

char a变量值的是-1;先用32位二进制位求出补码。
原码:10000000000000000000000000000001
反码:11111111111111111111111111111110
补码:11111111111111111111111111111111
但因为是存放char类型中,只能取8个bite位,从补码后面截断8个比特位,得到11111111
但是用%d(十进制的形式打印有符号整型整数)形式来打印,所以发生了整型提升(a是有符号类型,所以用符号位的数补全二进制位32位数)得到:
补码:11111111111111111111111111111111
反码: 11111111111111111111111111111110
原码:10000000000000000000000000000001
所以char a的输出值应该是 - 1;
同理,因为char == signed char,char a 和 signed char b是一样的,所以 signed char b的输出值也应该是 -1;

unsigned char c的变量值是 - 1;先用32位二进制位求出补码。
原码:10000000000000000000000000000001
反码:11111111111111111111111111111110
补码:11111111111111111111111111111111
但因为是存放char类型中,只能取8个bite位,从补码后面截断8个比特位,得到11111111
重点在这里!!!因为c变量是unsigned char,不考虑符号位,全是数值位,在发生整形提升时,统统补0就好了。所以得到:
补码:00000000000000000000000011111111
符号位是0,说明是正数,所以反码,原码相同,输出的值应该是255.
在这里插入图片描述

1.4代码二理解:


int main()
{
	char a = -128;
	printf("%d\n", a);
	printf("%u\n", a);
	return 0;
}

先求出 -128的补码:
原码:10000000000000000000000010000000
反码:11111111111111111111111101111111
补码:11111111111111111111111110000000
因为是char 类型,只能存放后面8bite位,发生截断得到:10000000
又因为是char类型,补的是符号位,得到:11111111111111111111111110000000。
如果使用%d打印,符号位是1,是负数,补码需要转变成原码:最后的结果自然是 -128;
如果使用%u(十进制的形式打印无符号整型整数)打印,%u没有符号位的概念,所有二进制位都是数值位则打印的就是:11111111111111111111111110000000
这数字很大,你忍一下。打印的是:4294967168
在这里插入图片描述

1.5代码三理解:

#include<stdio.h>
#include<Window.h>
int main()
{
	unsigned int i;
	for(i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
		Sleep(1000);//减慢打印时间
		            //单位是毫秒
	}

	return 0;
}

其实很容易看出代码死循环了,因为unigned int 是无符号整型恒大于等于0,跳不出for循环。当 i = -1时,原本要跳出了的,但因为是无符号类型,负1的补码是:
11111111111111111111111111111111。所以打印的是一个很大的数。
在这里插入图片描述

1.6代码四理解:

int main()
{
	char a[1000];
	int i;
    for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));	
	return 0;
}

先看for的条件的条件,i从0递增至1000次
,再看a[ i ]的赋值。
-1,-2,-3,-4,-5,-6,-7…-998,-999。
但是前面我们说了,char的取值范围是-128 ~ 127。多出的部分进行下一次循环。
所以应该是如图:
在这里插入图片描述
strlen函数测的是字符串长度,判断结束的条件是遇见’0’;所以strlen在遇到第256个数字0时,就结束了判断。所以最终的输出应该是255;
在这里插入图片描述

1.7代码五理解:

#include <stdio.h>

unsigned char i = 0;//0~255
int main()
{
for (i = 0; i <= 255; i++)
       {
          	printf("hello world\n");
       }
	return 0;
}

unsigned char 的取值范围是0 ~ 255
所以是死循环了。

在这里插入图片描述

三. 大小端字节序介绍及判断

什么大端小端?

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

为什么有大端和小端:

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8 bit的char之外,还有16 bit的short型,32bit的long型(要看具体的编器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。 例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22放在高地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式

简而言之,变量在内存中存放的字节序(以字节为单位来讨论存储的顺序)在不同编译器上不同,有些编译器是小端字节序存储,反之是大端字节序存储。小端字节序存储是把一个数据的低位字节的内容,存放在低地址处,把一个数据的高位字节的内容,存放在高地址处。
大端字节序存储是把一个数据的低位字节的内容,存放在高地址处,把一个数据的高位字节的内容,存放在低地址处。

举个简单例子:
在这里插入图片描述
你可以写个程序来判断你的编译器的大小端

int main()
{
	int a = 1;//整型存放四个字节 00 00 00 01
	          //用字符p来接收整型的第一个字节
	char* p = (char*)&a;//a强制类型转换后取得一个字节的内容
	if (*p == 1)        //用1 或 0判断段大小端存放
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

在这里插入图片描述
我用的时VS2019,是小端字节序存储。
在这里插入图片描述

小编愚钝,如果有错误的地方请在评论区批评指出,看官走的时候给我个赞赞支持一下呗,谢谢。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/580406.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【P40】JMeter 录制控制器(Recording Controller)

文章目录 一、录制控制器&#xff08;Recording Controller&#xff09;二、准备工作三、测试计划设计 一、录制控制器&#xff08;Recording Controller&#xff09; 可以理解为一个占位符&#xff0c;用来告诉代理服务器将脚本录制到何处&#xff0c;本身无任何逻辑作用&…

AI时代来临,新时代程序员如何紧追时代的风口浪尖?

文章目录 背景AI时代的背景和机遇抓住AI时代的机遇新时代程序员的技能和素质实践建议和资源总结 背景 在这个快速发展的AI时代&#xff0c;程序员们正置身于科技革新的前沿。随着人工智能技术的蓬勃发展和广泛应用&#xff0c;程序员的作用变得愈发重要和关键。他们不再是简单…

Doris之rollup上卷及物化视图

Rollup上卷 通过建表语句创建出来的表称为 Base 表&#xff08;Base Table,基表&#xff09; 在 Base 表之上&#xff0c;我们可以创建任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的&#xff0c;并且在物理上是独立存储的。 Rollup表的好处&#xff1a; 和基表…

如何在华为OD机试中获得满分?Java实现【最长的连续子序列】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

如何在华为OD机试中获得满分?Java实现【滑动窗口】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

软件测试理论----接口测试中restful接口状态码规范

一、restful接口状态码总体分类 类别描述1xx&#xff1a;信息通信传输协议信息2xx&#xff1a;成功表示客户端的请求已成功接受3xx&#xff1a;重定向表示客户端必须执行一些其他操作才能完成其请求4xx&#xff1a;客户端错误此类错误状态码指向客户端5xx&#xff1a;服务器错…

在SPSS Statistics中使用R(插件)

date: 2018-10-30 09:26:33 在SPSS中使用R&#xff08;插件&#xff09; 谷歌或者百度“SPSS中调用R”, 最详细也是最靠谱的就是IBM SPSS社区的这两篇文章: https://www.ibm.com/developerworks/cn/data/library/ba/ba-1401spss-r/https://www.ibm.com/developerworks/cn/ana…

基于Open3D的点云处理6-点云去噪

当我们从扫描设备获取点云数据时&#xff0c;数据会包含噪声和伪影&#xff0c;点云噪声特性包括不真实的点、孤立点、不规则&#xff0c;基于噪声特性对器进行去除&#xff1b; 统计滤波 Statistical Outlier Removal&#xff08;SOR&#xff09;&#xff08;去除离群点&…

【JVM】13. 垃圾回收器

文章目录 13.1. GC分类与性能指标13.1.1. 垃圾回收器概述13.1.2. 垃圾收集器分类13.1.3. 评估GC的性能指标吞吐量暂停时间吞吐量 vs 暂停时间 13.2. 不同的垃圾回收器概述13.2.1. 垃圾回收器发展史13.2.2. 7种经典的垃圾收集器13.2.3. 7款经典收集器与垃圾分代之间的关系13.2.4…

前端自动化测试 —— Jest 测试框架应用

目录​​​​​​​ 什么是自动化测试 为什么要用前端自动化测试 前端自动化分类和思想 单元测试 集成测试 TDD 测试驱动开发&#xff08;Test Driven Development&#xff09; BDD 行为驱动开发&#xff08;Behavior Driven Development&#xff09; 如何自己写非框架…

分布式软件架构——SOA架构/微服务架构/无服务架构

SOA架构 Service-Oriented Architecture&#xff0c;面向服务的架构。面向服务的架构是一次具体地、系统性地成功解决分布式服务主要问题的架构模式。了解SOA架构前&#xff0c;先了解三种比较有代表性的服务拆分的架构模式&#xff0c;这些架构模式是SOA演化过程的中间产物&a…

偷偷曝光下国内这些软件外包公司!(2023 最新版)

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 我新建了人工智能中文站https://ai.weoknow.com 每天给大家更新可用的国内可用chatGPT资源 根据网上的资料&#xff0c;整理出来的一份国内软件外包公司的名单。 找工作的同学都要看看&#xff0c;根据自身的情况&#…

杰理AC632N实现custom hid

1. 设备描述符修改 设备描述符主要修改的是PID、VID、设备发现版本号以及字符串描述。 static const u8 sDeviceDescriptor[] { //<Device DescriptorUSB_DT_DEVICE_SIZE, // bLength: Size of descriptorUSB_DT_DEVICE, // bDescriptorType: Device #if defi…

langchain简版教程附案例

简介 LangChain是一个开源的应用开发框架。基于该开源框架&#xff0c;我们可以把大模型与各种工具结合从而实现各种功能&#xff0c;比如基本文档的问答&#xff0c;解析网页内容、查询表格数据等。目前支持Python和TypeScript两种编程语言。当前Python框架支持的模型和功能最…

腾讯云服务器ping不通解决方法(公网IP/安全组/系统多维度)

腾讯云服务器ping不通什么原因&#xff1f;ping不通公网IP地址还是域名&#xff1f;新手站长从云服务器公网IP、安全组、Linux系统和Windows操作系统多方面来详细说明腾讯云服务器ping不通的解决方法&#xff1a; 目录 腾讯云服务器ping不通原因分析及解决方法 安全组ICMP协…

智能计价器-第14届蓝桥杯省赛Scratch中级组真题第5题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第140讲。 智能计价器&#xff0c;本题是2023年5月7日举行的第14届蓝桥杯省赛Scratch图形化编程中级组真题第5题&#…

楼宇租赁管理系统-什么是楼宇租赁系统

楼宇租赁管理系统是一种综合管理平台&#xff0c;它为不同规模楼宇的租赁管理提供了全面的解决方案。楼宇租赁管理系统的主要功能包括租赁管理、财务管理、维修管理、报告管理以及客户服务管理等。让我们逐一介绍每一个功能点。 一、租赁管理 楼宇租赁管理系统通过集成租户信息…

路径规划算法:基于群居蜘蛛优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于群居蜘蛛优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于群居蜘蛛优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

博学谷学习记录】超强总结,用心分享 | 架构师 MySQL调优MVCC学习总结

文章目录 1 概述2 快照读与当前读当前读快照读隔离级别&#xff1a;undo log版本链&#xff1a; 3 Read View3.1 什么是Read View?3.2 实现原理3.3 Read View规则&#xff08;可见性算法&#xff09; 4 MVCC整体流程4.1 可重复读是如何工作的&#xff1f;4.2 读提交是如何工作…

ChatGPT国内镜像,以及如何使用ChatGPT帮你制作PPT

一&#xff1a;前言 ChatGPT&#xff1a;智能AI助你畅聊天地 在现代人日益忙碌的生活中&#xff0c;难免需要一些轻松愉快的聊天来放松身心。而现在&#xff0c;有了 ChatGPT&#xff0c;轻松愉快的聊天变得更加智能、有趣且不受时间、地点限制&#xff01; 什么是 ChatGPT&…