我试着理解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("");
}

出局
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

测验
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 !

问题
yolinux.com网站为BIG-ENDIAN宣布0x000001000040880!但我的电脑用的是小恩迪安,我想是英特尔程序
我从我的C应用程序和另一个网站hex2bin converter得到相同的值0x000001000040880。
__mingw_printf(…x%016llX…,…ll)也打印0x00001000004080,如您所见。
继yolinux网站之后,我暂时在输出中反转了我的“(小Endian)”和“(大Endian)”标签。
另外,一个正数的符号位必须是0,这是我的结果,也是yolinux结果的情况
如果我正确理解Endianness,只有字节被交换,而不是位,我的位组似乎被正确地反转了。
这只是yolinux.com上的一个错误,还是我遗漏了一个关于64位数字和C编程的步骤?

最佳答案

当您使用printf(和正确的格式说明符)打印某个“多字节”整数时,系统是小端还是大端并不重要。结果是一样的。
little和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;
}

输出:
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

所以我可以看到我在一个小小的endian机器上,因为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

现在是存储在最低地址上的MSB(最高有效字节,即12)。
要理解的重要一点是,这只与“多字节类型如何存储在内存中”有关。一旦整数从内存读取到内核中的寄存器中,寄存器将在小端机和大端机上保存格式为0x12345678的整数。

关于c - C,小端和大端的困惑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54548061/

10-12 22:10