转换回早期类型
Casting back to earlier type
我看到在某些代码中,我们有一个有符号值被传递给函数(它需要无符号值)。返回的值再次转换回有符号(目的是获取原始有符号值)。即使它目前有效..我怀疑,在所有可能的情况下,在这种情况下会保留原始签名值吗?
有人告诉我选角不好,应该尽可能避免。一些计算机科学专家可以告诉我,什么时候可以破解这段代码吗?
我知道的所有实现(在不同平台上与C++合作 20+ 年后),通过什么都不做来转换有符号<->无符号整数,即二进制值保持不变。
这种行为的根源在于处理(即不处理)C 中的整数溢出。拥有这样的遗产,这种签名/未签名的转换是一件合理的事情。我认为这永远不会改变。
总而言之,有符号->无符号->有符号和无符号->有符号->无符号的转换是100%安全的。当您有偶数次转换时,您需要注意数字的值是未使用最高位的非负整数,在这种情况下,类型是有符号还是无符号并不重要。否则,应使用自己的代码显式处理超出范围的值。
标准的整数提升部分很好地涵盖了有符号和无符号的转换。您的问题标记为C和C++,尽管我可以掸去这两个标准的灰尘,但我会在这里向您展示C99标准的相关部分。
关于将大小相似的有符号整数提升为无符号整数,其中有符号整数不在无符号整数的范围内(即它小于零(0)):
C99 6.3.1.3-p2
否则,如果新类型是无符号的,则通过重复添加或减去比新类型中可以表示的最大值多一个来转换值,直到该值在新类型的范围内。
这本质上意味着"添加(UINT_MAX+1)
"。
例如,在典型的 32 位系统上,UINT_MAX
0xFFFFFFFF
。现在假设您要转换以下内容:
int ival = -1;
unsigned int uval = (unsigned int)ival;
根据该标准,ival
将通过执行以下操作提升为unsigned int
:
uval = (UINT_MAX+1) + (-1);
当然,这会导致uval = UINT_MAX;
.这是由标准定义的。
从未签名转换为签名是另一回事。紧跟在上述标准上一节之后的是:
C99 6.3.1.3-p3
否则,新类型是有符号的,并且无法在其中表示值;结果要么是实现定义的,要么是实现定义的信号。
这实质上意味着,如果无符号中的值不在有符号整数的允许范围内,则不能依赖无符号转换为相同大小的有符号结果来具有实现不可执行的行为。换句话说:
unsigned int uval = INT_MAX;
int val = (int)uval;
定义了行为,因为INT_MAX是有符号整数范围内的值,而这:
unsigned int uval = INT_MAX + n;
int val = (int)uval;
对于一些任意n
使得 (INT_MAX+n
<= UINT_MAX
) 是实现定义的。因此,不要依赖它。标准中应该吓唬你避免这样做的特定部分是潜在的:"一个实现定义的信号被提出"。伊克斯。只是不要这样做。
上面文本中的示例
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char *argv[])
{
int ival = -1;
unsigned int uval = (unsigned int)ival;
printf("%d : %un", ival, uval);
uval = INT_MAX;
ival = (int)uval;
printf("%d : %un", ival, uval);
uval += 1;
ival = (int)uval;
printf("%d : %un", ival, uval);
return 0;
}
输出平台:Apple LLVM 版本 4.2 (clang-425.0.28)
-1 : 4294967295
2147483647 : 2147483647
-2147483648 : 2147483648
从有符号类型到无符号类型的转换定义良好;结果是原始值模 2^n,其中 n 是无符号类型的值表示中的位数。也就是说,负值被包装为大的正值。但是,从无符号类型转换为有符号类型时,如果正在转换的值可以在目标类型中表示,则该值保持不变;如果无法表示,则结果是定义的实现。因此,将较大的无符号值转换为不足以容纳它的有符号值不需要生成负值。
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 字符类型转换不兼容
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- C++:用户定义的显式类型转换函数错误
- 将类指针类型转换为键时出错
- 通过引用传递参数时C++类型转换
- 在 C++ 中将一个模板类型的对象类型转换为另一个模板类型
- C++显式类型转换(C 样式强制转换)的强制表示法和static_cast的多种解释
- C++无效的函数类型转换
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何将Windows产品类型转换为名称?
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 事件系统:使用类型转换或联合进行继承
- 如何在参数中定义隐式类型转换的构造函数?
- 类模板实例化中的类型转换