内存“编程判断主机字节序”是很多杀毒软件公司或者安全公司开发职位喜欢考察的知识。因为实现代码比较简洁又与实际工作强相关。
我这里用两种方法完成编程。“取值比较法”和“直接转换比较法”。
1. 取值比较法
所谓取值比较法,是首先定义一个4字节的16进制数。因为使用调试器查看内存最直观的就是十六进制。而后通过指针方式取出这个十六进制数在“内存”中的某一个字节,最后俞实际数值中相对应的数进行比较。由于字节序的原因,内存中的某字节与实际数值中对应的字节可能不同,这样就可以确定字节序了。
#include <stdio.h>
#include<windows.h>
int main(int argc, char* argv[])
{
DWORD dwSmallNum = 0x01020304;
if (*(BYTE*)&dwSmallNum == 0x01)
{
printf("Small Sequence. \r\n");
}
else
{
printf("Big sequence. \r\n");
}
return 0;
}
VS2019调试输出
Big sequence.
以上代码中,定义了0x01020304这个十六进制数,其在小尾方式内存中的存储顺序为 04 03 02 01。取 *(BYTE*)&dwSmallNum 内存中的低地址位的值,如果是小尾方式的话,那么低地址存储的值是0x04;如果是大尾方式的话,则低地址存储的值是0x01
2.直接转换比较法
所谓直接转换比较法,是利用了字节序转换函数将所定义的值进行转换,然后用转换后的值与原来值做比较。如果原值和转换后的值相同,说明是大尾方式,否则是小尾方式。
#include <stdio.h>
#include<windows.h>
#pragma comment(lib, "ws2_32")
int main(int argc, char* argv[])
{
DWORD dwSmallNum = 0x01020304;
if ( dwSmallNum == htonl(dwSmallNum) )
{
printf("Small Sequence. \r\n");
}
else
{
printf("Big sequence. \r\n");
}
return 0;
}
VS2019调试输出
Big sequence.
这种方式比较直观,其前提是网络字节序是固定的,就是大尾方式。因为是比较,所以要有个参照物。如果原来数值转换后的结果与原值相同,就说明该主机是大尾方式存储,反之则是小尾方式存储。
总结
从我几年的协议开发的项目经验看,基本都是采用直接转换比较法来判断的。