在低级语言中(如C语言),开发人员进程需要关心的问题是大小字节序的问题,俗称大端小端。在内存中,大端是如何存放,小端是如何存放,我经常搞反,记不清楚。今天写这个文章,也是当个笔记,以后也不至于每次都要写个代码测试一下才记起来。
在叙述之前,一起普及几个常识性的概念。
网络字节序和本地字节序。网络字节序肯定是大端。至于本地字节序,就是指本地机器字节序,有可能是大端,也有可能是小端。
字节序只和CPU相关,和内存,硬盘,操作系统都毫无关系。这点很多菜鸟经常弄不清楚,混为一谈。
拿一个典型的数据 0x01020304 这个整形数据来说。如果是大端。其在内存的布局如下
如果是小端,其在内存的布局为:
可以总结为大端是高数值位(如千位)在高地址位(内存从左往右看的话,就是右边),简称高—高;
小端端是低数值位(如个位)在高地址位(内存从左往右看的话,就是右边),简称低—高;
除了大小端外,历史上还有一个叫PDU Endian
在写代码时候,程序经常需要判断机器是大端还是小端。常见有两种处理策略。
一是编译期判断。这种情况适合是已经确认只会在一种字节序平台上运行你的程序情况。属于平台相关型。运行效率高。基本方法是利用gcc 库带的头文件里面的宏。还有一个缺点是,代码书写排版都很丑陋。如下
- #if __BYTE_ORDER == __LITTLE_ENDIAN
- //小端,你的代码
- #elif __BYTE_ORDER == __BIG_ENDIAN
- //大端, 你的代码
- #endif
而是运行期判断,这种处理方法好处是放到哪个平台运行都可以,平台兼容。缺点是每次运行到那段代码,都要耗费CPU 指令判断。
- bool is_little_endian() { static uint32_t _endian_x_ = 1; return (reinterpret_cast<const uint8_t*>(&
_endian_x_))[0]; }
- bool is_big_endian() { return !is_little_endian(); }
建议程序中使用运行期判断方式,平台兼容,对性能影响几乎可以忽略不计。编译期判断,虽然代码是平台兼容的,但是编译出来的可执行文件就不是平台兼容,要么只能在大端上运行,要么在小端上运行
阅读(12030) | 评论(1) | 转发(3) |