12

我的理解是,在 C/C++ 中,位运算符应该是独立于字节序的,并且按照您期望的方式运行。我想确保我真正从 64 位值中得到最重要和最不重要的字,而不用担心机器的字节顺序。这是一个例子:

uint64_t temp;
uint32_t msw, lsw;
msw = (temp & 0xFFFFFFFF00000000) >> 32;
lsw = temp & 0x00000000FFFFFFFF;

这行得通吗?

4

8 回答 8

17

6.5.7 移位运算符

4 E1 << E2的结果是E1左移E2位;空出的位用零填充。如果 E1 具有无符号类型,则结果的值为 E1 × 2E2,比结果类型中可表示的最大值多模一减少。如果 E1 具有带符号类型和非负值,并且 E1 × 2E2 在结果类型中是可表示的,那么这就是结果值;否则,行为未定义。

所以,是的——由标准保证。

于 2010-02-03T18:25:26.910 回答
5

它会起作用,但是一些作者在位移位之前进行位掩码的奇怪倾向总是让我感到困惑。

在我看来,一种更优雅的方法是首先进行转变的方法

msw = (temp >> 32) & 0xFFFFFFFF; 
lsw = temp & 0xFFFFFFFF; 

至少因为它每次都使用相同的“神奇”位掩码常数。

现在,如果您的目标类型是无符号的并且已经具有所需的位宽,则完全不需要掩码

msw = temp >> 32; 
lsw = temp; 
于 2010-02-03T22:35:49.130 回答
3

是的,这应该有效。当您检索 msw 时,您的掩码并没有真正完成太多 - 无论如何,当您进行移位时,您掩码为零的位将被丢弃。就个人而言,我可能会使用这样的东西:

uint32_t lsw = -1, msw = -1;
lsw &= temp;
msw &= temp >> 32;

当然,要产生有意义的结果,temp必须进行初始化,这不在您的代码中。

于 2010-02-03T18:29:05.737 回答
2

是的。它应该工作。

于 2010-02-03T18:23:23.347 回答
1

字节序是关于内存布局的。移位是关于位(和位布局)。字的意义是关于位布局,而不是内存布局。所以字节序与单词的意义无关。

于 2010-02-03T22:38:40.407 回答
1

只是我想分享的一个想法,也许您可​​以通过使用中找到的函数或宏来绕过值的字节序,<arpa/inet.h>将网络转换为主机顺序,反之亦然,可以说它更多地结合使用到套接字,但它可用于此实例以保证来自另一个处理器的 0xABCD 之类的值在 Intel x86 上仍然是 0xABCD,而不是求助于手动编码的自定义函数来处理字节序架构......? !

编辑:这是CodeProject上关于 Endianess 的文章,作者开发了宏来处理 64 位值。

希望这会有所帮助,最好的问候,汤姆。

于 2010-02-03T18:52:12.533 回答
0

我认为你说的很对,但这对你有什么影响?

如果你有一些字面值,那么你就知道哪一端是哪一端。但是,如果您发现自己的值来自程序外部,那么您就无法确定,除非它们以某种方式进行了编码。

于 2010-02-03T18:27:02.680 回答
0

除了其他响应之外,我还要补充一点,您不应该担心 C 中的字节序问题。字节序问题仅来自于查看与最初用于写入这些字节的类型不同的某些字节。当你这样做时,你很容易遇到别名问题,这意味着你的代码在使用另一个编译器或另一个优化标志时可能会中断。

只要您不尝试进行此类跨类型访问,您的代码就应该是端中立的,并且可以在小端和大端架构上完美运行。或者,换句话说,如果你有字节序问题,那么其他更大的麻烦也潜伏在附近。

于 2010-02-03T20:45:55.673 回答