C++ | 负数比0大?
文章目录
- C++ | 负数比0大?
- 现象
- 分析
- 剖析
- 赋值运算
- 类型提升
- 标准有符号整数类型的转换级别关系为:
- char short转换
- int long double 转换
- >>>>> 欢迎关注公众号【三戒纪元】 <<<<<
现象
在 for 的判断语句中,对区间进行遍历,得到的区间并非自己预想的区间:
uint32_t end_index = j * num_per_thread;
uint32_t start_index = (j + 1 ) * num_per_thread - 1;
for (int k = start_index; k >= end_index; --k) {
std::cout << " k: " << k << ", end_index: " << end_index
<< ", start_index: " << start_index << ", k >= end_index: "
<< std::boolalpha << (k >= end_index) << std::endl;
}
分析
for 中的 k 类型为 int , k >= end_index
这句,判断左边是int类型,判断右边是 unsigned int 类型, 有符号和无符号进行比较的时候,会统一转换为无符号数进行比较,所以当负数和无符号比较时,负数会转换为无符号的数,当待比较的无符号数是0的时候,等式恒成立。
上述代码,在int 和 unsigned int 比较的时候,将左侧k 转换为 unsigned int 了,所以即便k是负数,转换为无符号后仍然符合。
修改代码需要将 start_index 和 end_index 转换为有符号的类型。
剖析
如果运算符两边的运算数类型不同,编译器会先将较低级类型转换为较高级类型,最终两边均为相同的类型,再进行比较。
本质上, 各种数据类型会全部转换为字节最高的数据类型进行运算,转换按数据长度增加的方向进行,以保证精度不降低。
编译器都可以自动进行数据类型转换,表达式所得值的类型为其中字节最高的数据类型。
赋值运算
所以常见的赋值运算,包括直接赋值、函数返回值、函数参数输入等,也存在两边数据类型不同的问题。
如果左右两边数据类型不同,编译器会自动将右侧数据类型转换为左侧数据类型,然后进行赋值。
因此如果左侧类型的等级大于右侧的,编译器会将右边数据类型转换为左边变量的类型,然后赋值,这样不会丢失数据精度;
如果左边数据类型等级小于右边的,编译器同样会转换,但是数据会丢失精度。
自动数据类型转换可以进行所有类型之间的转换。
类型提升
标准有符号整数类型的转换级别关系为:
long long int > long int > int > short int > signed char
char short转换
char转换成 int
unsigned char转换成 int
short转换成 int
如果short的字节长度小于int的字节长度 unsigned short转换成 int ; 如果short的字节长度等于int的字节长度, unsigned short转换成 unsigned int
int long double 转换
- 如果int的字节长度小于long的字节长度
类型等级由高到低依次为:long double、double、float、 unsigned long long、long long、unsigned long、long、unsigned int、int
- 如果int的字节长度等于long的字节长度
类型等级由高到低依次为:long double、double、float、unsigned long long、long long、unsigned long、unsigned int、long、int
double ←── float 高
↑
long
↑
unsigned
↑
int ←── char,short 低
无符号的数据还有很多,很容易被忽略,包括sizeof()
、strlen()
、STL中的size()
函数等等