-1

我正在做一个非常微不足道的计算机科学作业,围绕 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”。它与十六进制数字有关吗?我一直无法在谷歌上找到任何东西。

4

4 回答 4

2

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

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

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

于 2014-01-22T20:46:02.503 回答
1

ORand运算符有AND两种形式,逻辑 ( || and &&) 和算术 ( | and &)。

逻辑OR并将AND返回bool结果。这些是您的“类英语”连词。

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

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

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因为它是 和 的按位运算OR,导致.0000 00010000 00100000 0011

于 2014-01-22T20:49:29.160 回答
1

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

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

于 2014-01-22T20:44:18.980 回答
0

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

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”来避免这些问题。

于 2014-01-22T23:41:15.380 回答