[英]Simple bitwise manipulation for little-endian integer, in big-endian machine?
为了满足特定的需要,我在四个一个字节的字符中构建一个四字节整数,没有什么特别的(在我的小端平台上):
return (( v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
我知道存储在大端机器中的整数看起来像AB BC CD DE
而不是具有小端字节的DE CD BC AB
,尽管它会完全影响我的操作,因为我将错误地移动,或者它只会导致反向存储的正确结果需要反转吗?
我想知道是否要创建这个函数的第二个版本来为大端机器做(但未知)位操作,或者可能使用与ntonl相关的函数,我不清楚如何知道我的数字是否正确或不。
你有什么建议来确保兼容性,请记住我需要以这种方式形成整数?
只要您在价值水平上工作,无论您的机器是小端还是大端,您获得的结果都绝对没有区别。 即只要您使用语言级别的运算符(如示例中的|
和<<
),您将在任何平台上从上面的表达式获得完全相同的算术结果。 机器的字节顺序无法检测到,并且在此级别不可见。
当您需要关心字节顺序时,唯一的情况是在对象表示级别检查您正在使用的数据,即在其原始内存表示很重要的情况下。 您上面所说的“ AB BC CD DE
而不是DE CD BC AB
”具体是关于数据的原始内存布局。 这就像ntonl
这样的功能:它们将一个内存布局转换为另一个内存布局。 到目前为止,您没有表明实际的原始内存布局对您来说非常重要。 是吗?
同样,如果您只关心上述表达式的值 ,则它完全且完全独立于字节序。 基本上,当您编写不尝试访问和检查原始内存内容的C程序时,您根本不应该关心字节序。
虽然它会完全影响我的操作,因为我会错误地转移(?)
没有。
无论endian架构如何,结果都是相同的。 比特移位和twiddling就像常规算术运算一样。 小端和大端架构上的2 + 2
是否相同? 当然。 2 << 2
也是一样的。
当你直接处理内存时会出现小的和大的endian问题。 执行以下操作时,您将遇到问题:
char bytes[] = {1, 0, 0, 0};
int n = *(int*)bytes;
在小端机器上,n将等于0x00000001。 在大端机器上,n将等于0x01000000。 这是你必须交换周围的字节。
[为清楚起见重写]
ntohl
(和ntohs
等)主要用于将数据从一台机器移动到另一台机器。 如果你只是简单地在一台机器上操作数据,那么在没有任何进一步仪式的情况下进行位移是完全没有问题的 - 位移(至少在C和C ++中)是用乘法/除以2的幂来定义的,无论机器是big-endian还是little-endian,它的工作原理都是一样的。
当/如果您需要(至少可能)将数据从一台机器移动到另一台机器时,在发送之前使用htonl
通常是明智的,而在收到它时则使用ntohl
。 这可能完全是nops(在BE到BE的情况下),两个相同的转换相互抵消(LE到LE),或实际上导致交换字节(LE到BE或反之亦然)。
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 -
佩里
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.