这个人说得很好, 看到真让我懂了!!, 每个人都能懂!
字节顺序的详细解释
草木瓜 2006.7.26
一、基本概念
位的概念:在计算机中,一个0或1称为一位(bit)。
字节:连续的八位称为一个字节(Byte),字节是计算机中可单独处理的最小单位。即以字节
为基本单位来解释信息,规定1个字节是8个二进制位。
通常1个ASCII码用1个字节存放,1个汉字用2个字节存放,双精度浮点实数用8个字节存放。
下面列表C语言中定义类型所占字节以及数据范围。
类型标识符 类型说明 长度(字节) 范围 备注
char 字符型 1 -128 ~ 127 -2^7~(2^7-1)
unsigned char 无符字符型 1 0 ~ 255 0~(2^8-1)
short int 短整型 2 -32768 ~ 32767 -2^15~(2^15-1)
unsigned short int 无符短整型 2 0 ~ 65535 0~(2^16-1)
int 整型 4 -2147483648 ~ 2147483647 -2^31~(2^31-1)
unsigned int 无符整型 4 0 ~ 4294967295 0~(2^32-1)
float 实型(单精度) 4 1.18*10-38 ~ 3.40*1038 7位有效位
double 实型(双精度) 8 2.23*10-308 ~ 1.79*10308 15位有效位
long double 实型(长双精度) 10 3.37*10-4932 ~ 1.18*104932 19位有效位
二、字节顺序由来
我们在写字符流时,因为字符型只占一个字节数,计算机只须按一个字符一个字符
写入文件即可。但是如果是处理整型时,由于整型占4个字节,所以一个整型内部的
字节存储排列的顺序直接关系到被计算机识别出来的整型值。某种意义上也可直接
理解计算机的识别顺序就是所谓的字节顺序。
三、一些有关字节顺序的解释
不同的计算机结构有时使用不同的字节顺序存储数据。例如,基于Intel的计算机存储数据
的顺序与Macintosh(Motorola)计算机就是相反的。Intel字节顺序称为“Little-Endian”,
反之Macintosh(Motorola),还有网络上采用标准是“Big-Endian”。在将应用程序从一种架
构类型迁移至另一种架构类型的过程中,经常会遇到字节排列顺序(endianness)问题。
字节排列顺序是数据元素及其单个字节在内存中存储和表示时的顺序。
通过以上分析,会发现有两类字节排列顺序:big-endian (通常为网络字节顺序)和
little-endian(主机字节顺序)。
下面是这些术语的废话解释。
Big-Endian 最重要的字节在整个内容的左端。
Little-Endian 最重要的字节在整个内容的右端。
对于big-endian处理器,在将字放在内存中时,是从最低位地址开始的,首先放入最重要的
字节。另一方面,对于little-endian处理器,如Intel处理器,首先放入的是最不重要的字
节。
说完上面的概念还是很模糊,个人认为对于不了解的字节顺序的人绝对是废话,网上大多都
是照搬照抄这几段废话。具体我们通过实际例子说明。
四、这里的解释说明
我们先看下面的代码,看完啥都明白了。
这是运行在HP-UNIX 9000/800下完整的C语言代码,即为 Big-Endian 方式。
#include <unistd.h>
void main()
{
int i=0x41424344;
printf("int Address:%x Value:%x\n",&i,i);
printf("-------------------------------\n");
char* pAddress=(char*)&i;
int j;
for(j=0;j<=3;j++)
{
printf("char Address:%x Value:%c\n",pAddress,*pAddress);
pAddress++;
}
}
编译输出(cc -g ...):
int Address:7f7f08f0 Value:41424344
-------------------------------
char Address:7f7f08f0 Value:A
char Address:7f7f08f1 Value:B
char Address:7f7f08f2 Value:C
char Address:7f7f08f3 Value:D
我们回到Windows XP下,看看这段代码的输出。Little-Endian 模式。
#include <stdio.h>
void main()
{
int i=0x41424344;
printf("int Address:%x Value:%x\n",&i,i);
printf("-------------------------------\n");
char* pAddress=(char*)&i;
int j;
for(j=0;j<=3;j++)
{
printf("char Address:%x Value:%c\n",pAddress,*pAddress);
pAddress++;
}
}
编译输出(VC 6.0):
int Address:12ff7c Value:41424344
-------------------------------
char Address:12ff7c Value:D
char Address:12ff7d Value:C
char Address:12ff7e Value:B
char Address:12ff7f Value:A
看完上面代码,应该就很清楚了,什么字节顺序?真是简单的要死!int i=0x41424344;
采用16进制,我们知道A的ACSII码是65,16进制就是41,可以理解,本例是想通过输出
A,B,C,D来验证字节顺序。我再对内存数据进行列表,相信会更有深层次的理解。
Big-Endian的内存放置顺序如下:
地址:0x7f7f08f0 0x7f7f08f1 0x7f7f08f2 0x7f7f08f3
0x41 0x42 0x43 0x44
Little-Endian的内存放置顺序如下:
地址:0x0012ff7c 0x0012ff7d 0x0012ff7e 0x0012ff7f
0x44 0x43 0x42 0x41
五、最后的说明
主机字节顺序(Host)
Little-Endian [ Intel、VAX和Unisys处理器 等]
网络字节顺序(Network)
Big-Endian [ IBM 370、Motorola和大多数RISC设计 ---- IBM 大型机和大多数Unix平台 ]
字节转换多半应用在网络编程,或者代码移植的情况下。
Unix环境下的一些相关函数:(必须包含头文件 #include <netinet/in.h>)
htons()--"Host to Network Short"
htonl()--"Host to Network Long"
ntohs()--"Network to Host Short"
ntohl()--"Network to Host Long"
Windows .Net 一些相关函数:
HostToNetworkOrder
NetworkToHostOrder
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=980278