【问题标题】:Does the result of bitwise operations depend on endianess in Java? What about in C or C++?按位运算的结果是否取决于 Java 中的字节顺序?在 C 或 C++ 中呢?
【发布时间】:2014-08-27 14:50:22
【问题描述】:

考虑以下代码:

long store;
int firstValue = 0x1234;
int secondValue = 0x5678;
store = (((long) firstValue) << 32) | secondValue;

无论机器的字节序如何,store 是否保证具有 0x12345678 的值...

  • 在 Java 中?
  • 在 C 或 C++ 中?

【问题讨论】:

    标签: java c++ c bitwise-operators endianness


    【解决方案1】:

    所有这些语言中的移位操作都对数字进行操作。字节顺序不是数字的属性。

    在 Java 中,store 保证具有 0x123400005678L 的值,因为 0x1234L &lt;&lt; 320x123400000000L

    在 C 和 C++ 中,store 不保证具有任何特定值:结果取决于所涉及类型的大小,并且由于溢出,它可能具有未定义的行为(long 允许与32 位,在一些主流实现中确实如此)。如果没有溢出,则结果与 Java 相同。

    【讨论】:

    • 我的意思是长变量的 32 位移,我已经编辑了修复错误的问题。谢谢
    • C 中的 AFAIK 甚至没有由语言定义不属于 0
    • @Durandal 关于C,您是在谈论溢出吗?关于Java,那是相当挑剔的。如果我删除反引号可以吗(它不再是代码,现在我们回到数字而不是 Java 文字:P)?
    • C 根本没有定义实际使用了多少移位计数的最低位。 int32 i = 1;我 说 它给出的价值:)
    • 未定义的行为不就是这个意思吗?
    【解决方案2】:

    我假设您的意思是移动 16 位而不是 32 位以获得0x12345678。在 Java 和大多数 C/C++ 实现中,移位 32 会溢出。

    这是有保证的,并且与字节顺序无关。字节序决定了多字节值如何存储在内存中,而不是哪些位在逻辑上位于值中的哪个位置。左移 N 位总是等价于乘以 2N

    【讨论】:

    • 我的意思是长变量的 32 位移,我已经编辑了修复错误的问题。谢谢
    • @Trollkemada:在这种情况下,Java 中的结果至少是0x123400005678;在 C/C++ 中,long 不能保证那么大。
    【解决方案3】:

    字节顺序无关紧要,尽管机器使用一个补码还是二进制补码都可以。

    • 在 C 中,&lt;&lt; 不受影响,因为它是根据算术运算(乘法和求幂)定义的。
    • 在 Java 中,&lt;&lt; 不受影响,因为它是根据算术运算(乘法、求幂、加法、算术求反和减法)定义的。
    • 在 C 中,| 是根据底层位定义的。字节序不会产生任何影响,但它在一个补码机器上的表现可能与在一个补码机器上的表现不同。
    • 在 Java 中,| 不受影响,因为 Java 整数始终是二进制补码。

    我认为 C++ 与 C 相同。

    【讨论】:

    • 如果你改变内部表示,乘以 2 的幂不会停止表现不同:作为一个简单的演示,“3 * 16”的值与“三乘以十六”的值相同”。我使用“3”或“三”并没有使它成为不同的数字。
    • @mafso 这是一个溢出(即乘法导致的数字大于结果类型中可表示的最大数字)。不需要涉及“符号位”之类的东西。
    • C11 (n1570) 6.5.7 p.5 “E1 &lt;&lt; E2 的结果是E1 左移E2 位位置;空出的位用零填充。[...]如果 E1 具有带符号类型和非负值,并且 E1 × 2**E2 在结果类型中是可表示的,那么这就是结果值;否则,行为未定义。"
    • @mafso,更新答案。
    猜你喜欢
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 2019-02-07
    • 1970-01-01
    • 2013-10-05
    • 2021-05-08
    相关资源
    最近更新 更多