字节序,一种简称,表示为内存中存储的字节的顺序,但仅仅是某一结构的存储字节的顺序,不影响总体结构。
起源
...
发展
...
基础
这里重点说一下字节序基础知识和用途。
字节序目前分为两种,大端字节序(big-endian,BE)和小端字节序(little-endian,LE)。在我们的编程惯性中,我们用得最多的是大端字节序,比如 unsigned int tmp = 0x1234; 那么 大单字节序的机器而言,tmp在内存的值为 0x1234,小端字节序机器而言,tmp在内存里面的值就是0x3412。所以我们惯性才是大端字节序。
1. 为什么要存在大端与小端。
这个问题其实是有必要的,如果大小端统一的话,对于我们程序员来说也就少了一些必要的编程考虑。对于大端和小端我比较接受网上的一个说法,"计算机的寻址都是一个起始地址加偏移量寻址的,小端的话就可以在寻址方面比较直观,因此可以带来一些额外的效果"。
对于两者为什么要并存的问题其实很难讲清楚,并且由于我的知识局限也没办法展开来讲。但是不可争议的时,随机时代的发展,市面上确实无法在短期内统一字节序。
2. 编程中的注意
很多时候我们编程都是用一个最直观的方式来的,对于一般情况,这些无伤大雅。但是对于数据传输的时候,如果不注意就会发送一段与网络字节序不一样的字节序,或者接受一段与当前机器字节序不符合的数据,对于这样的结果往往是网络抓包发现数据有问题,然后再仔细研究一下数据,最后找到原因,在代码中加入字节序的判断。
一般为了代码能够在不同平台运行,并且在不同字节序的机器上运行得出同样的结果,运行如下代码,看看是不是和想象中的结果一样。
/**
* test for BE and LE
*/
#include <stdio.h>
union test{
int a;
char b[4];
float c;
short d;
};
int main(){
union test t;
t.a = 128;
printf("int = %d,\nshort=%d,\nfloat%f\n",t.a,t.d,t.c);
printf("%d-%d-%d-%d",t.b[0] - '\0' ,t.b[1] - '\0',t.b[2] - '\0',t.b[3] - '\0');
scanf("%d",&t.a);
}
所以我们往往会在使用一些结构的时候加上一些判断,比如下面比较拙劣的判断:
int endian = 1;//default BE
union _t_{
short a;
char b[2];
};
_t_ _t;
_t.a = 1
if(_t.b[0] -'\0' == 1) endian = 0;// LE
#define __ENDIAN__ endian
在之后的使用中如果有涉及字节序的问题就需要判断一下。具体视情况而定。
网络字节序
网络传输中,都是使用大端字节序。