所以我正在编写一个程序来测试机器的endianess并打印它。 我理解小端和大端的区别,但是,从我在网上找到的,我不明白为什么这些测试显示机器的结束。
这是我在网上找到的。 *(char *)& x是什么意思,它如何证明机器是Little-Endian?
int x = 1;
if (*(char *)&x == 1) {
printf("Little-Endian\n");
} else {
printf("Big-Endian\n");
}
答案 0 :(得分:14)
如果我们分成不同的部分:
&x
:这会获取变量x
所在位置的地址,即&x
是指向x
的指针。类型为int *
。
(char *)&x
:这会使用x
的地址(int *
)并将其转换为char *
。
*(char *)&x
:取消引用char *
指向的&x
,即获取x
中存储的值。
现在我们回到x
以及如何存储数据。在大多数机器上,x
是四个字节。在1
中存储x
会将最低有效位设置为1
,其余位设置为0
。在小端机器上,它作为0x01 0x00 0x00 0x00
存储在内存中,而在大端机器上,它存储为0x00 0x00 0x00 0x01
。
表达式的作用是获取这些字节中的第一个并检查它是否为1
。
答案 1 :(得分:4)
这是内存的样子,假设一个32b整数:
Little-endian
0x01000000 = 00000001000...00
Big-endian
0x00000001 = 0......01
取消引用char *
会给你一个字节。您的测试通过将地址解释为char *
然后取消引用它来获取该内存位置的第一个字节。
答案 2 :(得分:1)
分解*(char *)&x
:
&x
是整数x的地址
(char *)
导致整数x的地址被视为字符的地址(又称字节)
*
引用字节的值
答案 3 :(得分:1)
int x;
x
是一个可以保存32位值的变量。
int x = 1;
给定硬件可以将值1
存储为以下格式之一的32-bit
值。
Little Endian
0x100 0x101 0x102 0x103
00000001 00000000 00000000 00000000
(or)
Big Endian
0x100 0x101 0x102 0x103
00000000 00000000 00000000 00000001
现在让我们尝试打破表达式:
&x
获取变量x
的地址。假设x
的地址为0x100
。
(char *)&x
&x
是整数变量的地址。 (char *)&x
将地址0x100
从(int *)
转换为(char *)
。
*(char *)&x
取消引用(char *)
中存储的值,该值只是4字节(32位整数x
)中的第一个字节(从左到右)。
(*(char *)&x == 1)
如果从左到右的第一个字节存储值00000001
,则它是小端。如果从左到右的第4个字节存储值00000001
,则它是大端。
答案 4 :(得分:0)
是的,这回答了这个问题。这是一个更一般的答案:
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
int main()
{
cout<<"sizeof(char) = "<<sizeof(char)<<endl;
cout<<"sizeof(unsigned int) = "<<sizeof(unsigned int)<<endl;
//NOTE: Windows, Mac OS, and Linux and Tru64 Unix are Little Endian architectures
//Little Endian means the memory value increases as the digit significance increases
//Proof for Windows:
unsigned int x = 0x01020408; //each hexadecimal digit is 4 bits, meaning there are 2
//digits for every byte
char *c = (char *)&x;
unsigned int y = *c*pow(16,0) +pow(16,2) * *(c+1)+pow(16,4) * *(c+2)+pow(16,6) * *(c+3);
//Here's the test: construct the sum y such that we select subsequent bytes of 0x01020408
//in increasing order and then we multiply each by its corresponding significance in
//increasing order. The convention for hexadecimal number definitions is that
//the least significant digit is at the right of the number.
//Finally, if (y==x),then...
if (y==x) cout<<"Little Endian"<<endl;
else cout<<"Big Endian"<<endl;
cout<<(int) *c<<endl;
cout<<(int) *(c+1)<<endl;
cout<<(int) *(c+2)<<endl;
cout<<(int) *(c+3)<<endl;
cout<<"x is "<<x<<endl;
cout<<(int)*c<<"*1 + "<<(int)*(c+1)<<"*16^2 + "<<(int)*(c+2)<<"*16^4 + "<<(int)*(c+3)<<" *16^6 = "<<y<<endl;
system("PAUSE"); //Only include this on a counsel program
return 0;
}
显示 8 4 2 1 对于c,c + 1,c + 2和c + 3处的解除引用值。 和y是16909320,等于x。即使数字的重要性从右向左增长,这仍然是Little Endian,因为相应的存储器值也从右向左增长,这就是左移二元运算符&lt;&lt;会增加变量的值,直到非零数字完全偏离变量。不要将此运算符与std :: cout的&lt;&lt;混淆运营商。 如果这是Big Endian,则c,c + 1,c + 2和c + 3的显示分别如下所示: 1 2 4 8
答案 5 :(得分:0)
如果big-endian 4字节无符号整数看起来像0xAABBCCDD等于2864434397,那么同样的4字节无符号整数在小端处理器上看起来像0xDDCCBBAA,也等于2864434397。
如果big-endian 2字节无符号短路看起来像0xAABB等于43707,那么相同的2字节无符号短路看起来像小端处理器上的0xBBAA,也等于43707。
以下是一些方便的#define函数,用于将字节从little-endian交换为big-endian,反之亦然 - &gt;
// can be used for short, unsigned short, word, unsigned word (2-byte types)
#define BYTESWAP16(n) (((n&0xFF00)>>8)|((n&0x00FF)<<8))
// can be used for int or unsigned int or float (4-byte types)
#define BYTESWAP32(n) ((BYTESWAP16((n&0xFFFF0000)>>16))|((BYTESWAP16(n&0x0000FFFF))<<16))
// can be used for unsigned long long or double (8-byte types)
#define BYTESWAP64(n) ((BYTESWAP32((n&0xFFFFFFFF00000000)>>32))|((BYTESWAP32(n&0x00000000FFFFFFFF))<<32))