c语言大小端转化
补:x86机是小端(修改分区表时要注意),单片机一般为大端
大端字节(Big-endian):
----------------->>>>>>>>内存地址增大方向
short变量地址
_____________________________
| | |_______________|________________
高位字节在低位字节的前面,也就是高位在内存地址低的一端.可以这样记住(大端->高位->在前->正常的逻辑顺序)
小端字节(little-endian):
----------------->>>>>>>>内存地址增大方向
short变量地址
_____________________________
| | |________________|________________ 低位字节在高位字节的前面,也就是低位在内存地址低的一端.可以这样记住(小端->低位->在前->与正常逻辑顺序相反)
可以做个实验
在windows上下如下程序
#include<stdio.h>
#include<assert.h>
void main( void )
{
}
/ 在LINUX下程序 #include <stdio.h> int main() { } 如果输出的结果是a = 0x12345678 b = 0x78 则说明你的机器是小端存放 ///
正因为有字节顺序的差别,所以在网络传输的时候定义了所有字节顺序相关的数据都使用big-endian,BSD的代码中定义了四个宏来处理:
#definentohs(n)
#definehtons(n)
#definentohl(n)
#definehtonl(n)
举例说明下这其中一个宏的实现:
#define sw16(x) \
这里实现的是一个交换两个字节顺序.其他几个宏类似.
我们改写一下上面的程序
#include<stdio.h>
#include<assert.h>
#define sw16(x) \ // 因为x86下面是低位在前,需要交换一下变成网络字节顺序
#define htons(x) sw16(x)
void main( void )
{
}
|
文章三:
big-endian和little-endian这两个术语来自JonathanSwift在十八世纪的嘲讽作品Gulliver’sTravels。Blefuscu帝国的国民被根据吃鸡蛋的方式划分为两个部分:一部分在吃鸡蛋的时候从鸡蛋的大端(bigend)开始,而另一部分则从鸡蛋的小端(little end)开始。
x86的CPU使用的是LE(Windows中称为“主机字节序”),而SocksAddr中使用的则是BE(就是“网络字节序”),所以在使用网络编程时需要使用htns,htnl,nths,nthl来倒字节序。
其实对汇编熟了就清楚了,惨,我的汇编很惨的
LE little-endian
最符合人的思维的字节序
地址低位存储值的低位
地址高位存储值的高位
怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说
低位值小,就应该放在内存地址小的地方,也即内存地址低位
反之,高位值就应该放在内存地址大的地方,也即内存地址高位
BE big-endian
最直观的字节序
地址低位存储值的高位
地址高位存储值的低位
为什么说直观,不要考虑对应关系
只需要把内存地址从左到右按照由低到高的顺序写出
把值按照通常的高位到低位的顺序写出
两者对照,一个字节一个字节的填充进去
例子:在内存中双字0x01020304(DWORD)的存储方式
内存地址
4000 4001 4002 4003
LE 04 03 02 01
BE 01 02 03 04
MSDN中关于LE和BE的解释
Byte Ordering Byte ordering Meaning
big-endian The most significant byte is on the left end ofaword.
little-endian The most significant byte is on the right end ofaword.
这里这个最重要的字节可以解释成值的最高位,如果换成是钱的话就是最值钱的那一位
比如我有1234元人民币,最值钱的是1000元,最不值钱的是4元,那么这个1就是最重要的字节
Big endian machine: It thinksthefirst byte it reads is the biggest.
Little endian machine: It thinks the first byte it reads isthelittlest.
举个例子,从内存地址0x0000开始有以下数据
0x0000
0x0001
0x0002
0x0003
如果我们去读取一个地址为0x0000的四个字节变量,若字节序为big-endian,则读出
结果为0x1234abcd;若字节序位little-endian,则读出结果为0xcdab3412.
如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
0x0000
0x0001
0x0002
0x0003
x86系列CPU都是little-endian的字节序.