Chinaunix首页 | 论坛 | 博客
  • 博客访问: 76243
  • 博文数量: 13
  • 博客积分: 229
  • 博客等级: 二等列兵
  • 技术积分: 162
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-03 09:45
文章分类

全部博文(13)

文章存档

2013年(2)

2012年(11)

分类: LINUX

2012-07-26 09:40:35

本文档的Copyleft归rosetta所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性。
参考资料:UNPV13e
    字节序的概念是最基础不过的,但这东西学了不经常用就忘,所以以后学习回顾后都记成笔记以备查询使用,并且也可以记录我近段时间的学习历程。
    内存中存储数据有两种方法:一种是低字节存在低地址,高字节存在高地址,称为小端字节序(little-endian);另一种正常好相反,低字节存在高地址处,高字节存在低地址处。只要记住小端字节序:小高高(小代表小端,第一个高代表高字节,第二个代码高地址),那么另外一个大端自然而然就知道。一般情况下,网络字节序使用大端,intel x86主机序为小端。本文先画个草图,然后给出两个判断当前主机是小端还是大端的源码,结合代码就能更好理解和记忆。
    
              低地址                       高地址
              ------------------------------------->
   小端字节序 |  低字节|        |        | 高字节  |
              ------------------------------------->
                        图1
 
   比如int a = 0x01020304,
   如果是小端,在内存中的分布就如下图2:
                低地址                       高地址
              ------------------------------------->
   小端字节序 |  0x04  |  0x03  |  0x02  |  0x01   |
              ------------------------------------->
                        图 2

   如果是大端,在内存中的分布就如下图3:
                低地址                       高地址
              ------------------------------------->
   大端字节序 |  0x01  |  0x02  |  0x03  |  0x04   |
              ------------------------------------->
                        图 3

代码一:
  结合以上图2、图3,给出判断当前主机字节序的c源码:
  //mybyteorder
  #include

  int main(void)
  {
      int a = 0x01020304;//0x04相当于低字节,0x01为高字节。
      if(*(char *)&a == 0x01)//如果a的首地址(即低地址)第一个字节长度地址存放的是高字节内容0x01,那么主机序为大端。
          printf("big.\n");
      else if(*(char*)&a == 0x4)//如果a的首地址一个字节长度地址存放的是低字节内容04,那么主机序为小端。
          printf("small.\n");
 
      return 0;
  }
  [root@xxx study]# gcc mybyteorder.c -Wall -o app
  [root@xxx study]# ./app
  small.

代码二(来到UNPV1e3):
  此代码片段还可以理解union这个数据类型的使用,unp.h在UNPV1e3源码中都有,包括此代码也有。


  //byteorder.c
  #include    "unp.h"
 
  int
  main(int argc, char **argv)
  {
      union {
        short  s;
        char   c[sizeof(short)];
      } un;
 
      un.s = 0x0102;//0x02为低字节,0x01为高字节。
      printf("%s: ", CPU_VENDOR_OS);
      if (sizeof(short) == 2) {
          if (un.c[0] == 1 && un.c[1] == 2)
              printf("big-endian\n");
          else if (un.c[0] == 2 && un.c[1] == 1)
              printf("little-endian\n");
          else
              printf("unknown\n");
      } else
          printf("sizeof(short) = %d\n", sizeof(short));
 
      exit(0);
  }

  [root@xxx intro]# make
  gcc -I../lib -g -O2 -D_REENTRANT -Wall   -c -o byteorder.o byteorder.c
  gcc -I../lib -g -O2 -D_REENTRANT -Wall -o byteorder byteorder.o ../libunp.a -lpthread
  [root@xxx intro]# ./byteorder
  i686-pc-linux-gnu: little-endian

  正因为保留代码一,是想看其对于非char类型进行char操作的过程,当然其可改成像代码二一样使用union的方法:
  int main(void)
    union{
        int a;
        char s[sizeof(int)];
    }u;

    u.a = 0x01020304;
    if(u.s[0] == 0x01)
        printf("big.\n");
    else if(u.s[0] == 0x04)
        printf("small.\n");

    return 0;
  }
阅读(2314) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~