大小端问题

工作中会遇到数据大小端问题,也就是大于1个字节的数据在内存中是怎么存放的(内存是按字节来存放数据的,每个内存地址只放1个字节)。

大小端解释:

大端:低地址放高位数据,高地址放低位数据

小端:低地址放低位数据,高地址放高位数据

总结一句话:按内存地址增长的顺序,先放高位就据就是大端,先放低位数据就是小端。


比如32bit的CPU:

读数据:(假设内存0x00000000,0x00000001,0x00000002,0x00000003四个地址分别存放:0xaa,0xbb,0xcc,0xdd四个字节)

大端读出来的结果是:0xaabbccdd

小端读出来的结果是:0xddccbbaa


存数据:(假设要把0xaabbccdd存放到0x00000000地址)

大端写入的结果是:0x00000000(0xaa) 0x00000001(0xbb) 0x00000002(0xcc) 0x00000003(0xdd)

小端写入的结果是:0x00000000(0xdd) 0x00000001(0xcc) 0x00000002(0xbb) 0x00000003(0xaa)


PS:X86是小端的,KEIL C51是大端的,ARM DSP是小端的,有些ARM大小端可配置的。


几种判断大小端的程序:

linux操作系统对大小端的判断

static union { char c[4]; unsigned long l; } endian_test = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l)
(如果ENDIANNESS=’l’表示系统为little endian,为’b’表示big endian )。

C语言判断

/* 1 : little-endian */

/* 0 : big-endian */

int islittle_endian() 
{
union w { int a; char b; } c;
c.a = 1;
return (c.b);
}


由于网络字节序是大端的,此时对于大端的处理器,字节序是不需要改变的。而对于小端的处理器则需要转变。

#if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)  
  
  
   #define htons(A)  (A)  
   #define htonl(A)  (A)  
   #define ntohs(A)  (A)  
   #define ntohl(A)  (A)  
  
  
#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)  
  
  
   #define htons(A)  ((((uint16_t)(A) & 0xff00) >> 8 ) | \\  
                      (((uint16_t)(A) & 0x00ff) << 8 ))  
   #define htonl(A)  ((((uint32_t)(A) & 0xff000000) >> 24)  | \\  
                      (((uint32_t)(A) & 0x00ff0000) >> 8 )  | \\  
                      (((uint32_t)(A) & 0x0000ff00) << 8 )  | \\  
                      (((uint32_t)(A) & 0x000000ff) << 24))  
   #define ntohs     htons  
   #define ntohl     htohl  
  
  
#else  
  
  
   #error Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both.  
  
  
#endif

发布了7 篇原创文章 · 获赞 17 · 访问量 24万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览