最近,我们在一些旧代码中发现了奇怪的行为.这段代码已经工作了很长时间,但在某些平台(XBox 360,PowerPC)上打破了编译器优化最大化.通常,我怀疑未定义的行为.
代码看起来大致如下:
#include <stdint.h>
uint32_t sign_extend16(uint32_t val)
{
return (int32_t)(int16_t)val;
}
Run Code Online (Sandbox Code Playgroud)
它是模拟器的一部分,所以有问题的操作不应该太奇怪.通常情况下,我希望这只考虑较低的16位并将其符号扩展为32位.显然,这是它多年来的行为.在x86_64上,GCC给出了这个结果:
0000000000000000 <sign_extend16>:
0: 0f bf c7 movswl %di,%eax
3: c3 retq
Run Code Online (Sandbox Code Playgroud)
但是,根据我对标准的理解,如果无法用signed类型表示unsigned的值,则无法定义将unsigned转换为signed.
那么编译器是否可以假设无符号值必须在范围内[0, 32767],因为任何其他值都是未定义的?在这种情况下,一个演员int16_t和另一个演员int32_t将无能为力.在这种情况下,编译器将代码转换为简单的移动是否合法?
我试图找到 a 的平方int。我的代码如下所示:
long long sqr=0;
int num=77778;
sqr= num*num;
Run Code Online (Sandbox Code Playgroud)
结果应该是6049417284
但是当我检查输出时它显示1754449988。我在做什么错误?
long long应该能够存储结果,但为什么我得到不同的值?
如:
let mut a : usize = 0xFF;
a += -1; // -1 may be from other variable, so there can't be a -= 1;
println!("{}", a);
Run Code Online (Sandbox Code Playgroud)
输出是:
let mut a : usize = 0xFF;
a += -1; // -1 may be from other variable, so there can't be a -= 1;
println!("{}", a);
Run Code Online (Sandbox Code Playgroud)
反正?
据我所知,在 C 编程语言(以及许多基于 C 的语言)中,当算术运算溢出 N 位整数时,此溢出会将结果缩短为 2 的模 N 次方,仅保留 LSB结果。
当这样的整数算术运算在 Rust 编程语言中溢出时会发生什么。
我们有一些整数算术,由于历史原因,它必须在PHP上使用与在一些静态类型语言中相同的算法.自从我们上次升级PHP以来,溢出整数的行为已经改变.基本上我们使用以下公式:
function f($x1, $x2, $x3, $x4)
{
return (($x1 + $x2) ^ $x3) + $x4;
}
Run Code Online (Sandbox Code Playgroud)
但是,即使有转换:
function f($x1, $x2, $x3, $x4)
{
return intval(intval(intval($x1 + $x2) ^ $x3) + $x4);
}
Run Code Online (Sandbox Code Playgroud)
我仍然以完全错误的数字结束......
例如,使用$ x1 = -1580033017,$ x2 = -2072974554,$ x3 = -1170476976)和$ x4 = -1007518822,我最终得到PHP中的-30512150和C#中的1617621783.
只是加在一起$ x1和$ x2我无法得到正确的答案:
在C#我得到
(-1580033017 + -2072974554) = 641959725
Run Code Online (Sandbox Code Playgroud)
在PHP中:
intval(intval(-1580033017) + intval(-2072974554)) = -2147483648
Run Code Online (Sandbox Code Playgroud)
这与:
intval(-1580033017 + -2072974554) = -2147483648
Run Code Online (Sandbox Code Playgroud)
我不介意写一个"IntegerOverflowAdd"函数或其他东西,但我不太清楚如何(-1580033017 + -2072974554)等于641959725.(我确实认为它是-2147483648 +(2*2 ^ 31) ,但是-2147483648 + 2 ^ 31是-1505523923,它大于Int.Min那你为什么要加2*2 ^ 31而不是2 …
我写了一个方法来将给定数字从天转换为毫秒:
private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = expireTimeInDays * 24 * 60 * 60 * 1000;
}
Run Code Online (Sandbox Code Playgroud)
我很难弄明白我做错了什么.现在我的问题是: 这个错误是如此明显吗?
纠正方法:
private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = ((long) expireTimeInDays) * 24 * 60 * 60 * 1000;
}
Run Code Online (Sandbox Code Playgroud)
如果我在计算之前没有将整数转换为long,那么我得到一个完全错误的结果.
在较长的脚本中,我必须将向量A(2614)的长度乘以数据帧B(1456000)的行数.如果我直接这样做,length(A) * nrow(B)我会得到消息,NAs produced by integer overflow虽然当我乘以相同的数字时没有问题:
2614 * 1456000
[1] 3805984000
Run Code Online (Sandbox Code Playgroud)
使乘法运算的唯一方法是round(length(A)) * nrow(B)或length(A) * round(nrow(B)).但这些数字所生产length和nrow必须为整数无论如何!此外,我使用函数is.integer的帮助页面上建议的以下函数对此进行了测试...
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x-round(x)) < tol
Run Code Online (Sandbox Code Playgroud)
......当然,他们是整数.那么为什么我需要拐杖"圆"呢?非常令人费解......有人知道背景中发生了什么?
请考虑以下代码:
template <std::intmax_t Base, std::intmax_t Exponent>
struct integer_power_bounded
{
static_assert(Exponent >= 0,
"Error in 'integer_power_bounded': 'Exponent >= 0' is false");
static constexpr std::intmax_t value = /* something */;
};
template <std::intmax_t Base>
struct integer_power_bounded<Base, 0>
{
static constexpr std::intmax_t value = 1;
};
Run Code Online (Sandbox Code Playgroud)
而不是/* something */,我想返回std::numeric_limits<std::intmax_t>::min()或std::numeric_limits<std::intmax_t>::max()如果Base^Exponent不能用a代表std::intmax_t.困难的是避免在计算过程中出现溢出,因为它们在编译时会产生错误.
怎么做(没有提升)?
c++ metaprogramming integer-overflow template-meta-programming c++11
我正在做一堆应用数学/信号处理/算法 C++ 代码。
我已启用-Wconversion编译器警告以捕获诸如类型double到类型数字的运行时转换之类的问题int32_t。
显然,在这些转换过程中我总是很担心,因为:
int32_t在本例中))每当我担心这种转换时,我通常使用单行检查:
boost::numeric_cast<DestType>(SourceType)
Run Code Online (Sandbox Code Playgroud)
但是,我想在没有boost.
直接的 C++ 有等价的boost::numeric_cast<DestType>(SourceType)吗?
如果直接的 C++ 没有等价物,那么什么是可比较的非boost实现?
我认为有点类似的检查基本上是一个模板函数,它有一个 if 语句来检查输入参数是否正溢出或负溢出(通过使用std::numeric_limits<DestType> ::max()and::min()和引发异常)。
我有这段简单的代码:
let val: u8 = 255 + 1;
println!("{}", val);
Run Code Online (Sandbox Code Playgroud)
这里据说这样的代码如果使用--releaseflag运行的话会正常编译。
我通过 运行此代码cargo run --release,并且仍然看到检查:
error: this arithmetic operation will overflow
--> src/main.rs:2:19
|
2 | let val: u8 = 255 + 1;
| ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
|
= note: `#[deny(arithmetic_overflow)]` on by default
error: could not compile `rust-bin` due to previous error
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?