C、小端和大端混淆

Eph*_*ral 0 c endianness

我试图理解 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 编程的步骤?

438*_*427 5

当您使用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的整数很少和大端机。