目录摘要一现象及例题1现象2例题二大小端概念1概念2读取大小端3大小端对数组存储的影响三验证大小端的两种方式1验证的思路2整形验证3联合体验证摘要本文旨在彻底理解大小端模式的含义并且讲解两种验证大小端模式的方法~一现象及例题1现象#include stdio.h int main() { int a 0x11223344; return 0; }调试以一行四列和一行一列查看a解释①int a 0x11223344 的32位二进制是00010001 00100010 00110011 01000100其中的44(01000100)叫做32位中的低位字节11(00010001)叫做32位中的高位字节很好理解比如十进制的123其中1是百位所以是高位3是个位所以是低位③而此时在内存中存储的现象是在7C7D7E7F这样地址呈递增的内存空间中分别存储的44,33,22,11也就是低位字节44存储在低地址处7C高位字节11存储在高地址处7F低位字节存储在低地址处高位字节存储在高地址处2例题#include stdio.h // x86 int main() { int a[4] { 1, 2, 3, 4 }; int* ptr (int*)((int)a 1); printf(%x, *ptr); return 0; }解释①a为数组名其代表数组首元素的地址也就是整形1的地址此时被强转为int整形也就是指针变量被强转为了整形int值然后进行1代表进行的就是整形值1(如果100就变成101)随后再被强转为int*整形指针类型此时解引用求*ptr②经过这一系列操作其实就是把指针指向的位置往后移动了一个字节然后int*指针进行解引用代表求往后的4个字节的值等同于求元素1的第2个字节开始往后的4个字节如图②因为环境未变所以此时在内存中的存储特点仍然是低位字节存储在低地址处高位字节存储在高地址处所以此时的00000002若按照高位到低位的表达方式应该为20000000注意02整体是1个字节所以内部没有高位低位之分~③所以%x打印*ptr的值 就是16进制打印0x02000000所以值就为2000000(7位)④当然4个字节应该对应8个16进制位这里的2000000只有7个16进制位是因为%x会把最前面的0省略了如果以%p形式打印则不会省略二大小端概念1概念其实超过⼀个字节的数据在内存中存储的时候就有存储顺序的问题按照不同的存储顺序我们分为大端字节序存储和小端字节序存储下⾯是具体的概念大端存储模式是指数据的低位字节内容保存在内存的高地址处而数据的高位字节内容保存在内存的低地址处。小端存储模式是指数据的低位字节内容保存在内存的低地址处而数据的高位字节内容保存在内存的高地址处。注不管大端小端内存是按字节编址的一个字节内部不再高位低位所以在上述的调试现象和例题中都是低位字节存储在低地址处高位字节存储在高地址处故博主的环境就是小端模式反之就是大端存储2读取大小端❓️在初次学习大小端的时候会有一个常见的误区那就是一个整形分别在大端和小端的模式下存储的顺序不同此时进行读取会不会值不同呢不管大端小端读取的值都是一样的这就是为什么我们不管环境是大端小端创建的变量值是多少读取打印的值就是多少~整形1在大端和小端下的存储❓️会不会大端下读取到的1的补码为00000000 00000000 00000000 00000001而小端下读取到的补码为00000001 00000000 00000000 00000000这样打印结果前者为1后者为16777216当然不会CPU会抹去大小端下存储机制的差异化让我们读取到的值都一样CPU会把内存中的字节重新组合成正确的数值所以无论大端还是小端读取到的补码都是00000001 00000000 00000000 00000000。大端和小端的差异只存在于内存存储层面CPU 读取后都会转换成统一的二进制格式(高位在左)所以数值永远一样。而上文中的例题中的图为❓️此时可能会不理解为什么读取到的不是0x00000002此时按地址从低到高排列00 00 00 02CPU会将其恢复为高位在左低位在右也就是02000000这才是这四个字节所存储的值所以%x打印为2000000~3大小端对数组存储的影响需要注意的一点是在一个数组内大小端只会让单个元素内部字节存储顺序不同而数组整体的线性地址递增顺序完全不受大小端影响。下标越大地址一定越高。并且不会出现一个整形数组{1,2,3,4}在不同端下会存储为{4,3,2,1}的情况这是极大的误解三验证大小端的两种方式1验证的思路面试中验证大小端是一个常见的问题我将介绍两种方式验证大小端~首先需要知道一个char*指针去取地址的时候在大小端取到的地址虽然相同但是该字节的内容不相同比如❓️CPU不是会抹去大小端下存储机制的差异化让我们读取到的值都一样吗所以这里两个char*对应的空间存储的值为什么不同在大端和小端中一个字节的内容存储在一个地址处这是恒定的所谓的组合顺序也不会改变每个地址中的存储的内容此外须知CPU 只在读取才做组合成正确数值这一操作而且CPU做这件事也不会影响到大端小端的存储特点所以验证大小端的思路就是我们利用整形1整形1只有低位的那一个字节为1其余3字节都是0所以如果我们单独利用char*取出整形存储在低地址处的那一个字节如果*解引用验证为1代表为小端反之为0则大端2整形验证#include stdio.h int check_sys() { int i 1; return (*(char*)i); } int main() { int ret check_sys(); if (ret 1) { printf(小端\n); } else { printf(大端\n); } return 0; }解释对整形i进行取地址此时取到的就是整形i的起始地址也就是存储在低地址处的那个字节的地址然后进行强转char*在*解引用得到了该字节的值为1则小端反之大端3联合体验证#include stdio.h int check_sys() { union { int i; char c; }un; un.i 1; return un.c; } int main() { int ret check_sys(); if (ret 1) { printf(小端\n); } else { printf(大端\n); } return 0; }解释①联合体的成员变量占据同一块内存所以读取char就是读取int的第一个字节。小端下整形该字节是1大端下整形该字节是0由此判断字节序。②所以需要把成员变量i置为1再用c的值去判断 [ 作者 ] shylyly [ 首次发布 ] 2026.5.16❌ [ 最新修改 ] 2026.10.17 [ 声明 ] 由于笔者水平有限文中难免有疏漏或不妥之处还望读者不吝赐教。