是否有任何有效且可移植的方法来检查C中的int64_t或uint64_t操作数的乘法运算何时溢出?
例如,为了添加uint64_t,我可以这样做:
if (UINT64_MAX - a < b) overflow_detected();
else sum = a + b;
Run Code Online (Sandbox Code Playgroud)
但我无法得到一个类似的简单表达式来进行乘法运算.
所有发生在我身上的是将操作数分解为高和低uint32_t部分,并在检查溢出时执行这些部分的乘法,这些东西真的很难看,也可能效率低下.
更新1:添加了一些实现多种方法的基准代码
更新2:添加了Jens Gustedt方法
基准程序:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define N 100000000
int d = 2;
#define POW_2_64 ((double)(1 << 31) * (double)(1 << 31) * 4)
#define calc_b (a + c)
// #define calc_b (a + d)
int main(int argc, char *argv[]) {
uint64_t a;
uint64_t c = 0;
int o = 0;
int opt;
if (argc != 2) …Run Code Online (Sandbox Code Playgroud) 我正在做两个涉及atoi的操作,我想知道如何使用无符号整数来执行此操作,因为atoi似乎将这些转换为signed会导致循环整数溢出.我想使用32位无符号整数,但atoi有效地将我限制为31位无符号.
if (multiplication_is_safe(atoi(argv[1]),atoi(argv[3])))
{
printf("%s * %s = %u \n", argv[1], argv[3], atoi(argv[1]) * atoi(argv[3]));
return 0;
} else
Run Code Online (Sandbox Code Playgroud) 什么是整数溢出错误?为什么我关心这样的错误?有哪些避免或预防方法?
在下面的程序中,第5行确实提供了 预期的溢出警告,但令人惊讶的是,第4行在GCC中没有给出任何警告:http://www.ideone.com/U0BXn
int main()
{
int i = 256;
char c1 = i; //line 4
char c2 = 256; //line 5
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在想这两行应该给出溢出警告.还是有什么我想念的?
导致我做这个实验的主题是:typedef类型检查?
在那里我说了以下(我从我的答案中删除了,因为当我运行它时,它没有像我预期的那样出现):
//However, you'll get warning for this case:
typedef int T1;
typedef char T2;
T1 x = 256;
T2 y = x; //possible overflow warning! (but it doesn't give warning :()
Run Code Online (Sandbox Code Playgroud) 在C99中,有一些(可选的)类型int8_t,int16_t例如,它们保证具有精确指定的宽度和没有填充位,并且表示二进制补码(7.18.1.1)中的数字.在6.2.6.2中,有符号整数溢出被提及为脚注44)和45),即它可能导致在填充位中捕获值.
由于intN_t没有任何填充位,并且它们保证是两个补码,这是否意味着它们的溢出不会产生任何未定义的行为?什么是例如溢出乘法的结果?添加怎么样?2^N对于无符号类型,结果是否减少了模数?
我正在构建一个Lisp,如果计算会导致它们溢出,我希望32位整数自动切换到64位整数.同样,对于64位溢出,切换到任意大小的整数.
我遇到的问题是我不知道检测整数溢出的"正确"方法是什么.
a, b := 2147483647, 2147483647
c := a + b
Run Code Online (Sandbox Code Playgroud)
如何有效地检查c是否溢出?
我已经考虑过总是转换为64位值来进行计算,然后在可能的情况下再次调整大小,但这对于像基本算术一样原始和核心的东西来说似乎很昂贵且内存浪费.
我正在为MATLAB/Octave中的一些VHDL代码开发一个验证工具.因此,我需要生成"真正"溢出的数据类型:
intmax('int32') + 1
ans = -2147483648
Run Code Online (Sandbox Code Playgroud)
稍后,如果我可以定义变量的位宽,那将会很有帮助,但现在这不是那么重要.
当我构建一个类似C的例子时,变量增加直到它小于零,它会永远旋转:
test = int32(2^30);
while (test > 0)
test = test + int32(1);
end
Run Code Online (Sandbox Code Playgroud)
我尝试的另一种方法是自定义"溢出" - 例程,每次更改数字后都会调用它.这种方法非常缓慢,不实用,根本不适用于所有情况.有什么建议?
可能重复:
添加两个字符会产生int
给出以下C++代码:
unsigned char a = 200;
unsigned char b = 100;
unsigned char c = (a + b) / 2;
Run Code Online (Sandbox Code Playgroud)
逻辑上预期输出为150 ,但表达式中(a + b)是否应该存在整数溢出?
显然必须有一个整数提升来处理这里的溢出,或者其他一些我无法看到的事情.我想知道是否有人可以启发我,所以我可以知道它是什么,我不能依赖于整数提升和溢出.
我在C规范中读到一点,无符号变量(特别是unsigned short int)执行一些所谓的整数溢出回绕,虽然我找不到任何有符号变量,除了我留下未定义的行为.我的教授告诉我他们的价值观也被包围了.(也许他只是意味着gcc)我认为这些位被截断了,我留下的位给了我一些奇怪的价值?!那么,任何人都可以解释什么是环绕的,它与仅截断位有什么不同.
我知道java.lang.Math中提供了一组静态方法来执行某些操作(sum,difference,multiply,increment,decrement,negate,toInt),抛出ArithmeticException溢出.
电力有类似的东西吗?