计算机的大小端主要体现在两个点:
1,内存存储的大小端
2,网络字节序,确定的是大端。
内存之所以有大小端,原因为:超过1个字节的存储,比如short,int等,该如何组织存储单元?数据的高位放在内存的高地址还是低地址?都需要有明确的定义。
大端指的是数据的高位放在内存的低地址,小端则相反。
具体记忆的时候可以这样:我们肉眼看的或者写的就是大端。从左往右权重依次减小,内存地址依次增大。
内存存储大小端是由什么关键因素决定的?
分析下(纯属个人臆想分析)可能的决定点有:操作系统和CPU。
如果是操作系统,那么在程序经过编译之后应该会有显示的对于汇编指令的特殊调用来适配大小端操作,也就是说不应该是正常的调用汇编指令,所以只需要查看生成的汇编指令文件即可确定,gcc -S a.c,X86-64上面任写一个文件可以清楚的看到是直接使用汇编指令,并无特殊之处。目测应该不是操作系统来决定。
剩下的就是CPU本身了,CPU更能理解一点,汇编指令经过汇编之后生成的机器码,统一接口,硬件操作。
当然具体的也百度了下,网上一致说的也都是由CPU决定的,官方文档没有查看过。
接下来就是网络字节序的大小端。
why?为什么网络字节序需要大小端?
用于网络通信的套接字,端口和ip地址的存储都是大于一个字节的数据类型,同时这两个信息也是由用户来设置的,大小端的服务器都需要进行网络通信,网络模块代码也不可能说大端一份小端一份,那么这时候就需要做一个约定规定了,网络字节序使用大端,所以在写套接字代码的时候端口设置要用到htons htonl函数来显示的赋值大端模式下的值。
那接收端也是同样的,接收到之后肯定就是大端模式,根据大端模式来解析出端口或者ip地址。
这里还有一个问题:网络通信的tcp层用户数据需要显示的转换为大端吗?
回答是:可要可不要。
可要的原因是:服务器的客户端肯定有大端小端之分,且传输的数据必然有int等类型,那么必须需要一个统一的格式,要不然大端的服务器发送到小端的客户端上面,数据解析就肯定出错了,那么就需要采用协议栈标准的网络字节序了。
可不要的原因是:现在网络传输有各种各样的流库,比如json,protobuf等,把数据完全字符串话,也就是说避免了大小端的区分了,都是一个一个独立的char组成的字符串。
总结下就是:网络的字节序大端,主要就是协议栈内部使用。
另外一点,也是提供一个标准吧,毕竟网络是处在中间位置,两边可能不一致。
C语言判断大小端的代码:
理论上应该还可以通过CPU信息拿到,也有可能拿不到,必然系统没有提供等等原因,请知道的留言。
#include "stdio.h"
typedef struct {
char a;
char b;
}mystruct;
typedef union {
short value;
mystruct mysvalue;
}union_t;
int main()
{
union_t union_value={.value=0x0102};
if(union_value.mysvalue.a==0x01)
{
printf("big endian\n");
}
else if(union_value.mysvalue.a==0x02)
{
printf("small endian\n");
}
else
{
printf("a is %#x and b is %#x\n",union_value.mysvalue.a,union_value.mysvalue.b);
}
return 0;
}