c中的字节序

首先我们要知道我们C程序映像中内存的空间布局情况:在《C专家编程》中或者《Unix环境高级编程》中有关于内存空间布局情况的说明,大致如下图:
----------------------- 最高内存地址 0xffffffff
 | 栈底
 .
             
 .
  栈顶
-----------------------
 |
 |
\|/

NULL (空洞)

/|\
 |
 |
-----------------------
               
-----------------------
未初始化的数据
----------------(统称数据段)
初始化的数据
-----------------------
正文段(代码段)
----------------------- 最低内存地址 0x00000000

以上图为例如果我们在栈上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢[注1]?看下图:
栈底 (高地址)
----------
buf[3]
buf[2]
buf[1]
buf[0]
----------
栈顶 (低地址)

现在我们弄清了高低地址,接着来弄清高/低字节,如果我们有一个32位无符号整型0x12345678(呵呵,恰好是把上面的那4个字节buf看成一个整型),那么高位是什么,低位又是什么呢?其实很简单。在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。

高低地址和高低字节都弄清了。我们再来回顾一下Big-Endian和Little-Endian的定义,并用图示说明两种字节序:
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位,如下图:
栈底 (高地址)
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
栈顶 (低地址)

Little-Endian: 低地址存放低位,如下图:
栈底 (高地址)
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
---------------
栈顶 (低地址)

在现有的平台上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。

================================================================================================================

The display of text is reversed from the normal display of languages such as English that read from left to right. For example, the word "XRAY" displayed in this manner, with each character stored in an 8-bit atomic element:

←  increasing addresses
... "Y" "A" "R" "X" ...
可以看到和我们手写的顺序是相反的,这一点特别要注意!) 

If pairs of characters are stored in 16-bit atomic elements (using 8 bits per character), it could look even stranger:

←  increasing addresses
... "AY" "XR" ...
相关的一个C例子:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6.         char a[]= {'a','b','c'};
  7.         char b[]= {'d','e','f'};

  8.         a[3]= 0;
  9.         printf("strlen(a)=%d, strlen(b)=%d\n", strlen(a), strlen(b));
  10.         printf("a=%s, b=%s\n", a, b);
  11.         printf("sizeof(a)=%d, sizeof(b)=%d\n", sizeof(a), sizeof(b));
  12.         return 0;
  13. }
运行结果:
strlen(a)=3, strlen(b)=6
a=abc, b=defabc
sizeof(a)=3, sizeof(b)=3
分析:
字符数组a和b都分配在栈上,先分配a, 而a中的字符是如何分配的呢?显然因为“写字符串时,低位的字符写在左边,高位的字符写在了右边”。'a'是最低位,'b'在中间,而'c'在最高位。而栈是从高地址从低地址扩展的。假如是小端CPU的话,按照“高高低低”的原则,高位的'c'应该最先分配,接着是'b',最后是'a'。
分配玩字符数组a之后,在分配字符数组b,同样的道理,高位的'f'应该最先分配,接着是'e',最后是'd'。
再执行a[3] = 0;显然a[3]的地址应该比'c'字符的地址要高。所以该语句执行玩之后的栈的情况如下:
高地址 <<---- 低地址
\0   c   b   a   f   e   d
所以:a字符打印的结果是:abc,而b字符打印的结果是:defabc.

下面是一个判断大小端的小程序:
int main()
{
        int x=1;
        if (*(char *) &x ==1)
                printf("Little endian!\n");
        else    printf("Big endian!\n");
        return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值