C/C++ 大小端、位域、内存详解

本文深入解析了大小端存储格式、位域(位段)使用及内存对齐原理,揭示了C/C++中数据在内存中的存储方式,对嵌入式底层开发者尤为关键。

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

前言

面试时遇到关于大小端、位段(或者叫位域)和内存对齐的考题,然后就不知所措了。这部分对于嵌入式底层工作者是必须要掌握的,其他方面不是必须的;但还是很有必要学习理解这些知识点,因为它可以让你更了解C++的,了解程序在内存的运行情况,也能加深对计算机系统的理解。

1、大小端

         在现代的“冯.诺依曼体系结构”计算机中,计算机内的数制都是采用二进制来存储,并且是以8位,一个字节为单位,产生内存地址系统。数据在内存中有如下三种存在方式:

           1、从静态存储区分配:此时的内存在程序编译的时候已经分配好,并且在程序的整个运行期间都存在。全局变量,static变量等在此存储。

           2、在栈区分配:在程序的相关代码执行时创建,执行结束时被自动释放。局部变量在此存储。栈内存分配运算内置于处理器的指令集中,效率          高,但容量有限。

            3、在堆区分配:动态分配内存。用new/malloc时开辟,delete/free时释放。变量的生存期由用户指定,灵活,但会有内存泄露等问题。

          一般涉及到大小端问题都是针对的float、int、long等等非一个字节类型的数据类型,像C/C++中的char这样的数据类型,它本身就是占用一个字节的大小,不会产生什么问题。例如 int数据类型,在32位系统中,占4个字节,那这样4个字节存放空间地址是什么样的顺序呢,这就涉及到了大小端的原理了。

          常用的x86结构都是小端模式,而大部分DSP,ARM也是小端模式,不过有些ARM是可以选择大小端模式,KEIL C51是大端的。

        大端:数值的高字节放在内存的低地址处,数值的低字节放到高低址处;就是高位在前。

        小端:数值的低字节放在内存的低地址处,数值的高字节放到高低址处;就是低位在前。

        总结一句话:按内存地址增长的顺序,先放高位就据就是大端,先放低位数据就是小端。

  示例:

        int Height = 0x12345678,&Height = 0x0042ffc4

      小端模式:

   地址0x0042ffc40x0042ffc50x0042ffc60x0042ffc7

数值

0x78

0x56

0x34

0x12

      大端模式:

地址0x0042ffc40x0042ffc50x0042ffc60x0042ffc7
数值

0x12

0x34

0x56

0x78

 

2、位域

       在计算机中,是采用0 ,1表示数据的,每一个0或者1占用1位(bit)存储空间,8位组成一个字节(byte),为计算机中数据类型的最小单位,如char在32bit系统中占用一个字节。但有的时候,我们只需要bool类型的数据量,但C/C++里面没有bool类型的数据,那如何使用bool类型的数据量呢,这就涉及到了位域的概念;并且使用位域(有的叫做位段)可以节省空间。

       具体的语法就是在变量名字后面,加上冒号(:)和指定的存储空间的位数。具体的定义语法如下:

struct A{
    char a:2;
    char b:3;
    char c:2;
    int  d;
};

      A.a = 2;

      A.b = 4;

      A.c = 1;

      A.d = 18;

      sizeof(A) = 8;

      假如 A 的地址为0x0004b80,则

地址                                               0x0004b800x0004b81~ 0x0004b830x0004b84~ 0x0004b87
 7~6c:2b:3a:2 d
数值0132 18

       在这里讲解位域的时候,涉及到了内存对齐或者叫字节对齐的概念,在下面讲解到。

3、内存

       内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址)、访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 。

       具体详细的请看我另外三篇专门讲解字节对齐的博客:

       #Pragma Pack(n)内存分配:https://mp.youkuaiyun.com/postedit/93205993

      C语言 字节对齐问题 详解: https://mp.youkuaiyun.com/postedit/92686850

      #pragma pack(push,1)与#pragma pack(1)的区别:https://mp.youkuaiyun.com/postedit/93206004

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值