C语言进阶——深度解析数据的存储-2

本文深入探讨C语言中整型数据在内存中的存储方式,包括原码、反码、补码的概念及转换,以及大小端存储模式的理解。通过实例解释了补码的优势,并提供了判断机器大小端的编程练习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

🎸
作者:爱弹吉他的小奔同学
🎸
专栏:《C语言》
🎸
仓库:gitee(所有的代码都在这个仓库里面)
🎸
如果感觉学累了,那么就看一个视频放松一下吧,猜猜点进去你会看到什么😜(视频)
🎸
我向往以后悠闲的生活,但现在的我们正处于需要努力的年华

在这里插入图片描述
点赞收藏关注啦啦啦啦啦

整形在内存中的存储

原码、反码、补码

对于原码、反码、补码之间的转换就不多说了

int a = 20;
int b = -10;

20是正数
原码:0000 0000 0000 0000 0000 0001 0100
反码:0000 0000 0000 0000 0000 0001 0100
补码:0000 0000 0000 0000 0000 0001 0100

-10是负数
原码:1000 0000 0000 0000 0000 0000 1010
反码:1111 1111 1111 1111 1111 1111 0101
补码:1111 1111 1111 1111 1111 1111 0110

因为过于麻烦,所以我们写成十六进制

20
原码:0x00 00 00 14
反码:0x00 00 00 14
补码:0x00 00 00 14

-10
原码:0x80 00 00 0a
反码:0x80 00 00 0a
补码:0xff ff ff f6

在这里插入图片描述

通过内存显示,对于整型,在内存中是以补码的二进制序列储存的,20储存0x00 00 00 14,-10储存0xff ff ff f6

为什么要使用补码呢?
原码按位取反+1——>补码
补码按位取反+1——>原码

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

举一个例子:
5 - 10 = -5

5是0x00 00 00 05
-10是0xff ff ff f6

相加得0xff ff ff fb,取反+1得原码0x80 00 00 05,对应的数是-5,加法和减法都可以统一这样处理,所以我们使用补码

大小端介绍

我们可以看到对于a和b分别存储的是补码。但是我们发现顺序有点不对劲。
这是又为什么?先了解一下大小端的概念

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中;
难以理解就看接下来的图

我们来探究一下对于0x11 22 33 44(补码)这个数据在内存中储存的形式是什么

我们以字节为单位来讨论数据储存于内存中的形式

请添加图片描述

小端字节序存储
请添加图片描述

大端字节序存储
请添加图片描述

在vs2019编译器里,它的储存形式是这样的
在这里插入图片描述

是颠倒的,实际上就是数据的低位保存在内存的低地址,数据的高位保存在内存的高地址中,这叫小端字节序存储

那么相反,数据的低位保存在内存的高地址,数据的高位保存在内存的低地址中,这叫大端字节序存储

注意:
对于一个字节大小的类型,比如char,它的存储是没有顺序可言的,因为有顺序的最低也要两个及其以上字节大小的类型
就比如short,int等,这些都是有顺序的

那么什么时候是以大端存储的?什么时候是以小端存储的?
这跟硬件有关,也就是跟电脑有关,跟编译器没有什么关系

写个程序来判断当前机器是大端还是小端?

#include<stdio.h>
//函数一
int judge_if_endian()
{
	int a = 1;
	char* p = (char*)&a;

	*p = 0;//改变a的低地址放的数据为00
	//如果大端——00 00 00 01,则仍为00 00 00 01
	//如果小端——01 00 00 00,则变为00 00 00 00

	//判断a是否被改变
	if (a == 1)
		return 0;
	else if (a == 0)
		return 1;
}

//函数二
int judge_if_endian()
{
    int i = 1;
    return (*(char *)&i);
    //看看首地址是01还是00
    //01则是小端,00则是大端
}


int main()
{
	int a = judge_if_endian();
	//返回0则为大端,返回1则为小端
	
	if (a == 0)
		printf("该电脑是大端字节序存储");
	else if(a == 1)
		printf("该电脑是小端字节序存储");

	return 0;
}

配套练习

请添加图片描述

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小奔同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值