相关疑难解决方法(0)

是否有一些有意义的统计数据来证明保持未定义的有符号整数算术溢出是合理的?

C标准明确规定有符号整数溢出具有未定义的行为。然而,大多数CPU都使用定义的语义为溢出实现签名算法(可能除法除法溢出为:x / 0INT_MIN / -1)。

编译器的作家一直在走的优势undefinedness这种溢出的补充,往往会打破传统的代码非常微妙的方式更积极的优化。例如,此代码可能在较旧的编译器上有效,但在gccand的当前版本上不再有效clang

/* Tncrement a by a value in 0..255, clamp a to positive integers.
   The code relies on 32-bit wrap-around, but the C Standard makes
   signed integer overflow undefined behavior, so sum_max can now 
   return values less than a. There are Standard compliant ways to
   implement this, but legacy code is what it is... */
int sum_max(int a, unsigned char b) {
    int …
Run Code Online (Sandbox Code Playgroud)

c c++ signed integer-overflow language-lawyer

35
推荐指数
3
解决办法
812
查看次数

c/c++是否定义有符号整数除法的结果:负极值除以负1(INT_MIN/-1)

对于这种特殊情况,C 或 C++ 标准对有符号整数除法有何规定?它是否定义以及以何种方式定义?

INT_MIN / -1      (0x8000_0000 / 0xFFFF_FFFF)
Run Code Online (Sandbox Code Playgroud)

数学结果将是0x8000_0000无法用 32 位带符号 2 补码表示的正值。

c c++ language-lawyer

6
推荐指数
1
解决办法
179
查看次数

constexpr 中允许未定义的行为——编译器错误?

我的理解是:

  • C++ 中的有符号整数溢出是未定义的行为
  • 常量表达式不允许包含未定义的行为。

看来像下面这样的东西不应该编译,事实上在我的编译器上它不编译。

template<int n> struct S { };

template<int a, int b>
S<a * b> f()
{
  return S<a * b>();
}

int main(int, char **)
{
  f<50000, 49999>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,现在我尝试以下方法:

#include <numeric>

template<int n> struct S { };

template<int a, int b>
S<std::lcm(a, b)> g()
{
  return S<std::lcm(a,b)>();
}

int main(int, char **)
{
  g<50000, 49999>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

g++、clang 和 MSVC 都会愉快地编译它,尽管事实上

如果 |m|、|n| 或 |m| 的最小公倍数,则行为未定义 和|n| 不能表示为 type 的值 std::common_type_t<M, N> …

c++ undefined-behavior constexpr

6
推荐指数
1
解决办法
257
查看次数

mips 中的算术溢出

我刚刚开始学习 MIPS 指令的异常处理程序。

我需要使我的程序具有算术溢出异常,以便我可以测试我的异常处理程序。

我有两个数组 A 和 B。数组 A 有十六进制数,数组 B 有整数。

如何通过添加十六进制数和整数来使溢出?

哪些十六进制数和整数相加会导致溢出?

mips integer-overflow

5
推荐指数
1
解决办法
3万
查看次数

(int)(unsigned)-1 == -1 是未定义行为

我试图理解这句话的含义:

(int)(unsigned)-1 == -1;
Run Code Online (Sandbox Code Playgroud)

据我目前的理解,会发生以下事情:

  1. -1是一个有符号的 int并且被转换为无符号的 int。其结果是,由于环绕行为,我们获得了该类型可以表示的最大值unsigned

  2. 接下来,unsigned我们在步骤 1 中获得的这种类型最大值现在被转换为signed int。但请注意,该最大值是一个unsigned type。所以这超出了的范围signed type。并且由于有符号整数溢出是未定义的行为,因此程序将导致未定义的行为

我的问题是:

  1. 我上面的解释正确吗?如果不是,那么实际发生了什么。
  2. 这是我怀疑的未定义行为还是实现定义的行为。

PS:我知道如果它是未定义的行为(而不是定义的实现),那么我们不能依赖程序的输出。所以我们不能说我们是否总是会得到truefalse

c++ signed integer-overflow undefined-behavior c++11

3
推荐指数
1
解决办法
546
查看次数

int16_t如何表示大于32767且不翻转的数字

在 Arduino Uno 上运行的这段代码会打印递增的数字,并按预期从 32767 回绕到 -32768。

int16_t i = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  i++;
  Serial.println(i);
}
Run Code Online (Sandbox Code Playgroud)

然而,人们认为在功能上等效的这段代码不断打印超过 200000 个 16 位数字(有符号或无符号)应该能够表示的数字。

void setup() {
  Serial.begin(115200);

  int16_t i = 0;

  while(true) {
    i++;
    Serial.println(i);
  }
}

void loop() {}
Run Code Online (Sandbox Code Playgroud)

Arduino 参考中有关于数据类型的注释/警告int。这有关系吗?

当有符号变量超过其最大或最小容量时,它们就会溢出。溢出的结果是不可预测的,因此应该避免这种情况。溢出的典型症状是变量从最大容量“滚动”到最小容量,反之亦然,但情况并非总是如此。如果您想要这种行为,请使用 unsigned int。

第二个代码片段发生了什么?变量如何明显代表这么大的数字而不滚动?

c++ types arduino

1
推荐指数
1
解决办法
141
查看次数