【问题标题】:Comparing results after integer promotion比较整数提升后的结果
【发布时间】:2018-07-30 12:51:40
【问题描述】:

以下情况:

我有用于将变量的补码连同其原始值一起存储在结构中的宏。使用另一个宏,我想检查原始值是否等于存储的补码值的补码。但奇怪的是,我没有得到预期的结果。 简化操作,结果如下:

#include <stdbool.h>
#include <stdint.h>
#define CHECKVAR(var__, compl__) ((var__^compl__)==-1);

int main()
{
uint8_t var;
uint8_t complementvar;

var=3;
complementvar=~var;

bool checkOK=CHECKVAR(var,complementvar); /*-> I expect that all bits are set and hereby it is equal to "-1", but instead i get "false" */

return 0;
}

我的期望是(例如在 32 位系统上:

  1. 在补码运算后complementvar 的值为0xfffffffc(在由 ~ 运算符引起的整数提升为 int 并通过隐式将左值强制转换为 uint8 将左值分配给 complementvar 之后)。
  2. 现在到检查宏: 按位运算导致双方的整数提升?:
    • 2a)。 var: 0000 0000 0000 0000 0000 0000 0000 0011; complementvar: 1111 1111 1111 1111 1111 1111 1111 1100
    • 2b)\ 现在对 var 和 Complementvar 进行异或运算会导致 1111 1111 1111 1111 1111 1111 1111 1111
  3. 与 -1 一起检查 XOR 运算的结果(表示为整数) 1111 1111 1111 1111 1111 1111 1111 1111==1111 1111 1111 1111 1111 1111 1111 1111 应为真,但我总是收到假,因为异或运算的结果(对我来说很奇怪)是 0x000000ff?

我使用的是什么编译器?它是 MSVC++11,但实际上解决方案应该尽可能独立于编译器。 由于我也必须是可移植的,所以使用 C 编译器的结果会有所不同吗?

【问题讨论】:

  • 我建议您阅读以下内容:stackoverflow.com/questions/10820340/…。即使这可能不是这里的问题。
  • @Scheff "虽然uint8_t 被提升为unsigned" uint8_t 被提升为int (因为int 总是可以代表uint8_t 的整个取值范围)。
  • 两个uint8_ts之间的操作可以将它们转换/提升为int,但没有符号扩展。 (cppreference: unsigned char 或 unsigned short 可以转换为 int 如果它可以保持其整个值范围,否则 unsigned int ;)所以,uint8_t ^ uint8_t 的结果是@ 987654342@ 即使0xff 的类型是(int) 并且不等于-1 至少是0xffff(如果sizeof (int) 只有2 个)。
  • 好的,现在我明白了。整数提升不会导致符号扩展。所以解决方案(如果我想使用 XOR 操作来避免像我在@FelixPalmen 的回答中所写的那样显式转换为“基本类型”)将检查UINT8_MAX 而不是-1
  • @mbed_dev 那么你当然会再次绑定到uint8_t

标签: c++ c integer bit-manipulation integer-promotion


【解决方案1】:

在补码运算之后,complementvar 的值为0xfffffffc

没有。看看那个代码:

uint8_t complementvar;
complementvar=~var;

~var 将评估为您期望的值,但 complementvar 的类型为 uint8_t,因此转换仅导致 0xfc

在您的检查步骤中,这再次提升为int,但由于uint8_t 是一个无符号 类型,此处不会发生符号扩展,您只需添加0 位。这解释了您从 xoring (^) 获得的结果。

【讨论】:

  • 实际上,您的版本的解决方案是#define CHECKVAR(var, compl) (((uint8_t)~var) == (compl))?,因为根据gccMSVC++11compl 上的补码运算符的结果是0xffffff00,因为补码运算符导致与符号扩展的结果相同
  • @mbed_dev 你是对的,该死的......我只会回滚我的编辑。我假设您希望您的宏与类型无关,我认为这是(有点聪明)的方式。不是:o
猜你喜欢
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
  • 2011-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 2012-08-25
相关资源
最近更新 更多