大小端,"字节序"
2 字节序
2.1 字节
字节(Byte)作为计算机世界的计量单位,和大家手中的人民币多少多少“元”一个意思。反正,到了计算机的世界,说字节就对了,使用人家的基本计量单位,这是入乡随俗。
比如,一个电影是1G个字节(1GB),一首歌是10M个字节(10MB),一张图片是1K个字节(1KB)。
2.2 字节序
一元钱可以干嘛?啥也干不了,公交都不够坐的。一个字节可以干嘛?至少可以存一个字符。
当数据太大,一个字节存不下的时候,我们就得使用多个字节了。比如,我有两个分别需要4个字节存储的整数,为了方便说明,使用16进制表示这两个数,即0x12345678和0x11223344。有的人采用以下方式存储这个两个数字:
这个方案看起来不错,但是,又有人采用了以下方式:
蒙圈了吧,到底该用哪一种方式来存!两种方案虽有不同,但也有共识,即依次存储每一个数字,即先存0x12345678,再存0x11223344。大家的分歧在于,对于某一个要表示的值,因为只能一个字节一个字节的存嘛,我是把值的低位存到低地址,还是把值的高位存到低地址。前者使用的是“小端(Little endian)”字节序,即先存低位的那一端(两个数字的最低位分别是0x78、0x44),如上图中的第一个图;后者使用的是“大端(Big endian)”字节序,即先存高位的那一端(两个数字的最高位分别是0x12、0x11),如上图中的第二个图。
由此也引发了计算机界的大端与小端之争,不同的CPU厂商并没有达成一致:
- x86,MOS Technology 6502,Z80,VAX,PDP-11等处理器为Little endian。
- Motorola 6800,Motorola 68000,PowerPC 970,System/370,SPARC(除V9外)等处理器为Big endian。
- ARM, PowerPC (除PowerPC 970外), DEC Alpha, SPARC V9, MIPS, PA-RISC and IA64的字节序是可配置的。
大端也好,小端也罢,就权当是个人爱好吧,只要你不影响别人就行,对不?
2.3 网络字节序
前面的大端和小端都是在说计算机自己,也被称作主机字节序。其实,只要自己能够自圆其说是没啥问题的。问题是,网络的出现使得计算机可以通信了。通信,就意味着相处,相处必须得有共同语言啊,得说普通话,要不然就容易会错意,下了一个小时的小电影发现打不开,理解错误了!
但是每个计算机都有自己的主机字节序啊,还都不依不饶,坚持做自己,怎么办?
TCP/IP协议隆重出场,RFC1700规定使用“大端”字节序为网络字节序,其他不使用大端的计算机要注意了,发送数据的时候必须要将自己的主机字节序转换为网络字节序(即“大端”字节序),接收到的数据再转换为自己的主机字节序。这样就与CPU、操作系统无关了,实现了网络通信的标准化。突然觉得,TCP/IP协议好任性啊有木有!
为了程序的兼容,你会看到,程序员们每次发送和接受数据都要进行转换,这样做的目的是保证代码在任何计算机上执行时都能达到预期的效果。
这么常用的操作,BSD Socket提供了封装好的转换接口,方便程序员使用。包括从主机字节序到网络字节序的转换函数:htons、htonl;从网络字节序到主机字节序的转换函数:ntohs、ntohl。当然,有了上面的理论基础,也可以编写自己的转换函数。
下面的一段代码可以用来判断计算机是大端的还是小端的,判断的思路是确定一个多字节的值(下面使用的是4字节的整数),将其写入内存(即赋值给一个变量),然后用指针取其首地址所对应的字节(即低地址的一个字节),判断该字节存放的是高位还是低位,高位说明是Big endian,低位说明是Little endian。
#include <stdio.h>
int main ()
{
unsigned int x = 0x12345678;
char *c = (char*)&x;
if (*c == 0x78) {
printf("Little endian");
} else {
printf("Big endian");
}
return 0;
}
2.4 身边的字节序
字符编码方式UTF-16、UTF-32同样面临字节序的问题,因为他们分别使用2个字节和4个字节编码Unicode字符,一旦某个值用多个字节表示,就必须要考虑存储的顺序了。于是,采用了最简单粗暴的方式,给文件头部写几个字符,用来表示是大端呢还是小端:
头部的字符 编码 字节序 FF FE UTF-16/UCS-2 Little endian FE FF UTF-16/UCS-2 Big endian FF FE 00 00 UTF-32/UCS-4 Little endian 00 00 FE FF UTF-32/UCS-4 Big-endian
这里不得不提一下UTF-8啊,明明人家是单个字节的,不存在什么字节序的问题。微软为了统一UTF-X,硬生生给他的头部也加了几个字符!是的,这几个字符就是BOM(Byte Order Mark),这就是Windows下的UTF-8。
相信很多人都被UTF-8的BOM给坑过,多了这个BOM的UTF-8文件,会导致很多问题啊。比如,写的Shell脚本,内容为#!/usr/bin/env bash,在UTF-8有BOM和UTF-8无BOM的编码下,对应的16进制为:
所以,有BOM的话,Shell解释器就报错啦。原因在于,解释器希望遇到#!/usr/bin/env bash,而使用UTF-8有BOM进行编码的内容会多了3个字节的EF BB BF。
对于UTF-8和UTF-8无BOM两种编码格式,我们更多的使用UTF-8无BOM。
大小端,"字节序"的更多相关文章
- 从inet_pton()看大小端字节序
#include<stdio.h> #include<netinet/in.h> #include<stdlib.h> #include<string.h&g ...
- [C/C++]大小端字节序转换程序
计算机数据存储有两种字节优先顺序:高位字节优先(称为大端模式)和低位字节优先(称为小端模式). 大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿 ...
- linux kernel如何处理大端小端字节序
(转)http://blog.csdn.net/skyflying2012/article/details/43771179 最近在做将kernel由小端处理器(arm)向大端处理器(ppc)的移植的 ...
- 大端字节序&小端字节序(网络字节序&主机字节序)
大端字节序:整数的高位字节存储在内存的低地址处,低字节存储在内存的高地址处. 小端字节序:整数的高位字节存储在内存的高地址处,低字节存储在内存的低地址处. 一般pc大多采用小端字节序,也称为主机字节序 ...
- 写一个c程序辨别系统是大端or小端字节序
字节序有两种表示方法:大端字节序(big ending),小端字节序(little ending) 看一个unsigned short 数据,它占2个字节,给它赋值0x1234.若采用的大端字节序, ...
- C语言 大小端 字节对齐
参考:http://www.cnblogs.com/graphics/archive/2011/04/22/2010662.html 1. 大端序:数据的高位字节存放在地址的低端,低位字节存放在地址的 ...
- c/c++字节序转换(转)
字节序(byte order)关系到多字节整数(short/int16.int/int32,int64)和浮点数的各字节在内存中的存放顺序.字节序分为两种:小端字节序(little endian)和大 ...
- linux的大小端、网络字节序问题 .
1.80X86使用小端法,网络字节序使用大端法. 2.二进制的网络编程中,传送数据,最好以unsigned char, unsigned short, unsigned int来处理, unsigne ...
- linux网路编程:字节序(大端、小端、网络、主机)
字节序:就是数据在内存中的存放顺序,也可称之为端模式. 大端模式和小端模式的定义 1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端. 2) Big-End ...
随机推荐
- JS如何获取屏幕、浏览器及网页高度宽度?
屏幕的尺寸是指当前分辨率下的高度.宽度,而不是物理高度.宽度. 如:一个22寸的显示器,屏幕分辨率为1366 * 768,那么我们可以获取到的屏幕高度为1366px,宽度为768px. 屏幕宽度和高度 ...
- (转)Shell——基本运算符
Shell 基本运算符 原文:http://blog.csdn.net/sinat_36053757/article/details/70319481 Shell 和其他编程语言一样,支持多种运算符, ...
- gitbook一仓库多本书持续化部署
引言 本文档用户指导新手如何部署GitLab+Jenkins自动化构建GitBook,并使用Nginx发布资料.在部署过程中,如遇到任何问题,请自行百度. 注意: 此文章的环境和数据,仅为用于调试的片 ...
- 【VMware】无法连接MKS:套接字连接尝试次数太多;正在放弃
启动我的电脑 -> 右键 -> 管理 -> 服务和应用程序 -> 服务: 将当前服务全部进行启动
- js经验点滴js apply/call/caller/callee/bind使用方法与区别分析
一.call 方法 调用一个对象的一个方法,以另一个对象替换当前对象(其实就是更改对象的内部指针,即改变对象的this指向的内容). Js代码 call([thisObj[,arg1[, arg2[, ...
- [转] EF cannot be tracked because another instance of this type with the same key is already being tracked
本文转自:http://stackoverflow.com/questions/6033638/an-object-with-the-same-key-already-exists-in-the-ob ...
- 分页存储过程ROW_NUMBER() over(order by pid desc)
分页存储过程 : create proc usp_GetMyPhotos @pageIndex int, --当前页码 @pageSize int, --每页多少条 @pageCount ...
- java使用poi.3.10读取excel 2003 (xls格式)
最近在做一个Excel导入数据库的案例,整理文档出来供大家参考. 1.下载 最新的 poi http://poi.apache.org/download.html 2.解压 把相关jar包引进项 ...
- MySQL 查询多张表中相同字段的最大值
MySql : 有N张表,N未知,每张表都有一个字段(id),每张表的字段结构不完全一样,如何查询所有表里面所有id的最大值?如下图所示: 对上面三张表进行操作的话,结果应该为:9 SQL语句: se ...
- [转]谷歌Chrome浏览器开发者工具教程—JS调试篇
来源:http://blog.csdn.net/cyyax/article/details/51242720 上一篇我们学习了谷歌Chrome浏览器开发者工具的基础功能,下面介绍的是Chrome开发工 ...