我正在编写一个程序来测试机器的字节序并打印出来。我了解小端和大端的区别,但是从我在网上查找到的内容中,我不明白为什么这些测试可以显示机器的字节序。
以下是我在网上找到的内容。*(char *)&x 是什么意思,为什么它等于 1 就证明机器是小端字节序?
int x = 1;
if (*(char *)&x == 1) {
printf("Little-Endian\n");
} else {
printf("Big-Endian\n");
}
我正在编写一个程序来测试机器的字节序并打印出来。我了解小端和大端的区别,但是从我在网上查找到的内容中,我不明白为什么这些测试可以显示机器的字节序。
以下是我在网上找到的内容。*(char *)&x 是什么意思,为什么它等于 1 就证明机器是小端字节序?
int x = 1;
if (*(char *)&x == 1) {
printf("Little-Endian\n");
} else {
printf("Big-Endian\n");
}
如果我们将其分成不同的部分:
&x
: 这会得到变量 x
的地址,即 &x
是指向 x
的指针。类型是 int *
。
(char *)&x
: 这将获取 x
的地址(它是一个 int *
),并将其转换为 char *
。
*(char *)&x
: 这会取消引用由 &x
指向的 char *
,即获取存储在 x
中的值。
现在如果我们回到 x
和数据的存储方式。在大多数机器上,x
是四个字节长的。将 1
存储在 x
中将最低有效位设置为 1
,其余为 0
。在小端机器上,这被存储在内存中为 0x01 0x00 0x00 0x00
,而在大端机器上,它被存储为 0x00 0x00 0x00 0x01
。
该表达式所做的是获取这些字节中的第一个字节,并检查它是否为 1
。
Little-endian
0x01000000 = 00000001000...00
Big-endian
0x00000001 = 0......01
char *
指针会返回一个字节。您的测试通过将地址解释为char *
并对其进行解引用来获取该内存位置的第一个字节。请注意保留HTML标记。0x80000000
作为内存中的字节地址吗? - Hunter McMillen2^31
。 - cnicutar分解*(char *)&x
:
&x
是整数x的地址
(char *)
将整数x的地址视为字符(也称为字节)的地址
*
引用字节的值
int x;
x
是一个可以容纳32位值的变量。
int x = 1;
1
以以下一种格式之一存储为32位
值。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
,那么它是小端序。如果从左到右的第四个字节存储值为00000001
,那么它是大端序。char x[]
或char *x
。 - Sangeeth Saravanaraj// 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))
是的,那回答了这个问题。这里有一个更一般性的答案:
#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;
}
这将显示c、c+1、c+2和c+3的解引用值,分别为8、4、2和1。 总和y为16909320,等于x。尽管数字的重要性从右到左增长,但这仍然是小端模式,因为相应的内存值也是从右到左增长的,这就是为什么左移二进制运算符<<会增加变量的值,直到非零数字被完全移出变量。不要将此运算符与std::cout的<<运算符混淆。 如果这是大端模式,那么c、c+1、c+2和c+3的显示将如下所示: 1 2 4 8