在big-endian机器中对little-endian整数进行简单的按位操作?

时间:2011-04-12 23:57:26

标签: c binary integer bit-manipulation endianness

对于特定需要,我在四个一字节字符中构建一个四字节整数,没有太多特别的东西(在我的小端平台上):

    return (( v1 << 24) | (v2 << 16) | (v3 << 8) | v4);

我知道存储在大端机器中的整数看起来像AB BC CD DE而不是DE CD BC AB的小端,虽然它会完全影响我的操作,因为我会错误地移动,或者它只会导致反向存储的正确结果并需要反转?

我想知道是否要为big-endian机器创建此函数的第二个版本来进行(但未知)位操作,或者可能使用ntonl相关函数,我不知道如果我的数字是是否正确。

您的建议是什么以确保兼容性,请记住我需要以这种方式形成整数?

4 个答案:

答案 0 :(得分:8)

只要您在级别工作,无论您的计算机是小端还是大端,您获得的结果都绝对没有区别。即只要您使用语言级别的运算符(例如示例中的|<<),您就可以在任何平台上获得与上述表达式完全相同的算术结果。机器的字节顺序无法检测到,并且在此级别不可见。

当您需要关心字节顺序时,唯一的情况是在对象表示级别检查您正在使用的数据时,即在其原始内存表示很重要的情况下。您上面所说的关于“AB BC CD DE而不是DE CD BC AB”的内容具体是关于数据的原始内存布局。这就像ntonl这样的功能:它们将一个内存布局转换为另一个内存布局。到目前为止,您没有表明实际的原始内存布局对您来说非常重要。是吗?

同样,如果您只关心上述表达式的,那么它完全且完全与字节顺序无关。基本上,当您编写不尝试访问和检查原始内存内容的C程序时,您根本不应该关心字节序。

答案 1 :(得分:3)

  

虽然它会完全影响我的操作,因为我会错误地移动(?)

没有

无论endian架构如何,结果都是相同的。比特移位和twiddling就像常规算术运算一样。小端和大端架构上的2 + 2是否相同?当然。 2 << 2也是一样的。

当您直接处理内存时会出现小的和大的endian问题。执行以下操作时,您将遇到问题:

char bytes[] = {1, 0, 0, 0};
int n = *(int*)bytes;

在小端机器上,n将等于0x00000001。在大端机器上,n将等于0x01000000。这是你必须交换字节的时候。

答案 2 :(得分:1)

[为清晰起见重写]

ntohl(和ntohs等)主要用于将数据从一台机器移动到另一台机器。如果你只是简单地在一台机器上操作数据,那么在没有任何进一步仪式的情况下进行位移是完全没有问题的 - 位移(至少在C和C ++中)是用乘法/除以2的幂来定义的,无论机器是大端还是小端,它的工作原理都是一样的。

当/如果您需要(至少可能)将数据从一台计算机移动到另一台计算机时,在发送之前使用htonl通常是明智的,而在收到它时ntohl通常是明智的。这可能完全是nops(在BE到BE的情况下),两个相同的转换相互抵消(LE到LE),或者实际上导致交换字节(LE到BE,反之亦然)。

答案 3 :(得分:1)

FWIW,我认为这里所说的很多内容都是正确的。但是,如果程序员在编写时考虑了字节顺序,比如使用掩码进行按位检查和操作,则跨平台结果可能会出乎意料。

您可以在运行时确定'endianness',如下所示:

#define LITTLE_ENDIAN 0
#define BIG_ENDIAN    1

int endian() {
    int i = 1;
    char *p = (char *)&i;

    if (p[0] == 1)
        return LITTLE_ENDIAN;
    else
        return BIG_ENDIAN;
}

......然后继续进行。

我从这里借用了代码片段:http://www.ibm.com/developerworks/aix/library/au-endianc/index.html?ca=drs-其中也对这些问题进行了很好的讨论。

hth -

佩里