我想定义一个带有unsigned intas参数的函数,并向参数返回一个int全等模UINT_MAX + 1.
第一次尝试可能如下所示:
int unsigned_to_signed(unsigned n)
{
return static_cast<int>(n);
}
Run Code Online (Sandbox Code Playgroud)
但正如任何语言律师所知,从无符号转换为大于INT_MAX的已签名值是实现定义的.
我想实现这一点,以便(a)它只依赖于规范规定的行为; (b)它在任何现代机器上编译成无操作并优化编译器.
对于奇怪的机器......如果没有签名的int congruent将UINT_MAX + 1模数为unsigned int,那么假设我想抛出一个异常.如果有多个(我不确定这是否可能),那么就说我想要最大的一个.
好的,第二次尝试:
int unsigned_to_signed(unsigned n)
{
int int_n = static_cast<int>(n);
if (n == static_cast<unsigned>(int_n))
return int_n;
// else do something long and complicated
}
Run Code Online (Sandbox Code Playgroud)
当我不是一个典型的二元补充系统时,我并不太关心效率,因为我认为不太可能.如果我的代码成为2050年无所不在的符号量级系统的瓶颈,那么,我敢打赌,有人可以解决这个问题并对其进行优化.
现在,第二次尝试非常接近我想要的.尽管转换int为某些输入的实现定义,但是unsigned标准保证转换为保留模UINT_MAX + 1的值.所以条件确实检查我想要什么,它将在我可能遇到的任何系统上编译成什么.
但是......我仍然在int没有首先检查它是否会调用实现定义的行为.在2050年的一些假设系统中,它可以做谁知道什么.所以我想说我想避免这种情况.
问题:我的"第三次尝试"应该是什么样的?
回顾一下,我想:
[更新]
让我举一个例子来说明为什么这不是一个微不足道的问题.
考虑具有以下属性的假设C++实现:
sizeof(int) 等于4sizeof(unsigned) 等于4INT_MAX 等于32767INT_MIN等于-2 …我有一个无符号值,需要将函数作为有符号值传递(函数不会触及它).当它出现时我把它丢回原状.我知道转换为强制转换时执行定义的转换结果,但是我可以至少保证当我将其转换回来时(例如使用函数指针)我会得到相同的值吗?
例:
int32_t function_with_default(int32_t a_Default)
{
// Try some stuff
// ...
// Fall back to default
return a_Default;
}
void main()
{
uint32_t input = UINT32_MAX;
uint32_t output = static_cast<uint32_t>(function_with_default(static_cast<int32_t>(input));
// Is is guarenteed to be true?
input == output;
}
Run Code Online (Sandbox Code Playgroud)
我确实保证有符号整数总是大于或等于无符号整数(以字节为单位),因此不会因缺少空间而丢失数据.