将uint32_t转换为int32_t,既没有溢出的风险,也没有过度复杂的风险
Convert a uint32_t to an int32_t without either a risk of overflow or excessive complexity
在C++中,如何最好地通过包装将uint32_t
快速转换为int32_t
?
一些尝试:
uint32_t y = UINT32_MAX;
int32_t x = (int32_t)y; // UB on overflow
int32_t x = *(int32_t*)&y; // does this violate strict aliasing?
int32_t x = (int32_t)y;
不是溢出,也不是UB溢出是指算术运算产生的结果超出可表示值的范围。但是,转换不是算术运算。
这种情况是实现定义的行为。我所知道的所有实现都将行为定义为不更改表示。
请注意,此处不需要铸造。你可以写int32_t x = y;
。实际上,这更简单,而且永远有效。如此多的代码依赖于此,以至于没有供应商会定义任何其他行为(并不是说他们有任何理由这样做)。
int32_t x = *(int32_t*)&y
不是UB。它不违反严格别名,因为允许类型的有符号版本对无符号版本进行别名。该代码保证生成与相应的uint32_t
具有相同表示的int32_t
(即"包装",因为这些类型保证是2的补码)。
union {
int32_t i;
uint32_t u;
} u;
u.i = ...;
printf("%" PRIu32 "n", u.u);
This和memcpy(&uint_var, &int_var, sizeof uint_var)
是在不调用未定义行为的情况下进行此类转换的两种标准方法。
另请参阅:
- C99中是否未指定通过并集的类型punning,C11中是否已指定
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
int makesigned(unsigned x) {
if (x <= (unsigned) INT_MAX) {
return (int) x;
}
/* assume 2's complement */
if (x >= (unsigned) INT_MIN) {
return 0 - (int)(-x);
}
abort();
return 0;
}
int main(void) {
assert(makesigned(0) == 0);
assert(makesigned(INT_MAX) == INT_MAX);
assert(makesigned(UINT_MAX) == -1);
assert(makesigned(INT_MIN) == INT_MIN);
return 0;
}
相关文章:
- C++ VISUAL STUDIO:GLFWwindow没有初始化,即使它是在文档中编写的并且以前工作过
- 在没有标识符的情况下如何读取复杂的C++类型声明?
- 有没有办法帮助编译器处理复杂的参数推导?
- 有没有办法降低程序的时间复杂度?
- 有没有比具有多个维度的容器更好的解决方案来进行复杂的数据管理?
- 两个构造函数(带和不带参数),没有输入 -> 没有参数运行。跳过上述类中的构造函数
- 有没有一种优雅的方法可以将矢量<复杂<float>>转换为矢量<short>?
- boost::async_connect 上的 ASIO 完成处理程序在第一次失败后再也没有调用过
- 在没有值时跳过计算平均值.C++.Xcode
- 有没有什么方法可以降低时间复杂度来找到这个矩阵的幂n
- 代码跳过 getline 语句.我尝试了getline和cin都没有成功
- 链接时有没有办法跳过未使用的库
- 将uint32_t转换为int32_t,既没有溢出的风险,也没有过度复杂的风险
- 没有模板参数的类的C++专用构造函数(跳过尖括号)
- 没有匹配的函数可供调用,但从未调用过那个精确的函数
- 有没有尝试过用无符号或有符号整数来表示浮点
- 跳过初学者C++功能:没有错误
- 使用锁和 STL 算法对 C++ 向量进行排序,或者编写一个没有锁的更复杂的算法
- 'xxxx' :看起来像一个函数定义,但没有参数列表;跳过表观身体
- 有没有办法使用 clang 有效地编译已经预处理过的文件