【C语言】数据存储篇,内存中的数据存储----C语言整型,浮点数的数据在内存中的存储以及大小端字节序【图文详解】

news2024/11/19 23:39:47

欢迎来CILMY23的博客喔,本篇为​【C语言】数据存储篇,内存中的数据存储----C语言整型,浮点数的数据在内存中的存储以及大小端字节序【图文详解】,感谢观看,支持的可以给个一键三连,点赞关注+收藏。 

 前言

C语言中整型的存储是原码反码补码,那么浮点数的存储又是什么样的呢?本篇将以整型的数据存储开始,带大家了解C语言中数据的存储。

目录

 一、整型的存储

二、大小端字节序

三、练习题

四、浮点数的数据存储


 一、整型的存储

在C语言中,整型数据是以二进制的形式存入内存中的,那在c语言中能对二进制进行操作的有几个操作符,~ ,&,|,^,<<,>>。整数的二进制表示⽅法有三种,即原码、反码和补码,三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位最高位的⼀位是被当做符号位,剩余的都是数值位。

   符号位:

正整数的原码反码补码都相同

例如:4

它的原码,反码,补码都为

00000000 00000000 00000000 00000100

负整数的原码反码补码则表示不一样
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。 

例如以下负四这个例子: 

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

二、大小端字节序

虽然整型数据是按二进制存入内存的,但是在vs的编译器上却采用的是十六进制表示。

例如:

这是整型四的表示,在内存中的地址是 0x00CFFC8C

但是为什么vs的表示是04在前面的呢? 

这就涉及大小端字节序了,大小端字节序分大端字节序和小端字节序,字节序说的就是字节的顺序,当一个字节超过一个数值大小的时候,就有存储的顺序问题。内存中的存储单元是1字节的。

 大端字节序,是指数据的低位字节内容保存在内存的⾼地址处,而数据的高位字节内容,保存在内存的低地址处。

小端字节序,是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。

vs采用的是小端字节序存储

三、练习题

 3.1 如何判断机器的大小端字节序?

 思路一、通过1的二进制来判断,如果位于低地址处的1字节是01,那么是小端字节序,如果位于低地址处的1字节是00.那么是大端字节序。

    int a = 1;
    if (*(char*)&a == 1)
	{
		printf("小端字节序");
	}
	else
	{
		printf("大端字节序");
	}

 图解如下:

 思路一优化:我们可以根据(char*)&a的值进行封装函数,解引用后得到1就是1,得到0就是零,

#include<stdio.h>

int check_sys()
{
	int a = 1;
	return (*(char*)&a);
}

int main()
{
	
	if (check_sys() == 1)
	{
		printf("小端字节序");
	}
	else
	{
		printf("大端字节序");
	}
	return 0;
}

 3.2练习题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;
}

 答案是:

解析: char类型比较特殊,我们没法单纯通过观察判断char类型到底是signed,还是unsigned,而在vs上,它是被认为成signed char的。 

首先char a 的内部是什么样的呢?如下图所示:

b其实也同理可得,其中存放的是八个1,那c也是如此,只是因为没有了符号位,所以这里的三个变量都存了八个1.

%d是以十进制的形式打印有符号整型,所以会对a进行整型提升,也就是将其补充成四个字节的数据

由于b 和a一样都是signed char类型,所以过程也一样

而c不一样,c由于是无符号整型

因此打印的时候是-1,-1,255

 3.3练习题2

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

%u打印无符号整数 

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

  答案如下:

补充:

char类型的取值范围,char一个字节对应八个比特位,而这八个比特位的取值又如下 所示,所以有符号的char类型取值是-128-127.

所以a当中存储的是

00000000000000000000000010000000----补码

11111111111111111111111110000000----原码

故答案为4294967168

3.4练习题3


#include<stdio.h>

int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
    {
	  a[i] = -1 - i;
	}

	printf("%d", strlen(a));
	return 0;
 }

 根据前面所说,其实signed类型是在兜圈子

 所以这里只要确定0的位置即可,a当中从-1开始存,存够255之后又开始新的轮回

 3.5练习题5

#include<stdio.h>

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

结果是死循环 

解析:

无符号char取值是0~255,所以会无限制的打印

3.5练习题4 

#include <stdio.h>

int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}

	return 0;
}

解析:

i的数据类型是unsigned int ,是恒大于等于0的,而循环的条件是i>=0,恒成立,所以会不限制的答应i的值。会从9一直开始打印,然后进入2^ 0~2^32-1. 0~4294967295

3.6练习题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;
}

结果如下:

解析:

a是数组名,单独放在&后面,取出的是整个数组的地址,+1跳过整个数组的大小,(不理解的可以看http://t.csdnimg.cn/BlJ00)指向末尾,将其存入ptr1, ptr[-1] == *(ptr-1),将其解引用后得到的就是4。

因为数据在vs上看是小端存放,本身转换成int类型后,就是a本身的地址直接加1,然后将其转换成int*类型是四个字节,解引用后,读取要反过来,所以是20 00 00 00

四、浮点数的数据存储

常⻅的浮点数:3.14159、1E10等,浮点数家族包括:  float、double、long double 类型。

看一个例子:

#include <stdio.h>

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

结果如下:

那为什么会这样呢?

这就涉及浮点数的存储了。

假设

V = 5.625 

V = 101 .101 -----二进制

V = 1.011 * 2 ^2

V = (-1) ^ 0 * 1.011 * 2^2 

 其实就是先转换成二进制,然后将二进制小数点向左移动一位的同时E+1,最后将二进制化成大于等于1小于2的数。

 那根据这样的化简,我们有两种存储方式

对于32位的浮点数,最高的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M

对于64位的浮点数,最高的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

 因为最终M都会化简成1...多少的形式,所以我们只需要在内存中存储有小数点的位置即可。

我们接着看是如何存和取的:

我们存入的时候将其转换成二进制,

所以我们就可以解释第一个练习了:

 9以整型的形式存储在内存中,得到如下二进制序列:

0000 0000 0000 0000 0000 0000 0000 1001

首先,将9的二进制序列按照浮点数的形式拆分,得到第⼀位符号位s=0,后面8位的指数 E=00000000 ,
最后23位的有效数字M=000 0000 0000 0000 0000 1001。
由于指数E全为0,因此,浮点数V就写成:
    V=(-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146) 显然,V是⼀个很小的接近于0的正数,所以用十进制小数表⽰就是0.000000。

浮点数9.0,为什么整数打印是 1091567616
首先,浮点数9.0等于二进制的1001.0,即换算成科学计数法是:1.001×2^3
所以:9.0   =   (−1) ^0 * (1.001)*2^3,
那么,第⼀位的符号位S=0,有效数字M等于001后面再加20个0,凑满23位,指数E等于3+127=130, 即10000010
所以,写成二进制形式,应该是S+E+M,即

0 10000010 001 0000 0000 0000 0000 0000 

这个32位的⼆进制数,被当做整数来解析的时候,就是整数在内存中的补码,原码正是
1091567616

感谢各位同伴的支持,本期数据存储篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。 

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

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

相关文章

Android Activity启动模式

文章目录 Android Activity启动模式概述四种启动模式Intent标记二者区别 Android Activity启动模式 概述 Activity 的管理方式是任务栈。栈是先进后出的结构。 四种启动模式 启动模式说明适用场景standard标准模式默认模式&#xff0c;每次启动Activity都会创建一个新的Act…

Qt CMake 国际化相关配置

文章目录 本来用qmake使用pro文件很简单的一件事&#xff0c;结果用cmake折腾了半天。 何必呢~ 参考&#xff1a;QT6.3 CMake 多语言切换 这是我的 cmake_minimum_required(VERSION 3.16)project(testQml3_6 VERSION 0.1 LANGUAGES CXX)set(CMAKE_AUTOMOC ON) set(CMAKE_CXX…

MySQL 篇-深入了解 DML、DQL 语言(二)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 DML、DQL 语言说明 2.0 使用 DML 实现对数据管理和操作 2.1 DML - 增添数据 insert 2.2 DML - 修改数据 update 2.3 DML - 删除数据 delete 3.0 使用 DQL 实现对…

docker 容器修改端口和目录映射

一、容器修改端口映射 一般在运行容器时&#xff0c;我们都会通过参数 -p&#xff08;使用大写的-P参数则会随机选择宿主机的一个端口进行映射&#xff09;来指定宿主机和容器端口的映射&#xff0c;例如 docker run -it -d --name [container-name] -p 8088:80 [image-name]…

【EFK】基于K8S构建EFK+logstash+kafka日志平台

基于K8S构建EFKlogstashkafka日志平台 一、常见日志收集方案1.1、EFK1.2、ELK Stack1.3、ELK filbeat1.4、其他方案 二、EFK组件介绍2.1、Elasticsearch组件2.2、Filebeat组件【1】 Filebeat和beat关系【2】Filebeat是什么【3】Filebeat工作原理【4】传输方案 2.3、Logstash组件…

麒麟银河操作系统V10部署ffmpeg

麒麟银河操作系统V10部署ffmpeg 部署ffmpeg用来处理视频的各种操作 想使用ffmpeg&#xff0c;要先安装nasm&#xff0c;yasm&#xff0c;x264之后&#xff0c;否则会报错 nkvers 查看麒麟操作系统版本 cat /proc/version #查看linux版本信息 uname -a #查看linux版本和内核…

高分影像RPC校正工具使用步骤

高分影像准备 注意事项&#xff1a; 直接使用解压包&#xff0c;外部高分文件夹也要留存 文件夹内部不要有动作&#xff0c;就解压后的原始这些文件 最好不要有中文路径 xml中参数路径 入参包含三个&#xff0c;影像TIFF、影像RPB&#xff08;解压后自带&#xff09;、DEM&am…

电容元件及其特性

电容元件 电容器&#xff1a;由两块金属导体极板&#xff0c;中间间隔以不同的物质(如云母、绝缘纸、空气等)组成。 当在两极板之间加上电压后&#xff0c;两极板上分别聚集等量的正、负电荷&#xff0c;并在介质中建立电场且具有电场能量。 将电源移开后&#xff0c;电荷继续…

Java面向对象之接口和抽象类的区别一目了然

介绍 相信对于Java面向对象部分&#xff0c;很多人很长一段时间对于接口和抽象类的区别&#xff0c;使用场景都不是很熟悉&#xff0c;同是作为抽象层重要的对象&#xff0c;工作中到底什么情况下使用抽象类&#xff0c;不是很清楚。本文就一次性把这些概念一次性说清楚&#x…

Linux下性能分析的可视化图表工具

1 sar 和sadf 1.1 简介 sar命令可以记录系统下的常见活动信息&#xff0c;例如CPU使用率、网络统计数据、Block I/O数据、内存使用情况 等。 sar命令的“-o [file_name]”参数可以将系统活动数据记录到file_name文件&#xff0c;然后通过sadf来解析&#xff0c;sadf命令的“-g…

欢迎参与2024年 OpenTiny 开源项目用户调研

&#x1f389; 欢迎参与 OpenTiny 开源项目的用户调研 &#x1f389; &#x1f4e3; 调研背景 随着 OpenTiny 开源项目的不断发展&#xff0c;我们一直致力于为开发者提供高质量的 Web 前端开发解决方案。为了更好地满足用户需求&#xff0c;提升项目的实用性和易用性&#x…

CV及LLM常见名词解释

CV及LLM常见名词解释 看论文的时候&#xff0c;有些术语虽然常见但是却让人很难理解具体含义&#xff0c;如noise等&#xff0c;这里是一些常见术语的解释&#xff0c;同时也给出了这些术语所在的上下文及模型 例1&#xff1a;Stable Diffusion的文生图模块 Embedding&#…

IDEA开发环境热部署

开发环境热部署 在实际的项目开发调试过程中会频繁地修改后台类文件&#xff0c;导致需要重新编译重新启动&#xff0c;整个过程非常麻烦&#xff0c;影响开发效率。Spring Boot提供了spring-boot-devtools组件&#xff0c;使得无须手动重启SpringBoot应用即可重新编译、启动项…

亿道信息新品EM-T195轻薄型工业平板,隆重登场!

EM-T195是一款轻巧但坚固的平板电脑&#xff0c;仅 650克重、10.5mm毫米厚&#xff0c;即使没有额外的便携配件进行辅助&#xff0c;您也可以轻松将其长时间随身携带。耐用性外壳完全密封&#xff0c;防尘防潮&#xff1b;出色的坚固性和可靠性&#xff0c;使T195天生适合在苛刻…

Delegate(P29 5.5delegate)

一、Delegate简介 每个代理都可以访问许多附加的属性&#xff0c;其中一些来自数据模型&#xff0c;另一些来自视图。 从模型中&#xff08;Model&#xff09;&#xff1a;属性将每个项目的数据传递给 delegate。 从视图中&#xff08;View&#xff09;&#xff1a;属性将状…

Unity(第九部)物体类

拿到物体的某些数据 using System.Collections; using System.Collections.Generic; using UnityEngine;public class game : MonoBehaviour {// Start is called before the first frame updatevoid Start(){//拿到当前脚本所挂载的游戏物体//GameObject go this.gameObject;…

golang使用gorm操作mysql1

1.mysql连接配置 package daoimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger" )var DB *gorm.DB// 连接数据库&#xff0c;启动服务的时候&#xff0c;init方法就会执行 func init() {username : "roo…

Sentinel实战(待完善)

目录 服务雪崩 什么是服务雪崩 服务不可用原因 解决方案 技术选型对比 Sentinel 介绍 优点 核心概念 资源 规则 代码实战 API实现 SentinelResource注解埋点实现 服务雪崩 什么是服务雪崩 在服务调用链路中, 服务提供者不可用, 导致服务调用者不可用, 间接让上上游…

【推荐算法系列十六】:协同过滤

文章目录 参考原理基于邻域的协同过滤算法基于用户的协同过滤&#xff08;User-Based Collaborative Filtering&#xff09;基于内容的协同过滤 基于模型的协同过滤算法 扩展优缺点 参考 推荐系统之神经协同过滤 原理 基于邻域的协同过滤算法 基于邻域的协同过滤算法又包括…

「QALog」校招测试八股—计网篇(一)

哈喽大家好&#xff0c;我是chowley&#xff0c;QALog创始人&#xff0c;测试开发工程师 这次的测试八股系列专栏由我来主写&#xff0c;给大家带来亿点点硬货&#xff0c;今天是计网系列的第一篇&#xff0c;我总结了市面上主流的测试核心八股&#xff0c;废话少说直接开整&a…