【问题标题】:Logical NOT operation not returning expected value in c?逻辑NOT操作未在c中返回预期值?
【发布时间】:2018-03-23 16:17:30
【问题描述】:

我正在尝试使用逻辑运算符在 0xAA 和 0x55 之间切换。

我知道我可以使用 c >> 1 从 0xAA 更改为 0x55,但是我被要求使用逻辑运算符而不是位运算符来执行此操作,所以我不知道使用 >> 运算符是否算数...

但我对使用 NOT 逻辑运算有点困惑。

我确定如果我说

unsigned char c = 0xAA;
unsigned char b = !c;

那么 b 将是 0x55。相反,我得到了 0 的输出。它不应该将每个单独的位切换到相反的位置,给我 0x55?

感谢您的帮助。

【问题讨论】:

  • 您混淆了“逻辑”而不是“按位”。尝试使用~ 运算符进行比较。
  • @Code-Apprentice 我也看到了。虽然我在这里有点困扰,因为 '~' 也是位运算符,而不是逻辑运算符。我是否应该假设我可以使用按位运算符?有没有办法用逻辑运算符做到这一点?
  • 您所问的正是按位 ~ 运算符的设计目的。合乎逻辑!运算符的工作方式不同,因为它仅适用于布尔值,“真”或“假”,而不适用于单个位。
  • 回到你的导师那里,问问他们你是哪些运营商,哪些是不被允许使用的。
  • @zwol 看起来我将不得不做那个 zwol。

标签: c bitwise-operators logical-operators


【解决方案1】:

相反,我得到了 0 的输出。

logical operatorsboolean values 一起使用:truefalse

C 语言将任何不是0 的标量值处理为true,将0 处理为falseLogical NOT operator (!) 将任何真实值(即不同于0)转换为false(即0)。


假设您可以使用算术运算符(加法、乘法、除法),您可以计算输入数字的每一位,使用逻辑非运算符更改其值,然后将这些位组合回一个数字,即按位非输入的数字。

例如,c 的最后一位是 c % 2,如果从数字中删除该位并且其他位移动以填充其位置,则剩余的数字是 c / 2(或 c >> 1 为你已经知道了。)

【讨论】:

    【解决方案2】:

    我正在尝试使用逻辑运算符在 0xAA 和 0x55 之间切换。

    这是一项艰巨的任务。使用逻辑运算符的表达式评估为真/假。祝你项目顺利。

    关于

    那么 b 将是 0x55。相反,我得到了 0 的输出。它不应该将每个单独的位切换到相反的位置,给我 0x55?

    这不是逻辑运算符! 所做的。如果其操作数非零,则计算结果为 0;如果其操作数为 0,则计算结果为 1

    【讨论】:

    • 使用逻辑运算符的表达式实际上计算为 0 或 1,然后将其解释为真/假。 0/1 实际上是解决 OPs 难题的关键。
    【解决方案3】:

    如果你真的必须只使用! 而不是~,我想到了一个可怕的hack。因为这是家庭作业,所以我不会向您展示整个 hack,只是其中的一部分:

    static_assert(CHAR_BIT == 8, "What is this, a PDP-10?");
    
    union {
      uint8_t val;
      struct {
        uint8_t b0 : 1;
        uint8_t b1 : 1;
        uint8_t b2 : 1;
        uint8_t b3 : 1;
        uint8_t b4 : 1;
        uint8_t b5 : 1;
        uint8_t b6 : 1;
        uint8_t b7 : 1;
      } bits;
    } u;
    

    我向你保证,通过这个变量声明和一个符合 C99+勘误表的 C 编译器,现在大多数(但不是全部)是,可以仅使用=! 运算符。

    【讨论】:

      【解决方案4】:

      正如@Code-Apprentice 所说,!不是正确的运算符,因为您正在执行数学非而不是逻辑非。但是,您的问题表明您要使用逻辑运算符,因此 ~ 运算符是不够的,因为它不是逻辑运算符。想一想逻辑运算和数学运算之间的区别。逻辑运算不执行算术运算,它们对布尔值进行运算。然后,您将如何使用逻辑 NOT、AND、OR、XOR 等来完成您的任务?您甚至可以先用铅笔和纸尝试手动执行此操作(提示:先将十六进制值转换为二进制)

      【讨论】:

      • “逻辑运算不进行算术运算”是什么意思?
      • 什么是你不能用 NOT、AND、OR、XOR 等做的“这个”?
      • 逻辑运算符使用布尔值。没有逻辑运算符可以为您提供 2 + 2 或 15 - 7。您只能通过布尔运算的结果来近似算术。这就是为什么微处理器中的 ALU 既有逻辑单元又有加法器的原因。布尔求值的逻辑单元和算术求值的加法器。
      【解决方案5】:

      第一行:

      c = 0xAA; 
      

      第二行时被视为“真”

      b = !c;
      

      被执行,并且not true 为假,因此b 设置为false I.E。 0

      需要注意的一点:位运算符与逻辑运算符不同。 ! 是逻辑运算符

      【讨论】:

      • 这不是第一行被视为真实的。当解释为逻辑值时,视为真值。
      • @PaulOgilvie,看来我的回答措辞不当,澄清一下:is seen as 'true' when the second line 行(我不清楚)在第二行引用了c 的内容跨度>
      【解决方案6】:

      我正在尝试使用逻辑运算符在 0xAA 和 0x55 之间切换。

      这是不可能的,因为逻辑运算符不是这样工作的。相反,您需要使用位运算符。

      正如您所说,! 是逻辑非运算符。它接受“真”值并返回“假”或“假”值并返回“真”。请注意,它会反转整个值,而不是单个位。在 C 中,0 被认为是“假”,任何非零数值都被认为是“真”。所以!0xAA 评估为0 因为0xAA 是“真”而0 是“假”。

      将此与~ 进行对比,后者是按位非运算符。 ~0xAA 将按照您的预期计算为 0x55,因为它会反转每个单独的位。

      【讨论】:

      • 这不是不可能的。事实上,这很容易做到。我可以放弃答案,但如果我只是破坏答案,OP 可能会错过更多了解逻辑运算符的机会。此外,OP 并没有询问如何用逻辑进行数学运算,也没有询问如何对其进行编码,他询问的是如何在两个离散值之间翻转。非常简单,只需要一个特定的逻辑运算符。
      猜你喜欢
      • 2023-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      相关资源
      最近更新 更多