数据在内存里的存储(1)【整数在内存中的存储】【什么是大小端】

news2024/12/27 15:52:54

一.整数在内存里的存储

我们都知道,关于整数的二进制表示方法有三种,原码,反码和补码。而正数的原码,反码,补码都相等。而负数的表示方法各不相同。原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。反码:除了负数的符号位不变,其他位都取反就行。补码:反码加一就是补码。

对于整型来说,数据存放内存中其实存放的是补码。为什么用补码来存放呢?

原因在于,使用补码可以将符号位和数值域统一处理。同时,加法和减法也可以统一处理(CPU只有加法器),此外补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

二.大小端字节序和字节序判断

1.什么是大小端?

在超过一个字节的数据在内存中存储的时候,就会出现存储顺序的问题。按照顺序,我们就会有大端字节序存储和小端字节序存储。

这里可以看到,我给a的值是0x11223344。但是在内存中这个方向就完全反了过来。变成了44332211。这个就是我们说的小端字节存储。

小端字节序存储:把一个数据的低位字节的内容存储到低地址处,而高字节的的内容存储到高字节处。

大端字节存储:把一个数据的高位字节的内容存储到低地址处,而低字节的的内容存储到高字节处。

大小端存储跟计算机架构有关。我用的是vs2022,用的是小端存储。这就是大小端存储的基本知识。

2.为什么会有大小端?

因为在计算机系统中,我们是以字节为单位的,每个内存单元都对应着一个字节,而一个字节对应八个bit位,但是在c语言中除了八个bit位的char外,还有16位的short,32位的int(具体要看编译器)。另外,对于位数大于8位的处理器,例如16位和32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个将多个字节安排的问题。因此有了大小端存储。(x86结果是小端模式,而KEIL  C51为大端模式。很多的ARM,DSP都为小端模式。但有些ARM处理器还可以由硬件来选择大端还是小端)

三.一些练习

1.练习1

设计一个代码来判断当前机器的字节序

#include<stdio.h>
int main()
{
	int a = 1;
	if (*(char*)&a == 1)//注意这里我们是把a的地址给强制转化成char*,解引用的时候其实就访问一个字节
		                //大端存储就是0,小端存储就是1
		printf("小端\n");
	else
		printf("大端");
	return 0;
}

这里我的是小端存储,打印出来的也成功是小端。

2.练习2

不仅是大小端,关于数据的存储也有一些练习,大家来了解一下。

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

可以思考一下这三个值等于多少。

我们知道关于负数在内存中的存储是补码。注意:单独的一个char  到底是有符号还是无符号是取决于编译器的,这里我用的vs2022是是有符号的。先来看最后打印的是整型。那么这里的a,b,c是要整形提升的。(无符号补0,有符号补1)

#include<stdio.h>
int main()
{
	char a = -1;
	//1000000000000000000000000000001   -1的原码
	//1111111111111111111111111111110   -1的反码
	//1111111111111111111111111111111   -1的补码
	//因为是char类型,所以咱们就只要11111111
	//这里要整形提升,所以是1111111111111111111111111111111,按照步骤,求出原码就是-1
	signed char b = -1;
	//11111111也是-1
	//跟a的步骤一样
	unsigned char c = -1;
	//11111111也是-1
	//这个是无符号整形提升后是00000000000000000000000011111111
	//这个就是255
	printf("a=%d  b=%d  c=%d", a, b, c);
	//        -1    -1   255
	return 0;
}

取值范围:无符号的是0~255。有符号的是-128~127。

3.练习3

再来看一个代码

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

来看解析

#include <stdio.h>
int main()
{
	char a = -128;
	//原码:100000000000000000000000010000000
	//反码:111111111111111111111111101111111
	//补码: 111111111111111111111111110000000
	//因为是char类型,所以只有10000000-a
	printf("%u", a);
	//这里是用%u来打印,所以要整型提升
	//11111111111111111111111111111110000000
	//因为是无符号数,所以就不会存在什么原码反码和补码,直接把这个东西转化成十进制数就是答案
	//是一个很大的数字
	return 0;
}

输出:4294967168

那我把-128换成128来弄,大家来想一下是什么结果呢?

4.练习4

这个代码就很有意思了。

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

来看个图

当我们从0开始一直加,加到127的时候,已经到了最大数的限制。这时再去加一直接就变成了-127,等加到-1,又开始了一次循环。当然这是有符号的char类型。

那么像是这个题我们就好求了。strlen找的是'\0'之前的元素个数。

所以a[i]就是-1 -2 -3 ...-127  -128 127  126...4 3 2 1 0 -1...

看看有几个元素就行了。

5.练习5

前面的太简单了,上点强度。

#include <stdio.h>
int main()
{
	int a[4] = { 1,2,3,4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}

来看解析

#include <stdio.h>
int main()
{
	int a[4] = { 1,2,3,4 };
	int* ptr1 = (int*)(&a + 1);
	//&a的类型是int(*)[4]是一个数组指针,所以前面有一个强制转换。
	//这里有+1跳过的是整个数组,ptr1[-1]的意思就是*(ptr1-1),往后移动一个sizeof(int)的距离,结果就是4.
	int* ptr2 = (int*)((int)a + 1);
	//这里我直接是把a强制转换成int类型了,现在的a就是个整数,整数加一,那就是加一
	//比如像是这里的a在内存中的存储:01 00 00 00   02 00 00 00   03 00 00 00   04 00 00 00 
	//整数a加一,跳过了一个字节,本来位置在01的a,现在位置在00了
	//而现在又强转成了int*类型,一次访问4个字节,所以真正访问的是00 00 00 02
	//我用的是小端存储,所以真正打印出来的就是02000000
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}

最终打印:4,2000000

当然在内存中肯定不止整数的存储,当然还有小数。下篇博客我来介绍一下小数在内存中的存储。感谢大家的观看,如有错误,请大家多多指正。

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

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

相关文章

【Unity】uDD插件抓屏文字显示不清晰怎么办?

【背景】 之前介绍过用一款简称uDD&#xff08;uDesktopDuplication&#xff09;的开源插件抓取电脑桌面。整体效果不错&#xff0c;看电影很流畅。但是当切换到文档&#xff0c;或者仔细看任何UI的文字部分时&#xff0c;发现就模糊了。 【分析】 由于是依托于Canvas上的Te…

备考的秘密武器:一招清除笔迹,试卷、表格再利用!

擦除试卷笔迹的功能可以用于多种场合&#xff0c;尤其适用于教育领域和文档管理工作。以下是一些具体的应用场景&#xff1a; 教学复习&#xff1a;教师可以使用这个功能来清除已批改的试卷上的笔迹&#xff0c;以便重复使用试卷进行讲解或作为模板设计新的题目。 资料归档&a…

Linux中ifconfig无法查看ip解决

安装net-tool插件 sudo yum install net-tools

VUE中添加视频播放功能

转载https://www.cnblogs.com/gg-qq/p/10782848.html 常见错误 vue-video-player下载后‘vue-video-player/src/custom-theme.css‘找不到 解决方法 卸载原来的video-play版本 降低原来的版本 方法一 npm install vue-video-player5.0.1 --save 方法二 或者是在pack.json中直…

力扣刷题Days25-45. 跳跃游戏 II(js)

目录 1&#xff0c;题目 2&#xff0c;代码 贪心算法正向查找 3&#xff0c;学习 解题思路 具体代码处理 数组遍历的最后边界的处理&#xff1a; 1&#xff0c;题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向…

华为ensp中vrrp虚拟路由器冗余协议 原理及配置命令

CSDN 成就一亿技术人&#xff01; 作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; CSDN 成就一亿技术人&#xff01; ————前言————— VRRP&#xff08;Virtual Router Redundancy Protocol&#xff0c;虚拟路由器冗余协议&#xff0…

八大排序算法之希尔排序

希尔排序是插入排序的进阶版本&#xff0c;他多次调用插入排序&#xff0c;在插入排序上进行了改造&#xff0c;使其处理无序的数据时候更快 核心思想&#xff1a;1.分组 2.直接插入排序&#xff1a;越有序越快 算法思想&#xff1a; 间隔式分组&#xff0c;利用直接插入排序…

HTML 常用标签总结

本篇文章总结了一些我在学习html时所记录的标签&#xff0c;虽然总结并不是非常全面&#xff0c;但都是一些比较常用的。 html元素标签 首先一个html界面是由无数个元素标签组成的&#xff0c;每个元素具有它的属性 1.input 单行文本框 标签type属性——text <input ty…

【windows】安装 Tomcat 及配置环境变量

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

视频号小店如何开店,个人可以做吗?完整版开店教程分享

大家好&#xff0c;我是电商花花。 视频号小店现在成了新的电商创业新渠道&#xff0c;这两年视频号也迎来了大爆发&#xff0c;很多朋友也都靠着视频号、视频号小店赚到了人生第一桶金&#xff0c;让很多没有接触过视频号的朋友直流口水。 那视频号小店赚钱吗&#xff1f;个人…

OpenLayers基础教程——WebGLPoints图层样式的设置方法

1、前言 前一篇博客介绍了如何在OpenLayers中使用WebGLPoints加载海量数据点的方法&#xff0c;这篇博客就来介绍一下WebGLPoints图层的样式设置问题。 2、样式运算符 在VectorLayer图层中&#xff0c;我们只需要创建一个ol.style.Style对象即可&#xff0c;WebGLPoints则不…

研华工控机610L学习笔记2:visualstudio与第一个C#程序

今日继续学习工控机 C# 编程相关知识&#xff1a; 这篇结束后我将先进行一段时间的C#的学习研究&#xff0c;并写一些C#的笔记 后续再更新工控机编程设计相关 目录 1、安装visualstudio&#xff1a; 2、创建第一个C#程序&#xff1a; 3、寻找C#解决方案源文件&#xff1a; …

《深入浅出LLM 》(二):大模型基础知识

&#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料&#xff0c;配有全面而有深度的专栏内容&#xff0c;包括不限于 前沿论文解读、…

DM-达梦数据库实时主备搭建

dm实时主备说明 将主库产生的 Redo日志传输到备库&#xff0c;备库接收并重演Redo日志&#xff0c;从而实现备库与主库的数据同步。 一、环境准备 1.1、配置环境准备 首先搭建实时主备&#xff0c;要规划好机器的&#xff0c;我准备两台机器服务器 主服务器 mast…

小目标检测篇 | YOLOv8改进之增加小目标检测层(针对Neck网络为AFPN)

前言:Hello大家好,我是小哥谈。小目标检测是计算机视觉领域中的一个研究方向,旨在从图像或视频中准确地检测和定位尺寸较小的目标物体。相比于常规目标检测任务,小目标检测更具挑战性,因为小目标通常具有低分辨率、低对比度和模糊等特点,容易被背景干扰或遮挡。本篇文章就…

【C语言】tcp_sendmsg_locked

一、讲解 tcp_sendmsg_locked 函数是 Linux 内核中实现 TCP 数据发送的一个核心函数。这个函数被调用来将用户空间的数据通过 TCP 发送出去。以下是该函数的基本工作流程的中文解释&#xff1a; 1. 函数初始化和检查&#xff1a; - 它首先检查是否使用了 TCP 零拷贝发送&am…

【webpack】----错误解决【Cannot read properties of undefined (reading ‘tap‘)】

1. 报错场景 安装 webpack-obfuscator 后&#xff0c;进行 js 代码混淆编译的时候报错。 2. 报错截图 3. 错误原因 通常是由于版本不兼容或配置错误引起的。 4. 查询本地 webpack 版本 4.1 查询命令 npm 查询 npm view webpack versionyarn 查询 yarn info webpack ver…

Java学习笔记 | Java基础语法 | 03 | 流程控制语句

文章目录 0 前言1.流程控制语句1.1 流程控制语句分类1.2 顺序结构 2.判断语句2.1 if语句1. if语句格式1练习1&#xff1a;老丈人选女婿练习2&#xff1a;考试奖励 2. if语句格式2练习1&#xff1a;吃饭练习2&#xff1a;影院选座 3. if语句格式3练习1&#xff1a;考试奖励 2.2 …

C语言字节对齐关键字__attribute__((aligned(n)))的使用

0 前言 在进行嵌入式开发的过程中&#xff0c;我们经常会见到对齐操作。这些对齐操作有些是为了便于实现指针操作&#xff0c;有些是为了加速对内存的访问。因此&#xff0c;学习如何使用对齐关键字是对于嵌入式开发是很有必要的。 1 对齐规则 1.0 什么叫做对齐 众所周知&a…

实现登录拦截功能

1.4、实现登录拦截功能 温馨小贴士&#xff1a;tomcat的运行原理 当用户发起请求时&#xff0c;会访问我们像tomcat注册的端口&#xff0c;任何程序想要运行&#xff0c;都需要有一个线程对当前端口号进行监听&#xff0c;tomcat也不例外&#xff0c;当监听线程知道用户想要和…