Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1856983
  • 博文数量: 38
  • 博客积分: 690
  • 博客等级: 中士
  • 技术积分: 3715
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-27 14:06
文章分类

全部博文(38)

文章存档

2018年(8)

2016年(4)

2015年(2)

2014年(1)

2013年(3)

2012年(20)

分类: LINUX

2012-09-18 22:37:25

  在低级语言中(如C语言),开发人员进程需要关心的问题是大小字节序的问题,俗称大端小端。在内存中,大端是如何存放,小端是如何存放,我经常搞反,记不清楚。今天写这个文章,也是当个笔记,以后也不至于每次都要写个代码测试一下才记起来。

  在叙述之前,一起普及几个常识性的概念。
  网络字节序和本地字节序。网络字节序肯定是大端。至于本地字节序,就是指本地机器字节序,有可能是大端,也有可能是小端。
  字节序只和CPU相关,和内存,硬盘,操作系统都毫无关系。这点很多菜鸟经常弄不清楚,混为一谈。
  
   拿一个典型的数据 0x01020304 这个整形数据来说。如果是大端。其在内存的布局如下
   

 0x04

 0x03

 0x02

 0x01

  
   如果是小端,其在内存的布局为:

 0x01

 0x02

 0x03

 0x04


   可以总结为大端是高数值位(如千位)在高地址位(内存从左往右看的话,就是右边),简称高—高;
   小端端是低数值位(如个位)在高地址位(内存从左往右看的话,就是右边),简称低—高;

    除了大小端外,历史上还有一个叫PDU  Endian

 0x03

0x04 

0x01 

0x02 



   在写代码时候,程序经常需要判断机器是大端还是小端。常见有两种处理策略。
   一是编译期判断。这种情况适合是已经确认只会在一种字节序平台上运行你的程序情况。属于平台相关型。运行效率高。基本方法是利用gcc 库带的头文件里面的宏。还有一个缺点是,代码书写排版都很丑陋。如下

  1. #if __BYTE_ORDER == __LITTLE_ENDIAN
  2.    //小端,你的代码
  3. #elif __BYTE_ORDER == __BIG_ENDIAN
  4.   //大端, 你的代码
  5. #endif
   而是运行期判断,这种处理方法好处是放到哪个平台运行都可以,平台兼容。缺点是每次运行到那段代码,都要耗费CPU 指令判断。
  1. bool is_little_endian() { static uint32_t _endian_x_ = 1; return (reinterpret_cast<const uint8_t*>(& _endian_x_))[0]; }
  2. bool is_big_endian() { return !is_little_endian(); }

   建议程序中使用运行期判断方式,平台兼容,对性能影响几乎可以忽略不计。编译期判断,虽然代码是平台兼容的,但是编译出来的可执行文件就不是平台兼容,要么只能在大端上运行,要么在小端上运行
阅读(12030) | 评论(1) | 转发(3) |
给主人留下些什么吧!~~

leizisdu2013-08-12 22:05:07

博主,你好!你对大端和小端的定义似乎不对。大端:数据的高字节存储在内存的低地址;小端:数据的低字节存储在内存的低地址。设内存地址从左到右不断增大,对整型数据0x01020304来说,大端存储时,内存布局是:0x01,0x02,0x03,0x04;小端存储时,内存布局是:0x04,0x03,0x02,0x01。你所举的例子,那个判断是否是小端存储的函数的实现是对的,与你对小端存储的定义相反。