- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是对问题的完全重写。希望现在更清楚了。
我想在 C 中实现一个执行 signed int
加法的函数s 带包装以防溢出。
我想主要针对 x86-64 架构,但当然实现越便携越好。我还主要关心通过 gcc、clang、icc 以及 Windows 上使用的任何东西生成体面的汇编代码。
目标是双重的:
leal
或单个
addl
在 native 支持操作的机器上的指令。
int add_wrap(int x, int y) {
return (unsigned) x + (unsigned) y;
}
unsigned int
的类型转换。至
signed int
,让实现自由(另见
here )。
Otherwise, if the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
unsigned
进行预期的转换至
int
,这意味着它们采用正确的代表模数 2^N,其中 N 是位数,但它不是标准规定的,因此不能依赖(愚蠢的 C 标准再次命中)。此外,虽然这是在二进制补码机上做的最简单的事情,但在补码机上是不可能的,因为有一个类是不可表示的:2^(N/2)。
__builtin_add_overflow
像这样
int add_wrap(int x, int y) {
int res;
__builtin_add_overflow(x, y, &res);
return res;
}
If possible, the result will be equal to mathematically-correct result and the builtin will return 0. Otherwise, the builtin will return 1 and the result will be equal to the unique value that is equivalent to the mathematically-correct result modulo two raised to the k power, where k is the number of bits in the result type.
These built-in functions promote the first two operands into infinite precision signed type and perform addition on those promoted operands. The result is then cast to the type the third pointer argument points to and stored there.
long int
至
int
是特定于实现的,所以我没有看到任何保证这会导致包装行为。
__builtin_add_overflow
规范的一部分。 .
#include <limits.h>
int add_wrap(int x, int y) {
if ((x > 0) && (y > INT_MAX - x))
return (x + INT_MIN) + (y + INT_MIN);
else if ((x < 0) && (y < INT_MIN - x))
return (x - INT_MIN) + (y - INT_MIN);
else
return x + y;
}
leal
与
gcc ,但不是
clang或
icc .
f
在这两种情况下都不好,
g
在这两种情况下都很好(
addl
+
jo
或
addl
+
cmovnol
)。不知道是不是
jo
优于
cmovnol
, 但函数
g
始终优于
f
.
#include <limits.h>
signed int f(signed int si_a, signed int si_b) {
signed int sum;
if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
return 0;
} else {
return si_a + si_b;
}
}
signed int g(signed int si_a, signed int si_b) {
signed int sum;
if (__builtin_add_overflow(si_a, si_b, &sum)) {
return 0;
} else {
return sum;
}
}
最佳答案
I'm not so sure because of the rules for casting from unsigned to signed
The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 and C11 6.3.1.3).
For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised.
关于c - 如何在C中实现包装signed int加法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59307930/
我是一名优秀的程序员,十分优秀!