【问题标题】:C bit-wise operations with hex numbers十六进制数的 C 位运算
【发布时间】:2015-03-30 07:32:04
【问题描述】:

有没有办法在 C 中访问十六进制数的某些部分?

我想编写一个函数,它接受一个十六进制数并将其取反,但保持最低有效字节不变。示例:0x87654321 应变为 0x789ABC21。

我试图以某种方式保存 LSB,然后将其应用于否定的 x,但我的问题是我的掩码被应用于所有字节。我可以将它硬编码为一个特定的值,但显然这不是我想要的。

void b(int x) {
  int temp = x & 0xFF; // temp is all 0 with the LSB being the same as x's
  x = ~x;  // this negates x
  // one of a couple of attempts I tried thus far:
  // x = (x & 0x00) | temp; 
  // idea: change x's LSB to 00 and OR it with temp, 
  // changing x's LSB to temp's LSB
}

如果您不发布解决方案的代码,我将不胜感激,而只是回答是否有办法将位操作应用于十六进制数的特定部分,或者我如何解决这个问题。

【问题讨论】:

  • 我对 C 不是很熟悉,那么 && 到底是做什么的呢?在 Java 或 C++ 中,这将是合乎逻辑的比较,但这在这里没有多大意义,不是吗?
  • x = (~x & ~0xFF) | (x & 0xFF);
  • 虽然我很欣赏指导性答案而不是一些代码,但我仍然很欣赏这一点。谢谢李,这确实有效。

标签: c hex


【解决方案1】:

我找到了一种操作选定字节的方法。 (!!!这将是 CS:APP 的作业 2.60 !!!)

如果 0x12345678 是给定类型的十六进制值,比如 int,那么这样做将允许我更改第 i 个字节:

int x = 0x12345678;
unsigned char* xptr = (unsigned char*) &x;
xptr[i] = 0; // say i=2, then this would yield: 0x120045678

现在,如果我想在字节 i 的位置添加一个值,比如 0xAB,我会做 luser droog 已经提到的:

int temp = 0xAB;
temp = temp << i*8; // say i=2, then this would yield: 0x00AB0000
x = x | temp; // this yields the desired result 0x12AB3456

【讨论】:

    【解决方案2】:

    通常,您可以使用 掩码 对值的特定位进行操作。

    掩码是位模式,在你想操作的地方是 1,在你不想操作的地方是 0。

    您似乎需要 3 个操作:提取最低字节、取反、恢复最低字节。你可以算出否定,所以我将只讨论提取一个位域和恢复一个提取的位域。

    要提取指定位,请对所需位使用带 1 的掩码,并使用按位 and 运算符&amp;and 运算符为掩码的所有 0 设置 0,如果掩码为 1,它会从另一个参数复制位。如果您需要在程序的其他地方检查此值,也可以方便地将 &gt;&gt; 值右移到最低位置(这样更容易在表格中查找)。

    要恢复保存的位,如果您之前将其向下移动,请向上移动。然后从值中清除这些位,并使用 inclusive-or | 作为所有位的按位和。要清除值中的位,请使用第一次操作中的掩码的反转。 IE。 y = x &amp; 0xf 保存一个 nibble,x &amp; ~0xf 清除该 nibble,(x &amp; ~0xf) | y 重新组合成相同的原始 x。

    编辑: 如果您要提取的部分不在最低位置,例如来自 32 位无符号整数的第二个字节 (LSB),那么将提取的值移到零位置以使用它可能会很有用。

    x = 0x12345678;
    y = x & 0xFF00;  // == 0x5600
    y >>= 8;         // == 0x56
    

    但是,如果您这样做,那么您必须将其移回正确的位置(当然),然后才能使用位域的新值更新较大的值。

    x = (x & ~0xFF00) | (y << 8);
    

    【讨论】:

    • 我知道这一点,但正如我所说,我的掩码会应用于所有位。
    • 掩码是通过控制二进制运算的真值表来选择应用哪些位的工具。
    • 好的。我确实让它与你的方法一起工作 - 好吧,基本上我做了和 Lee Daniel Crocker 已经建议的一样的事情。虽然我不太了解右移的部分。您能否详细说明一下,或者举个小例子?
    • @Beko 编辑了更多关于转移的内容。
    【解决方案3】:

    如果我正确理解了这个问题,似乎会​​是这样的(未经测试)。

    void b(int x) {
      return (~x & ~0xFF) | (x & 0xFF);
    }
    

    【讨论】:

    • 他说的是LS byte,而不是bit,而且你的代码依赖于32位整数,所以你的常量应该是~0xFF和@ 987654323@.
    • @LeeDanielCrocker:错过了它是字节而不是位。已更新。
    • 该死,浪费我的时间遵循I'd appreciate if you don't post code for the solution的指示
    • 不,你没有。只是你最初的答案不太对。
    • 好的。很抱歉抱怨。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 2012-09-12
    • 2016-09-06
    • 2015-11-10
    • 2013-06-12
    • 2013-06-26
    • 2016-06-12
    相关资源
    最近更新 更多