【问题标题】:Is subtraction and comparison with unsigned integers in C / C++ well defined? [duplicate]C/C++ 中与无符号整数的减法和比较是否定义良好? [复制]
【发布时间】:2017-12-28 22:44:32
【问题描述】:

作为问题"Is unsigned integer subtraction defined behavior?" 的扩展,我对以下行为感到困惑。

在下面的代码中,请注意 A = 50B = 100 存储为无符号 16 位整数和减法 A - B = -50 = 65486 (mod 2^16 - 1)。如果我将减法的结果存储在D(一个无符号的 16 位整数)中,然后计算D > 4000,我得到true,因为65486 > 4000. 这是有道理的。

如果我放弃存储A - B 并直接评估A - B > 4000,我会得到错误。这似乎不一致。这是预期的结果吗?为什么?这总是正确的行为还是我处于“未定义行为”的境地。

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

int main() {
  uint16_t A = 50;
  uint16_t B = 100;

  uint16_t D = A - B;     // D = 65486                                                                                        
  printf("D = %u\n", D);

  int R = D > 4000;       // R = 1 (true)                                                                                 
  printf("R = %d\n", R);

  int S = A - B > 4000;   // S = 0 (false)                                                                                
  printf("S = %d\n", S);

  return 0;
}

顺便说一句,这种行为似乎与this question 的代码中的行为相矛盾,这进一步让我感到困惑。如果我将上面的uint16_t 更改为uint32_t,我会得到

D = 4294967246
R = 1
S = 1

这对我来说似乎是正确的。

更新:似乎最好的详细答案是 uint16_t 被提升为 intint 在我的系统上是 32 位),所以 A - B &gt; 4000 完成了 已签名 算术。而当我切换到 uint32_t 时,没有执行任何提升(已经是 32 位宽),所以 A - B &gt; 4000 是使用 unsigned 算术完成的。这样就可以解释了。

附:我知道人们想第一个回答,但仅仅说“整数提升”并不是一个有用的答案。

【问题讨论】:

  • 整数促销。
  • 哪些整数促销?如果 A 和 B 提升为 32 位无符号整数,则 A - B > 4000 应该为真。如果将它们提升为带符号的整数,那就更没有意义了。具体有哪些促销活动?
  • herehere
  • 这取决于:int 您的系统是 32 位还是 16 位?你会得到不同的答案。
  • 如果 int/unsigned == 16,uint32_t 未被提升 - 仍然是 uint32_t。如果int/unsigned == 32,则uint32_t 提升为unsigned。如果int/unsigned == 64,则uint32_t 提升为int

标签: c++ c undefined-behavior


【解决方案1】:

如果我放弃存储 A - B 并直接评估 A - B > 4000,我会得到错误。这似乎不一致。

是的,粗略一看。

但是,当计算表达式 A-B 时,在执行减法之前,两者都被提升为 int。因此,A - B &gt; 5000 的计算结果为 false。

您可以在http://en.cppreference.com/w/c/language/conversion 阅读“常用算术转换”。

回复。 但是当我切换到unit32_t时呢​​m>:

当两个操作数都是unit32_t 类型时,在sizeof(int) 为4 而非int 的平台上,结果也是unit32_t 类型。

【讨论】:

  • 但是当我切换到unit32_t 时呢?那我也应该是假的!
猜你喜欢
  • 2017-07-27
  • 2011-11-05
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-30
相关资源
最近更新 更多