这个C函数在运行时找到机器的字节顺序有什么问题?

sig*_*ice 8 c endianness

这就是我今天在接受采访时提出的.

int is_little_endian(void)
{
    union {
        long l;
        char c;
    } u;

    u.l = 1;

    return u.c == 1;
}
Run Code Online (Sandbox Code Playgroud)

我的面试官坚持认为c并且l不能保证在同一地址开始,因此,应该改变联盟说,char c[sizeof(long)]并且应该将返回值更改为u.c[0] == 1.

工会成员可能不会在同一地址开始是否正确?

Sin*_*nür 8

我对工会成员不确定,但是他们来救援了.

检查可以更好地写为:

int is_bigendian(void) {
    const int i = 1;
    return (*(unsigned char*)&i) == 0;
}
Run Code Online (Sandbox Code Playgroud)

顺便提一下,C FAQ显示了两种方法:如何确定机器的字节顺序是big-endian还是little-endian?

  • @Chris:char实际上是标准中的一个特例,作为访问其他类型的底层表示的一种方式. (4认同)
  • 如果不确定我会感到惊讶; 否则memcpy和大多数序列化代码将如何工作? (2认同)
  • @Chris我相信你已经逆转了.从`char*`转换为`int*`会导致未定义的行为.我有一份WG14/N1124草案的副本,如果事情从那时起没有改变:*当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节.*(第47页,http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf) (2认同)
  • @CHris:"毛茸茸的指针演员",又名原始内存重新解释,通常是UB,*除了*,如果你把它重新解释为一个字符数组.后者在C中明确允许.但是,当使用`char`(而不是`unsigned char`)时,你可以用重新解释的内存做的事情是有限的.上面的代码通常是UB,因为通过这样的`char*`指针读取值是UB - 该值可能是陷阱表示.正确的代码应该使用强制转换为`unsigned char*`. (2认同)

D.S*_*ley 6

你是正确的,因为"工会成员可能从同一地址开始".该标准的相关部分是(6.7.2.1第13段):

联合的大小足以包含其最大的成员.最多一个成员的值可以随时存储在union对象中.指向适当转换的union对象的指针指向其每个成员(或者如果成员是位字段,则指向它所在的单位),反之亦然.

基本上,联合的起始地址保证与其每个成员的起始地址相同.我相信(仍在寻找参考)a long保证大于a char.如果你假设这个,那么你的解决方案应该*有效.

*由于围绕整数表示的一些有趣的措辞,特别是有符号整数类型,我仍然有点不确定.仔细阅读6.2.6.2第1和第2条.