我正在寻找一些用于签名饱和64位加法的C代码,它使用gcc优化器编译为高效的X86-64代码.便携式代码是理想的,尽管如果需要可以使用asm解决方案.
static const int64 kint64max = 0x7fffffffffffffffll;
static const int64 kint64min = 0x8000000000000000ll;
int64 signed_saturated_add(int64 x, int64 y) {
bool x_is_negative = (x & kint64min) != 0;
bool y_is_negative = (y & kint64min) != 0;
int64 sum = x+y;
bool sum_is_negative = (sum & kint64min) != 0;
if (x_is_negative != y_is_negative) return sum; // can't overflow
if (x_is_negative && !sum_is_negative) return kint64min;
if (!x_is_negative && sum_is_negative) return kint64max;
return sum;
}
Run Code Online (Sandbox Code Playgroud)
写入的函数产生具有多个分支的相当长的汇编输出.有关优化的提示吗?看起来它应该只用一个带有一些CMOV指令的ADD来实现,但我对这些东西有点生疏.
怎么能一个增加两个long,因此如果结果溢出,然后它被钳范围在Java中值Long.MIN_VALUE.. Long.MAX_VALUE?
对于添加ints,可以执行long精度算术并将结果转换回int,例如:
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
long clampedSum = Math.max((long) Integer.MIN_VALUE,
Math.min(sum, (long) Integer.MAX_VALUE));
return (int) clampedSum;
}
Run Code Online (Sandbox Code Playgroud)
要么
import com.google.common.primitives.Ints;
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
return Ints.saturatedCast(sum);
}
Run Code Online (Sandbox Code Playgroud)
但是在long没有较大的原始类型可以保持中间(非夹紧)总和的情况下.
由于这是Java,我不能使用内联汇编(特别是SSE的饱和添加指令).
它可以使用BigInteger例如
static final BigInteger bigMin = BigInteger.valueOf(Long.MIN_VALUE);
static final BigInteger bigMax = BigInteger.valueOf(Long.MAX_VALUE);
long …Run Code Online (Sandbox Code Playgroud) java math signal-processing bit-manipulation integer-overflow
一般来说,如何防止C编程语言中发生整数溢出?我的意思是,有什么功能可以防止吗?最后,整数溢出是否会让我像缓冲区溢出等那样被黑客攻击?
为我的愚蠢道歉,因为这是我在这个论坛上的第一篇文章.我试图通过以下代码检测包装无符号32位计数器和大负跳转之间的区别,但编译器给我错误:
错误:由于数据类型的范围有限,比较始终为真[-Werror = type-limits]
这是我的代码片段:
#define MAX_BACKWARD_JUMP -4294959295 //UINT_MAX - 8000
#define MIN_BACKWARD_JUMP -3600
#define MAX_FORWARD_JUMP 4800000
signed int rtpDelta; //Signed 32-bit
unsigned int currRTPTs, prevRTPTs; //unsigned 32-bit
rtpDelta = currRTPTs - prevRTPTs;
if ((rtpDelta > MAX_BACKWARD_JUMP && rtpDelta < MIN_BACKWARD_JUMP)
|| (rtpDelta > MAX_FORWARD_JUMP))
{
printf("Delta in Timestamps too large\n",rtpDelta);
}
Run Code Online (Sandbox Code Playgroud)
这里的想法是在RTP时间戳中捕获无效的大型Deltas.我们有一个当前的TimeStamp和一个从对等RTP客户端接收的前一个Timestamp.RTP时间戳的无效值的边界限制是-4294959295 <rtpDelta <-3600,如果Delta小于-3600且大于-4294959295,它应该抛出错误,因为更接近UMAX_INT的值将被视为翻转.我在这做错了什么?