嵌入式 Linux下的大小端的判断和实现

原创 2013年12月02日 14:38:23

二、为什么会有大小端模式之分呢?

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。但是在C语言中除了8bitchar之外,还有16bitshort型,32bitlong型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bitshortx,在内存中的地址为0x0010x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARMDSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

 

三、如何区分大小端问题:

方法1

  1. #include     <stdio.h>
  2. #include     <stdlib.h>
  3.      
  4.     
  5. int main(void   
  6.     
  7.    
  8.     
  9.        int 1;    
  10.     
  11.        unsigned char *pointer;    
  12.     
  13.      
  14.     
  15.        pointer (unsigned char *)&i;    
  16.     
  17.        if(*pointer)    
  18.     
  19.           
  20.     
  21.               printf("litttle_endian");    
  22.     
  23.           
  24.     
  25.        else    
  26.     
  27.           
  28.     
  29.               printf("big endian/n");    
  30.     
  31.           
  32.     
  33.      
  34.     
  35.        return 0;    
  36.     
  37.    
#include   
  
   
  
int main(void)  
  
{  
  
       int i = 1;  
  
       unsigned char *pointer;  
  
   
  
       pointer = (unsigned char *)&i;  
  
       if(*pointer)  
  
       {  
  
              printf("litttle_endian");  
  
       }  
  
       else  
  
       {  
  
              printf("big endian/n");  
  
       }  
  
   
  
       return 0;  
  
}  


       C中的数据类型都是从内存的低地址向高地址扩展,取址运算"&"都是取低地址。小端方式中(i占至少两个字节的长度)则i所分配的内存最小地址那个字节中就存着1,其他字节是0大端的话则1i的最高地址字节处存放,char是一个字节,所以强制将char型量p指向ip指向的一定是i的最低地址,那么就可以判断p中的值是不是1来确定是不是小端。

 

方法2

  1. #include     
  2.     
  3.      
  4.     
  5. int main(void   
  6.     
  7.    
  8.     
  9.        union    
  10.     
  11.               short a;    
  12.     
  13.               char ch;    
  14.     
  15.        u;    
  16.     
  17.        u.a 1;    
  18.     
  19.      
  20.     
  21.        if (u.ch == 1)    
  22.     
  23.           
  24.     
  25.               printf("Littel endian/n");    
  26.     
  27.           
  28.     
  29.        else    
  30.     
  31.           
  32.     
  33.               printf("Big endian/n");    
  34.     
  35.           
  36.     
  37.    
#include   
  
   
  
int main(void)  
  
{  
  
       union {  
  
              short a;  
  
              char ch;  
  
       } u;  
  
       u.a = 1;  
  
   
  
       if (u.ch == 1)  
  
       {  
  
              printf("Littel endian/n");  
  
       }  
  
       else  
  
       {  
  
              printf("Big endian/n");  
  
       }  
  
}  


       利用联合体的特点,数据成员共享内存空间,union中元素的起始地址都是相同的——位于联合的开始。char来截取感兴趣的字节

 

四、需要考虑大小端(字节顺序)的情况

1、所写的程序需要向不同的硬件平台迁移,说不定哪一个平台是大端还是小端,为了保证可移植性,一定提前考虑好。

2. 在不同类型的机器之间通过网络传送二进制数据时。一个常见的问题是当小端法机器产生的数据被发送到大端法机器或者反之时,接受程序会发现,字(word)里的字节(byte)成了反序的。为了避免这类问题,网络应用程序的代码编写必须遵守已建立的关于字节顺序的规则,以确保发送方机器将它的内部表示转换成网络标准,而接受方机器则将网络标准转换为它的内部标准。

3. 当阅读表示整数的字节序列时。这通常发生在检查机器级程序时,e.g.:反汇编得到的一条指令:
80483bd: 01 05 64 94 0408       add �x, 0x8049464

3. 当编写强转的类型系统的程序时。

例1:如写入的数据为u32型,但是读取的时候却是char型的:

如:0x1234, 大端读取为12时,小端独到的是34

例2:将buffer中的数转换为整型:

如:int src = 0x1234

      memcpy(buffer, src, sizeof(int));

     大端:buffer[4] = {0x01, 0x02, 0x03, 0x04};

     小端:buffer[4] = {0x04, 0x03, 0x02, 0x01};

六、提高程序的可移植性

使用宏编译

#ifdefLITTLE_ENDIAN

//小端的代码

#else

//大端的代码

#endif

 

七、大、小端之间的转换

1、小端转换为大端


  1. #include     <stdio.h>
  2. #include     <stdlib.h>
  3.     
  4.      
  5.     
  6. void show_byte(char *addr, int len)    
  7.     
  8.    
  9.     
  10.        int i;    
  11.     
  12.      
  13.     
  14.        for (i 0; len; i++)    
  15.     
  16.           
  17.     
  18.               printf("%.2x /t"addr[i]);    
  19.     
  20.           
  21.     
  22.        printf("/n");    
  23.     
  24.    
  25.     
  26.      
  27.     
  28. int endian_convert(int t)    
  29.     
  30.    
  31.     
  32.        int result;    
  33.     
  34.        int i;    
  35.     
  36.      
  37.     
  38.        result 0;    
  39.     
  40.        for (i 0; sizeof(t); i++)    
  41.     
  42.           
  43.     
  44.               result <<= 8;    
  45.     
  46.               result |= (t 0xFF);    
  47.     
  48.               >>= 8;    
  49.     
  50.           
  51.     
  52.      
  53.     
  54.        return result;    
  55.     
  56.    
  57.     
  58.      
  59.     
  60. int main(void   
  61.     
  62.    
  63.     
  64.        int i;    
  65.     
  66.        int ret;    
  67.     
  68.      
  69.     
  70.        0x1234567;    
  71.     
  72.      
  73.     
  74.        show_byte((char *)&i, sizeof(int));    
  75.     
  76.        ret endian_convert(i);    
  77.     
  78.        show_byte((char *)&ret, sizeof(int));    
  79.     
  80.      
  81.     
  82.        return 0;    
  83.     
  84.    

相关文章推荐

大小端检测方法(ARM 和linux系统)

http://blog.csdn.net/haojianno1/article/details/7925797 第一部份:检测ARM或其他单片机 一、概念及详解 在各种体系的计算机中通常...

Linux系统大小端判断

Linux系统大小端判断
  • Ivanpku
  • Ivanpku
  • 2016年06月02日 20:27
  • 1671

Linux系统的大小端模式

大端模式   所谓的大端模式,是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加...

ARM存储格式的“大小端”解析

ARM储存—大端格式和小端格式   所谓的大端模式,是指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而...

关于机器大小端的判定

关于大小端:              (本人在这个大小端问题上栽倒好多次了)         大端存储:高字节存储在低地址中,即高位先存;         小端存储:低字节存储在高地址中,即低...
  • bitboss
  • bitboss
  • 2016年04月26日 20:07
  • 1018

利用gcc的预定义宏和内置函数(Built-in Functions)实现大小端判断和大小端数据转换

对于涉及跨平台开发的项目,就可能会遇到数据大小端的问题,其实就是一个数字在内存中的字节序的问题,判断当前系统是大小端有现成的例子,自己实现转换代码也非常方便,网上有好多不用多说。 但我是个懒人,就算...
  • 10km
  • 10km
  • 2015年10月10日 11:17
  • 3148

大端和小端区别-linux

Little-Endian:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。 Big-Endian:高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。 记忆方法:小端:低地址存放...

[笔试题] 如何判断主机是大端还是小端(字节序)

今天看《linux程序设计》中关于跨平台需要注意的事项,看到了大端小端的问题。突然想起实验室一同学的笔试题,如何判断主机的大端还是小端。         所谓大端就是指高位值在内存中放低位地址,所谓...

如何使用Google日志库 (glog)

如何使用Google日志库 (glog) 介绍 Google glog是一个应用层的库. 它提供基于C++风格的流和多种宏接口.例如: #include int main(int ar...

RecyclerView的高级用法——定制动画

相信大家都对RecyclerView的用法相当熟悉了,RecyclerView的出现给我们开发者提供了一个高扩展的控件, 不管是列表、网格、瀑布流,一个控件就可以搞定,而且神奇的是只需要修改一行代码...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 Linux下的大小端的判断和实现
举报原因:
原因补充:

(最多只允许输入30个字)