为什么这种检测机器存储方式的方法不正确? (使用C语言)

Why this way to detect machine storage methods is incorrect? (Using C language)

我做作业的时候漏掉了一个问题

计算机内存中存储数据的地方有大端存储和小端存储两种方式,为了检测某台机器的存储方式,某同学写了如下程序:

union NUM {
    int a;
    char b;
} num;

int main(){
    num.b = 0xff;
    if (num.a! = 0xff)
        printf ("bigend");
    else 
        printf ("smallend");
    return 0;
}

但是他在x86机器上发现了程序运行,打印出来居然是'bigend',这显然是错误的。你知道问题出在哪里吗? 这个程序应该怎么修改?

问过老师,题目是对的。我在一些网站上找到了一些信息,但它让我更加困惑。为什么这个问题没有错?问题究竟出在哪里?

假设 int(因此整个联合)是 4 个字节,写入 num.b 只会写入这 4 个字节中的一个,其余未初始化。随后读取 num.a 读取那些未初始化的字节,调用 undefined behavior.

union中的字节必须设置为全0,这样内容才能明确定义。

#include <stdio.h>
#include <string.h>

union NUM {
    int a;
    char b;
} num;

int main(){
    // set all bytes of num to 0 first
    memset(&num, 0, sizeof(num));
    num.b = 0xff;
    if (num.a! = 0xff)
        printf ("bigend");
    else 
        printf ("smallend");
    return 0;
}

类型双关在 C 中是未定义的行为。当您阅读 num.a 时,您违反了严格的别名规则,因此允许编译器生成可能返回任何内容的代码。它是做什么的。

要避免这种情况,您需要使用 memcpy():

int a = 0x00010203;
char bytes[sizeof(a)];
memcpy(bytes, &a, sizeof(a));
if(bytes[0] == 03) {
    printf("small endian\n");
} else ...