关于系统字节序

来源:互联网 发布:江苏减招 知乎 编辑:程序博客网 时间:2024/05/04 15:28

记录一下从网上搜索的关于系统字节序的相关帖子内容

 

    因为现行的计算机都是以八位一个字节为存储单位,那么一个16位的整数,也就是C语言中的short,在内存中可能有两种存储顺序big-endian和litte-endian.
    考虑一个short整数0x3132(0x32是低位,0x31是高位),把它赋值给一个short变量,那么它在内存中的存储可能有如下两种情况:
大端字节(Big-endian):
----------------->>>>>>>>内存地址增大方向
short变量地址
       0x1000                  0x1001
_____________________________
|                           |
|         0x31             |       0x32
|________________ | ________________
高位字节在低位字节的前面,也就是高位在内存地址低的一端.可以这样记住(大端->高位->在前->正常的逻辑顺序)

小端字节(little-endian):
----------------->>>>>>>>内存地址增大方向
short变量地址
       0x1000                  0x1001
_____________________________
|                           |
|         0x32             |       0x31
|________________ | ________________
低位字节在高位字节的前面,也就是低位在内存地址低的一端.可以这样记住(小端->低位->在前->与正常逻辑顺序相反)

可以做个实验
在windows上下如下程序
#include
#include

void main( void )
{
        short test;
        FILE* fp;
        
        test = 0x3132; //(31ASIIC码的’1’,32ASIIC码的’2’)
        if ((fp = fopen ("c://test.txt", "wb")) == NULL)
              assert(0);
        fwrite(&test, sizeof(short), 1, fp);
        fclose(fp);
}
    然后在C盘下打开test.txt文件,可以看见内容是21,而test等于0x3132,可以明显的看出来x86的字节顺序是低位在前.如果我们把这段同样的代码放到(big-endian)的机器上执行,那么打出来的文件就是12.这在本机中使用是没有问题的.但当你把这个文件从一个big- endian机器复制到一个little-endian机器上时就出现问题了.

下面代码示范了两种检测系统字节序的方法。

第一种方法,使用强制类型转换的方式。C 语言在把占用2个字节的 short 变量强制转换为 char 之后,会把 short 变量的首地址赋给 char 变量,可以根据 char 变量的值判断系统字节序是 大端 还是 小端。

第二种方法,利用 联合类型 的特性。联合类型 共享同一段内存,首地址是相同的。

/*******************
 * 文件名:endian.c
 ******************/
#include <stdio.h>

/*********************************************************
 * 使用类型的强制转换实现little-endian与big-endian的判断
 *********************************************************
 * 返回值:                                             
 *          1 表示是小端字节序。                        
 *          0 表示不是小端字节序。                      
 *********************************************************/
int is_little_endian_a(void)
{
    unsigned short flag = 0x4321;
    if(*(unsigned char*)&flag == 0x21)
        return 1;
    else
        return 0;
}

/*********************************************************************************
 * 利用联合的特点来判断little-endian与big-endian
 *********************************************************************************
 * 返回值:
 *          1   表示是小端字节序。
 *          0   表示是大端字节序。
 *          -1  表示不能使用这种方法确定字节序。比如有的机器的 short 长度不是 2 。
 ********************************************************************************/
int is_little_endian_b(void)
{
    union endian_un{
        short var;
        char bits[sizeof(short)];
    };

    union endian_un flag;
    flag.var=0x0102;

    //判断低位和高位的存储内容,确定是何种方式
    if(sizeof(short) == 2){
        if(flag.bits[0] == 1 && flag.bits[1] == 2)
            return 0;
        else if(flag.bits[0] == 2 && flag.bits[1] == 1)
            return 1;
        else
            return -1;
    }
   
    return -1;
}

int main(void)
{
    int type = 0;

    type = is_little_endian_a();
    if (1 == type)
        printf("judged by first method, little-endian/n");
    else if (0 == type)
        printf("judged by first method, big-endian/n");

    type = is_little_endian_b();
    if (1 == type)
        printf("judged by second method, little-endian/n");
    else if (0 == type)
        printf("judged by second method, big-endian/n");
    else
        printf("can't judge it/n");

    return 0;
}