对于特定需要,我在四个一字节字符中构建一个四字节整数,没有太多特别的东西(在我的小端平台上):
return (( v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
我知道存储在大端机器中的整数看起来像AB BC CD DE
而不是DE CD BC AB
的小端,虽然它会完全影响我的操作,因为我会错误地移动,或者它只会导致反向存储的正确结果并需要反转?
我想知道是否要为big-endian机器创建此函数的第二个版本来进行(但未知)位操作,或者可能使用ntonl相关函数,我不知道如果我的数字是是否正确。
您的建议是什么以确保兼容性,请记住我需要以这种方式形成整数?
答案 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 -
佩里