大端(big-endian)和小端(little-endian)<转>
2007-12-07 20:36
补:x86机是小端(修改分区表时要注意),单片机一般为大端

今天碰一个关于字节顺序的问题,虽然看起来很简单,但一直都没怎么完全明白这个东西,索性就找了下资料,把它弄清楚.

    因为现行的计算机都是以八位一个字节为存储单位,那么一个16位的整数,也就是C语言中的short,在内存中可能有两种存储顺序big-endian和 litte-endian.考虑一个short整数0x3132(0x32是低位,0x31是高位),把它赋值给一个short变量,那么它在内存中的存 储可能有如下两种情况:
大端字节(Big-endian):
----------------->>>>>>>>内存地址增大方向
short变量地址
       0x1000                  0x1001
_____________________________
|                           |
|         0x31             |       0x32
|_______________ | ________________
高位字节在低位字节的前面,也就是高位在内存地址低的一端.可以这样记住(大端->高位->在前->正常的逻辑顺序)
小端字节(little-endian):
----------------->>>>>>>>内存地址增大方向
short变量地址
       0x1000                  0x1001
_____________________________
|                           |
|         0x32             |       0x31
|________________ | ________________
低位字节在高位字节的前面,也就是低位在内存地址低的一端.可以这样记住(小端->低位->在前->与正常逻辑顺序相反)
可以做个实验
在windows上下如下程序
#include <stdio.h>
#include <assert.h>
void main( void )
{
        short test;
        FILE* fp;
        
        test = 0x3132; //(31ASIIC码的’1’,32ASIIC码的’2’)
        if ((fp = fopen ("c://test.txt", "wb")) == NULL)
              assert(0);
        fwrite(&test, sizeof(short), 1, fp);
        fclose(fp);
}
    然后在C盘下打开test.txt文件,可以看见内容是21,而test等于0x3132,可以明显的看出来x86的字节顺序是低位在前.如果我们把这段 同样的代码放到(big-endian)的机器上执行,那么打出来的文件就是12.这在本机中使用是没有问题的.但当你把这个文件从一个big- endian机器复制到一个little-endian机器上时就出现问题了.
    如上述例子,我们在big-endian的机器上创建了这个test文件,把其复制到little-endian的机器上再用fread读到一个 short里面,我们得到的就不再是0x3132而是0x3231了,这样读到的数据就是错误的,所以在两个字节顺序不一样的机器上传输数据时需要特别小 心字节顺序,理解了字节顺序在可以帮助我们写出移植行更高的代码.
正因为有字节顺序的差别,所以在网络传输的时候定义了所有字节顺序相关的数据都使用big-endian,BSD的代码中定义了四个宏来处理:
#define ntohs(n)     //网络字节顺序到主机字节顺序 n代表net, h代表host, s代表short
#define htons(n)     //主机字节顺序到网络字节顺序 n代表net, h代表host, s代表short
#define ntohl(n)      //网络字节顺序到主机字节顺序 n代表net, h代表host, s代表 long
#define htonl(n)      //主机字节顺序到网络字节顺序 n代表net, h代表host, s代表 long
举例说明下这其中一个宏的实现:
#define sw16(x) /
    ((short)( /
        (((short)(x) & (short)0x00ffU) << 8) | /
        (((short)(x) & (short)0xff00U) >> 8) ))
这里实现的是一个交换两个字节顺序.其他几个宏类似.

我们改写一下上面的程序
#include <stdio.h>
#include <assert.h>

#define sw16(x) /
    ((short)( /
        (((short)(x) & (short)0x00ffU) << 8) | /
        (((short)(x) & (short)0xff00U) >> 8) ))

// 因为x86下面是低位在前,需要交换一下变成网络字节顺序
#define htons(x) sw16(x)
void main( void )
{
        short test;
        FILE* fp;
       
        test = htons(0x3132); //(31ASIIC码的’1’,32ASIIC码的’2’)
        if ((fp = fopen ("c://test.txt", "wb")) == NULL)
              assert(0);
        fwrite(&test, sizeof(short), 1, fp);
        fclose(fp);
}
    如果在高字节在前的机器上,由于与网络字节顺序一致,所以我们什么都不干就可以了,只需要把#define htons(x) sw16(x)宏替换为 #define htons(x) (x).
    一开始我在理解这个问题时,总在想为什么其他数据不用交换字节顺序?比如说我们write一块buffer到文件,最后终于想明白了,因为都是unsigned char类型一个字节一个字节的写进去,这个顺序是固定的,不存在字节顺序的问题,够笨啊..

big endian little endian相关推荐

  1. 字节序是什么?(大小端 Big endian Little endian)

    字节序,即字节在电脑中存放时的序列与输入(输出)时的序列是先到的在前还是后到的在前. 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序. 常见序: Little endian: 将 ...

  2. 汽车以太网-SOME/IP之字节序(Network Byte Order-Big Endian)

    引子 SOME/IP规范中有如下定义: All SOME/IP Header Fields shall be encoded in network byte order(big endian). 译文 ...

  3. byte endian(biglittle endian)

    1. 大小端的区别 little endian:把低位字节存放在内存的低位; // big endian:   将低位字节存放在内存的高位; 比如:0x1234,则12 就属于高位字节:34 属于低位 ...

  4. 字符编码简介 ANSI Unicode Unicode big endian UTF-8

    1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和 1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte) ...

  5. redis源码笔记-endian

    对于目标机是大端字节序的机器,进行字节码的转换,提供了16byte.32byte.64byte字节的转换.在intset\ziplist\zipmap三种数据结构中使用,使得不同字节序机器生成的rdb ...

  6. 关于endian的故事,big-endian和little-endian

    为什么80%的码农都做不了架构师?>>>    在各种计算机体系结构中,对于字节.字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特. ...

  7. c语言中.h文件中的宏定义,endian.h这个头文件里面的宏可以直接用么?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 endian.h头文件中以宏的形式定义了大端字节序.小端字节序和混合字节序 #define __LITTLE_ENDIAN 1234 #define __ ...

  8. 大端(Big Endian)与小端(Little Endian)详解

    大端(Big Endian)与小端(Little Endian)简介 /// 1. 你从哪里来? 端模式(Endian)的这个词出自JonathanSwift书写的<格列佛游记>.这本书根 ...

  9. big and little endian

    总是容易搞混big endian 和 little endian,但是找到一篇文章,其解释让人耳目一新. 文章链接:http://www.cs.umd.edu/class/sum2003/cmsc31 ...

最新文章

  1. kettle性能及效率提升_开发人员掌握了这个技术,SQL效率会有几百倍的性能提升...
  2. oracle rownum分页 出现重复数据
  3. ibm3650m2 如何安装linux4,System x3650M2 (Type 7947) Windows Server 2008安装指南
  4. linux的swap增加的二个办法
  5. 走在程序世界道路上的我___大一篇
  6. Kettle使用_17 计算器生成时间维度数据
  7. pdf页眉页脚设置步骤
  8. Div被Select挡住的解决办法
  9. 走出软件质量困境的指导性思想
  10. 钢结构设计软件:IDEA StatiCa 21.1.4.X Crack-new
  11. requests 使用 socks5 协议 的另外一种方式
  12. ERP的总体结构(ERP的工作原理1)-------(转)
  13. Android中的UID和AppId
  14. 国产FPGA高云GW1NSR-4C,集成ARM Cortex-M3硬核
  15. 0.前言 与 Eigen库的使用整理
  16. CEILING_2_POWER
  17. 构建AWS Site-to-Site IPsec实现内网互联
  18. python自学笔记15之实例之绘图、dataframe操作、读写csv,excle
  19. 学生护眼台灯哪个牌子最好?高品质的护眼灯推荐
  20. Unity 之 ShaderGraph 实现自发光和能量护盾效果入门级教程

热门文章

  1. 【POJ1113】Wall(凸包)
  2. 父子表关联在窗体中的绑定显示和浏览
  3. sql server 2005 T-SQL @@TOTAL_READ (Transact-SQL)
  4. hbase shell 查看列名_Hbase的简单命令使用
  5. linux定时任务定向到空,Linux 定时任务下 /dev/null 21 相关知识说明
  6. python 无头模式 绕过检测_Python chrome 无头模式的问题
  7. 并查集c++代码_[Leetcode 每日精选](本周主题-并查集) 547. 朋友圈
  8. mysql.data.dll win10_关于Linux和Windows下部署mysql.data.dll的注册问题》
  9. C语言 函数(做个笔记)
  10. c语言统计26个英文字母各出现个数,网上答案汇总与分析——【输入一串英文,统计各单词出现的个数】...