判断大小端模式

判断大小端模式

       学C语言时,了解过大小端模式,但是一直都每怎么理解,对于网上查到的各种判断大小端的程序也是看的一知半解。最近再次看到大小端这个问题时,终于感觉顿悟了。以下是我的理解,如有错的地方请指出。

       大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。

       小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。


       因为在计算机系统中,数据存储是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8位。我们知道在C语言中,很多数据类型是超过8位的,short型、long型。。。这就涉及到数据存储在内存中的排列顺序。如short型的整数4386,表示为16进制是0x1122(0x代表数字为16进制),再表示为二进制数是  0001 0001 0010 0010 (short占2个字节,所以共占16位)。这个整数在内存中的存储可能会有两种方式:

               低地址                高地址
               1字节                 1字节
               占8位                 占8位
       大端模式          0001  0001            0010  0010
       小端模式          0010  0010            0001  0001

确定高低字节:

                          4386
                        0x1122
     0001  0001     0010  0010
         高字节         低字节

以下程序可判断存储模式是大端还是小端:

#include<stdio.h>
void byteorder()
{
	union
	{
		short value;
		char union_bytes[sizeof(short)];
	}test;  //联合体内成员共用地址空间
	test.value = 4386; //或0x1122
	if((test.union_bytes[0]==0x11)&&(test.union_bytes[1]==0x22))
	{
		printf("big endian\n");
	}
	else if((test.union_bytes[0]==0x22)&&(test.union_bytes[1]==0x11))
	{
		printf("little endian\n");
	}
	else
	{
		printf("unknown...\n");
	}
	//查看各地址单元的数据存储情况
	printf("size_short = %d   size_char = %d\n",sizeof(short),sizeof(char));
	printf("&    = %X\n",&(test.value)); //所输整数的首地址
	printf("&[0] = %X   value = %d\n",&test.union_bytes[0],test.union_bytes[0]);
	printf("&[1] = %X   value = %d\n",&test.union_bytes[1],test.union_bytes[1]);
}
int main()
{
	byteorder();
	return 0;
}
输出:

          解释这个程序,输出表示的是:这是小端模式,short型占用2个字节,char型占用1个字节,short型整数4386的首地址是CB9DBB10,union_bytes[0]的地址是CB9DBB10,该地址单元存储的是 00100010=34,union_bytes[1]的地址是CB9DBB11,该地址单元存储的是 00010001=17。

          程序中,因为联合体union成员共享地址空间,而我们要观察整数在各个地址单元的存储情况,char型正好占1个字节,对应一个地址单元,所有用short型和char型数组作为同一个联合体成员。根据输出,分析如下:

      CB9DBB11                       0001 0001                   0x11             17
      CB9DBB10                       0010 0010                   0x22             34
           地址            地址单元存储的二进制数据            对应的16进制      对应的10进制

可知低地址存的是低字节,高地址存的是高字节,所以为小端模式。




判断系统大小端有多种方法,以下是几种常见的实现方式: #### 方法一:通过指针访问整数的第一个字节 ```c #include <stdio.h> int main() { unsigned int x = 0x12345678; char *c = (char *)&x; if (*c == 0x78) { printf("Little"); } else { printf("Big"); } printf("%x\r\n", *c); return 0; } ``` 这种方法的原理是将一个无符号整数 `x` 的地址强制转换为 `char` 类型的指针,由于 `char` 类型指针每次只能访问一个字节,所以通过判断第一个字节的值是 `0x78`(小端模式下低字节在前)还是 `0x12`(大端模式下高字节在前)来确定系统的大小端模式 [^1]。 #### 方法二:使用位移操作 ```cpp #include <iostream> int main() { int i = 1; if ((i >> 32) == 0) { std::cout << "小端模式" << std::endl; } else { std::cout << "大端模式" << std::endl; } return 0; } ``` 此方法通过将整数 `1` 右移 32 位,根据结果判断系统大小端。不过该代码存在错误,因为在 32 位或 64 位系统中,`int` 类型通常为 32 位,右移 32 位会导致未定义行为。正确的做法可能是通过检查 `i` 的低字节来判断 [^2]。 #### 方法三:使用字符数组 ```c #include <stdio.h> int main() { char a[4] = { 0, 0, 0, 1 }; if (*(int*)a == 1) { printf("大端\n"); } else { printf("小端\n"); } return 0; } ``` 该方法创建一个字符数组 `a`,并将其初始化为 `{ 0, 0, 0, 1 }`。然后将数组的地址强制转换为 `int` 类型的指针,如果该指针所指向的值为 `1`,则表示低位字节在高地址,是大端模式;否则是小端模式 [^3]。 #### 方法四:使用短整型和字符指针 ```c #include <stdio.h> #include <stdbool.h> bool IsLittleEndian() { short sShort = 0x1234; char *pcChar = (char *)&sShort; if (*pcChar == 0x34) { return true; } return false; } int main() { if (IsLittleEndian()) { printf("小端模式\n"); } else { printf("大端模式\n"); } return 0; } ``` 此方法定义了一个函数 `IsLittleEndian`,通过将一个短整型变量 `sShort` 的地址强制转换为 `char` 类型的指针,判断第一个字节的值是否为 `0x34`,若是则为小端模式 [^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值