我试图理解 C 编程内存字节顺序,但我很困惑。我在此站点上尝试使用我的应用程序进行输出验证:www.yolinux.com/TUTORIALS/Endian-Byte-Order.html
对于我在 C 程序中使用的 64 位值:
volatile long long ll = (long long)1099511892096;
__mingw_printf("\tlong long, %u Bytes, %u bits,\t%lld to %lli, %lli, 0x%016llX\n", sizeof(long long), sizeof(long long)*8, LLONG_MIN, LLONG_MAX , ll, ll);
void printBits(size_t const size, void const * const ptr)
{
unsigned char *b = (unsigned char*) ptr;
unsigned char byte;
int i, j;
printf("\t");
for (i=size-1;i>=0;i--)
{
for (j=7;j>=0;j--)
{
byte = b[i] & (1<<j);
byte >>= j;
printf("%u", byte);
}
printf(" ");
}
puts("");
}
Run Code Online (Sandbox Code Playgroud)
出去
long long, 8 Bytes, 64 bits, -9223372036854775808 to 9223372036854775807, 1099511892096, 0x0000010000040880
80 08 04 00 00 01 00 00 (Little-Endian)
10000000 00001000 00000100 00000000 00000000 00000001 00000000 00000000
00 00 01 00 00 04 08 80 (Big-Endian)
00000000 00000000 00000001 00000000 00000000 00000100 00001000 10000000
Run Code Online (Sandbox Code Playgroud)
测试
0x8008040000010000, 1000000000001000000001000000000000000000000000010000000000000000 // online website hex2bin conv.
1000000000001000000001000000000000000000000000010000000000000000 // my C app
0x8008040000010000, 1000010000001000000001000000000000000100000000010000000000000000 // yolinux.com
0x0000010000040880, 0000000000000000000000010000000000000000000001000000100010000000 //online website hex2bin conv., 1099511892096 ! OK
0000000000000000000000010000000000000000000001000000100010000000 // my C app, 1099511892096 ! OK
[Convert]::ToInt64("0000000000000000000000010000000000000000000001000000100010000000", 2) // using powershell for other verif., 1099511892096 ! OK
0x0000010000040880, 0000000000000000000000010000010000000000000001000000100010000100 // yolinux.com, 1116691761284 (from powershell bin conv.) ! BAD !
Run Code Online (Sandbox Code Playgroud)
问题
yolinux.com网站公布0x0000010000040880为大端!但是我认为我的计算机使用 LITTLE Endian(Intel proc。)并且我从我的 C 应用程序和另一个网站 hex2bin 转换器获得相同的值 0x0000010000040880。__mingw_printf(...0x%016llX...,...ll) 也打印 0x0000010000040880,如您所见。
在 yolinux 网站之后,我暂时在输出中反转了“(Little-Endian)”和“(Big-Endian)”标签。
此外,对于正数,符号位必须为 0,这是我的结果也是 yolinux 结果的情况。(无法帮助我确定。)
如果我正确理解字节序,则只交换字节而不是位,并且我的位组似乎正确反转。
这只是 yolinux.com 上的一个错误,还是我遗漏了有关 64 位数字和 C 编程的步骤?
当您使用printf(和正确的格式说明符)打印一些“多字节”整数时,系统是小端还是大端都没有关系。结果将是相同的。
little endian 和 big endian 之间的区别在于多字节类型在内存中的存储顺序。但是一旦数据从内存读入核心处理器,就没有区别了。
此代码显示了如何将整数(4 个字节)放入我机器的内存中。
#include <stdio.h>
int main()
{
unsigned int u = 0x12345678;
printf("size of int is %zu\n", sizeof u);
printf("DEC: u=%u\n", u);
printf("HEX: u=0x%x\n", u);
printf("memory order:\n");
unsigned char * p = (unsigned char *)&u;
for(int i=0; i < sizeof u; ++i) printf("address %p holds %x\n", (void*)&p[i], p[i]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
size of int is 4
DEC: u=305419896
HEX: u=0x12345678
memory order:
address 0x7ffddf2c263c holds 78
address 0x7ffddf2c263d holds 56
address 0x7ffddf2c263e holds 34
address 0x7ffddf2c263f holds 12
Run Code Online (Sandbox Code Playgroud)
所以我可以看到我在一个小端机器上,因为 LSB(最低有效字节,即 78)存储在最低地址上。
在大端机器上执行相同的程序将(假设地址相同)显示:
size of int is 4
DEC: u=305419896
HEX: u=0x12345678
memory order:
address 0x7ffddf2c263c holds 12
address 0x7ffddf2c263d holds 34
address 0x7ffddf2c263e holds 56
address 0x7ffddf2c263f holds 78
Run Code Online (Sandbox Code Playgroud)
现在是存储在最低地址上的 MSB(最高有效字节,即 12)。
要理解的重要一点是,这仅与“多字节类型如何存储在内存中”有关。一旦整数从存储器中读取到核心内部寄存器,寄存器将持有的形式0x12345678的整数都很少和大端机。
| 归档时间: |
|
| 查看次数: |
1374 次 |
| 最近记录: |