【问题标题】:Why does this code for incrementing an uint8_t include `& 0xFF`?为什么这个增加 uint8_t 的代码包含`& 0xFF`?
【发布时间】:2015-04-04 01:34:29
【问题描述】:

在阅读 Xilinx 的一些 DMA 示例代码时,我发现了这段代码:

value = (value + 1) & 0xFF

其中 value 是一个 uint8_t。

& 0xFF 的意义何在?为什么不直接写value = value + 1

【问题讨论】:

  • 看起来像一个以前被编译器烧过的经验丰富的程序员。即使后来有人出现并更改了 uint8_t 或更改了 uint8_t 的定义,该代码仍然有效......
  • 或者使用uint8_t之前编写的代码工件。
  • 那个编码员正在寻找我们。他/她明确表示value 是一个 8 位值,我们甚至不必去寻找声明。

标签: c


【解决方案1】:

我的猜测是,即使value不是 1 字节(8 位)类型,这段代码也能正常工作。位掩码0xFF 确保只保留值的最后一个字节。

【讨论】:

  • 1 字节我猜你的意思是 8 位。那个程序员很可能过去被一个非 8 位的 char 咬过,后来他把 char 改成了 uint8_t 但保留了掩码。
  • @user3528438:是的,我也认为发生了这样的事情。但我们可能永远不会知道...
  • 在赋值期间转换回uint8_t 已经确保只保留值的最后一个字节。所以我不相信这个答案是正确的。更有可能的是,屏蔽是为了消除由整数提升引起的编译器警告。看我的回答。
  • @Lundin :掩码不会抑制警告,赋值右侧的表达式类型是int。您需要显式强制转换来抑制警告(如果您有警告的话;静态分析工具当然可以生成警告,但大多数编译器不会)。无论值的整数类型如何,掩码都能确保预期值,这可能会在维护期间发生变化..
  • @Clifford 我知道至少有一个编译器(Freescale Codewarrior)会发出这样的警告,你可以在那个编译器上用 0xFF 掩码解决它。因为编译器可以判断该值永远不会大于 255,因此优化了整个整数提升。编译器不需要执行整数提升,只要它可以推断出省略提升不会影响程序的行为。
【解决方案2】:

当您想避免implicit type promotions 出现问题时,或者当您只是想证明您在编写代码时考虑了隐式提升时,这种代码很常见,这是一种良好的编程习惯。

uint8_t 是一个小整数类型,因此无论何时在表达式中使用它时都始终提升为int(value + 1) 的结果总是int

如果没有屏蔽,一些编译器会给出警告,例如“试图将 int 存储在 uint8_t 中”。我在几个编译器上遇到过这样的警告。理论上int & 0xFF 仍然是一个 int,但由于它的值不能大于 0xFF,编译器很可能能够将类型优化到 uint8_t,警告就会消失。

或者,您可以编写 value = (uint8_t)(value + 1u);,其含义相同(但它是代码的 MISRA-C 兼容版本)。

【讨论】:

  • 为了完整起见,这称为“应用掩码”。通过使用 0xFF (255) 执行“逻辑与”操作,您将关闭任何会使值大于掩码的位。因此,这充当递增值,如果溢出此值,则将其重置为 255。
  • @user2010913 你的意思是 0,而不是 255。
  • @Quentin,0xFF 是 255,如果值溢出 255,它将始终是 255(不是 0)
  • @user2010913 如果值达到 0x100 (256),则 1 将被切断,因此它会返回 0。还是我疯了?
  • @user2010913 这完全不正确......它是按位/二进制 AND。十进制值没有任何意义,它只是掩盖了该值的 8 个最低有效位。如果八个 lsb 值中的任何一个是二进制值,它们将被保留。如果 8 个 lsb 之外有任何二进制,它们将被丢弃。这(应该)是非常基本的东西......不需要解释,你应该能够安全地假设 C 程序员理解二进制算术。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-23
  • 2012-05-14
  • 1970-01-01
  • 2017-01-10
  • 2011-08-31
  • 1970-01-01
  • 2015-03-12
相关资源
最近更新 更多