大端
1、概述
在计算机系统中,数据都是以字节进行存储的,每个地址单元对应一个字节,每个字节都是8位(bit)。但是C++除了char和bool之外,还有其它多字节类型。怎样存储多字节的数据就分为了大端和小端。字节序只和使用的处理器架构有关,和编程语言无关,常见的Intel系列是小端序。
2、大端和小端
大端模式(Big-endian):数据的高位字节保存在内存的低地址中,而数据的地位字节保存到内存的高地址中。这样的存储有点类似把数据当作字符串处理,和我们的阅读习惯一致。
小端模式(Little-endian):数据的高位字节保存在内存的高地址中,而数据的高字节保存到内存的低地址中。
看概念总是让人记不住或者难以理解,让我们看看例子:
假设一个类型为int的变量x,x的首地址为0x100即&x的值为0x100。那么x的4个字节被存储在存储器的0x100,0x101,0x102,0x103的位置。x 的值为16进制 0x12345678。
数据是0x12345678,数据的高位是12,低位是78。
内存地址低位是0x100,高位是0x103。
对照上面的表格就很明白了。现在虽然理解了,但是概念有点像绕口令,很难让人记住,有人就说了一种另外的方法来记。
Big-endian = 高尾端:数据的尾端存在存储器的高地址。
Little-endian = 低尾端:数据的尾端存在存储器的低地址。
3、怎么判断计算机的字节序
使用union的方法判断:
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
union
{
short s;
char c[sizeof(short)];
} un;
un.s = 0x0102;
if (sizeof(short) == 2)
{
if (un.c[0] == 1 && un.c[1] == 2)
printf("大端法\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("小端法\n");
else
printf("不能判断\n");
} else
printf("sizeof(short) = %d\n", sizeof(short));
exit(0);
}
其它方法:
int main(int argc, char** argv)
{
short int x;
char x0, x1;
x = 0x1122;
x0 = ((char*)&x)[0];
x1 = ((char*)&x)[1];
printf("x0=0x%x", x0);
return 1;
}
若是0x=0x11,则是大端(高尾端)。若是0x=0x22则是小端(低尾端)。
4、对程序员有啥影响?
大多数情况下对写程序不会出影响,但在某些特殊情况下会成为问题:
1、编写网络程序时,主机之间通过网络相互通信,不同主机之间可能采用不用的存储方法,而且网络字节序和主机字节序也有可能不同。当小端法机器产生的数据被发送到大端法机器或者反方向发送时会发现接受程序子里面的字节成了反序的。为了避免这种情况的发生,规定网络应用程序在将数据发送之前现将数据转换称网络字节序,在接收主机那边,主机再将网络字节序的数据转换成适合本主机的主机字节序,从而避免了字节序异常。(网络字节序为大端法)
注意:这里其实只对数据类型有效,对于传送字符串时,char占用一个字节,所以传输之后的顺序是不会变的。
网络编程中常用的转换函数有如下几个:
uing16_t htons(uint16_t host16bitvalue); // 参数为16位主机字节序的值,返回值是16位网络字节序的值
uint32_t htonl(uint32_t host32bitvalue); // 参数为32位主机字节序的值,返回值是32位网络字节序的值
uint16_t ntohs(uint16_t net16bitvalue); // 参数为16位网络字节序的值,返回值是16位主机字节序的值
uint32_t ntohl(uint32_t net32bitvalue); // 参数为16位网络字节序的值,返回值是16位主机字节序的值
2、当调试程序时常常需要将程序编译成汇编形式,当阅读汇编代码时数据的字节序很重要,需要根据自己的机器是大端法还是小端法来不同对待,以免搞错字节顺序。
3、当编写规避正常类型系统的程序时,在C语言中可以使用强制类型转换来允许以一中类型引用一个对象,而这种数据类型与创建这个对象时定义的数据类型不同,大多数应用编程都不推荐这种编码技巧,但是它们对于系统级编程来说十分有用。
感谢大家,我是假装很努力的YoungYangD(小羊)。
参考资料:
https://www.cnblogs.com/broglie/p/5645200.html