【问题标题】:C Bitwise OR returns "f"C 按位或返回“f”
【发布时间】:2014-01-22 20:40:21
【问题描述】:

我正在围绕 C 中的位运算符做一个非常微不足道的计算机科学作业,但我遇到了一个问题,我不知道为什么会发生这种情况。这是我正在运行的代码。

    #include <stdio.h>

int main(int argc, char *argv[]){
    int bitPattern1 = 0x10011001;
    int bitPattern2 = 0x01100110;
    int bitPattern3 = 0xFFFFFFFF;
    int bitPattern4 = 0x00000000;

    /* pair 1 */
    printf("bitPattern1 &  bitPattern2 = %x\n", bitPattern1 &  bitPattern2);
    printf("bitPattern1 && bitPattern2 = %x\n", bitPattern1 && bitPattern2);

    /* pair 2 */
    printf("bitPattern1 |  bitPattern2 = %x\n", bitPattern1 |  bitPattern2);
    printf("bitPattern1 || bitPattern2 = %x\n", bitPattern1 || bitPattern2);

    /* pair 3 */
    printf("bitPattern1 &  bitPattern3 = %x\n", bitPattern1 &  bitPattern3);
    printf("bitPattern1 && bitPattern3 = %x\n", bitPattern1 && bitPattern3);

    /* pair 4 */
    printf("bitPattern1 |  bitPattern3 = %x\n", bitPattern1 |  bitPattern3);
    printf("bitPattern1 || bitPattern3 = %x\n", bitPattern1 || bitPattern3);

    /* pair 5 */
    printf("bitPattern2 &  bitPattern4 = %x\n", bitPattern2 &  bitPattern4);
    printf("bitPattern2 && bitPattern4 = %x\n", bitPattern2 && bitPattern4);

    /* pair 6 */
    printf("bitPattern2 |  bitPattern4 = %x\n", bitPattern2 |  bitPattern4);
    printf("bitPattern2 || bitPattern4 = %x\n", bitPattern2 || bitPattern4);

    return 0;
} 

问题发生在第 4 对的第一部分,它返回以下结果:

bitPattern1 |  bitPattern3 = ffffffff
bitPattern1 || bitPattern3 = 1

为什么按位运算符返回“f”我查看了文档,虽然 OR 运算符返回 1 或零,但该示例似乎应该返回“11111111”。它与十六进制数字有关吗?我在谷歌上找不到任何东西。

【问题讨论】:

  • 这个问题似乎离题了,因为它对初等数学缺乏最基本的理解。
  • 1111 二进制 == F 十六进制

标签: c bitwise-or


【解决方案1】:

首先,OR 的输入是十六进制的FFFFFFFF,这意味着在二进制(按位)术语中它是11111111111111111111111111111111。 IE。 1s 比您引用的要多得多(准确地说是 32 位)。

其次,所讨论的按位 OR 确实应该以 binary 表示法返回 1111111...1。这正是它返回的结果。但是,当您以 hex 表示法打印结果时,您会得到FFFFFFFF。您在printf 中使用x 格式说明符明确请求十六进制表示法。

不幸的是,printf 没有用于生成二进制表示法的格式说明符。但是,将十六进制转换为二进制是一项微不足道的任务,因为它是用四个二进制数字直接替换每个十六进制数字。 F 代表 1111,所以您可以看到,按位计算,您的 OR 确实产生了 11111111111111111111111111111111,正如它应该的那样。

【讨论】:

  • 是的,我现在明白为什么会这样了,非常感谢。我忘了它是以十六进制表示的。
【解决方案2】:

位运算符对参数中的所有位进行操作,在执行操作时将每个位与其对应的位匹配。由于您分配了bitPattern3 = 0xFFFFFFFF,因此所有 32 位都打开,因此对它(|)进行按位或运算将使所有位都打开。

逻辑或 (||) 会将参数视为真/假,并对它们执行简单的 OR 运算,返回真/假值

【讨论】:

    【解决方案3】:

    ORAND 运算符有两种形式,逻辑 (|| and &amp;&amp;) 和算术 (| and &amp;)。

    逻辑ORAND 将返回bool 结果。这些是你的“类英语”连词。

    算术 ORAND 在位级别上工作,对每个相应的位进行联合。

    在前一种逻辑比较 (|| and &amp;&amp;) 的情况下,您通常会比较布尔值。例如:

    bool shouldUpdate = (hasNetworkConnection && isNewerVersionAvailable);
    bool isDifferentLocation = (location.X != this.X || location.Y != this.Y);
    

    对于后一种算术比较,通常使用enum 的值来完成Flags,如下所示:

    [Flags]
    enum AccessModeFlags
    {
      None = 0x0,
      Read = 0x1,
      Write = 0x2,
      ReadWrite = Read | Write
    }
    

    在这种情况下,ReadWrite0x3,因为它是0000 00010000 0010 的按位OR,导致0000 0011

    【讨论】:

      【解决方案4】:

      这与您的问题无关,但以下几行:

      int bitPattern1 = 0x10011001;
      int bitPattern3 = 0xFFFFFFFF;
      

      导致实现定义的行为或引发实现定义的信号,因为值 0x10011001 和 0xFFFFFFFF 超出了“int”的范围,假设您使用的是 32 位整数。

      重要的是要理解,当您编写这些行时,您并没有明确地将该位模式存储在变量中。您将 VALUE 4294967295 存储在变量中,编译器可以选择用于存储该值的位模式。它可以做任何它喜欢做的事情,只要你访问你所输入的值就可以了——尽管为了简单起见,现在的计算机几乎都使用二进制补码表示。

      在这种情况下,int 的最大值是 2147483647,因此您的分配超出了范围。但是 GCC 决定通过猜测您打算分配导致二进制补码表示 FFFFFFFF 的任何值来处理这个问题。其他编译器此时可以中止程序,但仍符合 C 标准。

      此外,您将“int”s 传递给 %x,如果 int 为负数,则会导致未定义的行为。 "%x" 需要一个 "unsigned int"。

      您可以通过将所有“int”更改为“unsigned int”来避免这些问题。

      【讨论】:

        猜你喜欢
        • 2011-02-25
        • 1970-01-01
        • 1970-01-01
        • 2017-04-09
        • 2013-07-22
        • 1970-01-01
        • 2021-06-13
        • 1970-01-01
        • 2021-07-05
        相关资源
        最近更新 更多