C 中不同 int 宽度的按位运算符是否定义明确?

Are bitwise operators on different int widths in C well defined?

我想确保我理解如果两个不同宽度的整数彼此按位或运算会发生什么。最明智的选择是用零在左侧填充较小的那个。我写了一个小程序来测试这个。

看这个示例代码:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main(void)
{
    uint32_t foo = 0x00000000;
    uint8_t bar = 0xFF;
    printf("%"PRIu32"\n", (foo | bar));
    printf("%"PRIu32"\n", (bar | foo));
}

如果我猜对了,我应该会得到两次 255。当我 运行 这个时,我得到

255
255

这是可以安全依赖的预期且定义明确的行为吗?是否有 link 解释具有不同 int 宽度的位操作的所有行为?

根据 C11 标准,第 6.5.12 章,按位包含或运算符

Each of the operands shall have integer type.

The usual arithmetic conversions are performed on the operands.

所以,按位运算应该没问题。

但是,在 printf() 的情况下,%d 需要 int 参数,而您提供的是 unsigned int 值。即undefined behavior.

您可以使用 PRIu32 宏从 inttypes.h 打印 uint32_t

您的代码在幕后执行的操作可能与您预期的不同:

uint32_t foo = 0x00000000;
uint8_t bar = 0xFF;
printf("%zu\n", (foo | bar));

让我们假设类型 uint32_t 在您的系统上是 unsigned int。在这种情况下,表达式 (foo | bar) 由编译器按以下方式处理:

  • 首先,bar 被更改(提升)为类型 int(称为整数提升的过程)- 这根本不会改变其数学值 255。
  • 然后,结果int被转换为unsigned int,因为|的另一个参数是unsigned int类型。同样,数学值没有任何变化,它仍然是 255。
  • 最后,如你所料,结果是255,类型为unsigned int

供您查看的相关主题是 C 对整数提升和隐式转换规则的处理。