x86 是小端。 little endian 中的二进制数 1 是
|10000000|00000000|00000000|00000000
如果你把这个左移 9 位,它就变成了......
|00000000|01000000|00000000|00000000
在小端机器中,0xDEADBEEF 打印为从低地址到高地址的一系列字节实际上会打印 EFBEADDE,请参阅
https://www.codeproject.com/Articles/4804/Basic-concepts-on-Endianness
和
https://www.gnu-pascal.de/gpc/Endianness.html.
大多数人在思考二进制时认为数字 1 表示如下(包括我),有些人 think 这是大端,但不是......
|00000000|00000000|00000000|00000001
在下面的代码中,我以小端序打印了 0xDEADBEEF,因为我的机器是 x86,并且我使用了 htonl 函数将其转换为网络字节顺序。注意网络字节顺序被定义为Big Endian。
所以当我打印出 1 的大端值时,即htonl(1)。 1 的大端表示是
|00000000|00000000|00000000|10000000
试试这个代码
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
void print_deadbeef(void *p, size_t bytes) {
size_t i = 0;
for (i = 0; i < bytes; ++i) {
printf("%02X", ((unsigned char*)p)[i]);
}
printf("\n");
}
void print_bin(uint64_t num, size_t bytes) {
int i = 0;
for(i = bytes * 8; i > 0; i--) {
(i % 8 == 0) ? printf("|") : 1;
(num & 1) ? printf("1") : printf("0");
num >>= 1;
}
printf("\n");
}
int main(void) {
in_addr_t left = inet_addr("8.8.8.0");
in_addr_t right = inet_addr("8.8.9.0");
in_addr_t left_h = htonl(left);
in_addr_t right_h = htonl(right);
in_addr_t left_s = left << 9;
in_addr_t right_s = right >> 9;
assert(left != right);
printf("left != right\n");
print_bin(left, 4);
print_bin(right, 4);
printf("Big Endian if on x86\n");
print_bin(left_s, 4);
print_bin(right_s, 4);
printf("Little Endian if on x86\n");
print_bin(left_h, 4);
print_bin(right_h, 4);
printf("\n\nSome notes\n\n");
printf("0xDEADBEEF printed on a little endian machine\n");
uint32_t deadbeef = 0xDEADBEEF;
print_deadbeef(&deadbeef, 4);
uint32_t deadbeefBig = htonl(deadbeef);
printf("\n0xDEADBEEF printed in network byte order (big endian)\n");
print_deadbeef(&deadbeefBig, 4);
printf("\n1 printed on a little endian machine\n");
print_bin(1, 4);
printf("\nhtonl(1) ie network byte order (big endian) on a little endian machine\n");
print_bin(htonl(1), 4);
return 0;
}
这是输出
left != right
|00010000|00010000|00010000|00000000
|00010000|00010000|10010000|00000000
Big Endian if on x86
|00000000|00001000|00001000|00001000
|00100001|00100000|00000000|00000000
Little Endian if on x86
|00000000|00010000|00010000|00010000
|00000000|10010000|00010000|00010000
Some notes
0xDEADBEEF printed on a little endian machine
EFBEADDE
0xDEADBEEF printed in network byte order (big endian)
DEADBEEF
1 printed on a little endian machine
|10000000|00000000|00000000|00000000
htonl(1) ie network byte order on a little endian machine
|00000000|00000000|00000000|10000000