文章目录
char转int 高位符号扩展
int main() {
char a = 0x9A;
int util;
util = (int)a;
cout << a << endl;
cout << util << endl;
if (util > 0) {
std::cout << "pos" << std::endl;
} else {
std::cout << "neg" << std::endl;
}
}
打印结果:
-102
neg
0x9A转换为十进制为154,所以,在把a强制转换为int类型的变量util之后以为还是154,所以,期望输出为“positive”。但实际上0x9A的二进制表示为10011010,在强制转换为int时,因为int是有符号的,需要对10011010进行符号扩展,也就是用其最高位1来扩充其他 3个高字节,变成 11111111 1111111111111111 10011010(假设 int是4个字节),而这个是负数-102的二进制补码表示。所以,在判断util是否小于0时就会输出“negative”。
正确做法:
int main() {
char a = 0x9A;
int util;
util = (int)(unsigned char)a;
cout << a << endl;
cout << util << endl;
if (util > 0) {
std::cout << "pos" << std::endl;
} else {
std::cout << "neg" << std::endl;
}
}
如果期望 0x9A为正数,实际上需要先把 a强制转换为unsigned char。这样0x9A才会被解析为154
有符号int与无符号int比较
int main() {
int d = -1;
int array[] = {23, 23, 23};
cout << d << endl;
cout << (unsigned int)d << endl;
cout << (sizeof(array) / sizeof(array[0])) << endl;
if (d < (sizeof(array) / sizeof(array[0]))) {
cout << "yes" << endl;
} else {
cout << "no" << endl;
}
return 0;
}
结果:
-1
4294967295
3
no
由于sizeof()的返回类型是无符号整型
if语句在比较signed int型变量d和unsignedint型值的时候,signed int型变量被转换为 unsigned int型变量。-1转换成 unsigned int的结果是一个非常巨大的正整数(在 32位操作系统上会转换成2^32-1),导致if判断为假。
正确的做法:sizeof返回的结果强制转换为int型。
int main() {
int d = -1;
int array[] = {23, 23, 23};
cout << d << endl;
cout << (unsigned int)d << endl;
cout << (sizeof(array) / sizeof(array[0])) << endl;
if (d < (int)(sizeof(array) / sizeof(array[0]))) {
cout << "yes" << endl;
} else {
cout << "no" << endl;
}
return 0;
}
-1
4294967295
3
yes
关于一个bit的位域变量的取值范围
typedef struct xxdata {
int flag: 1;
int other: 31;
} xxdata;
int status() {
return 1;
}
int main() {
xxdata test;
test.flag = status();
if (test.flag == 1) {
cout << "test.flag = 1" << endl;
} else {
cout << "test.flag != 1" << endl;
}
}
test.flag != 1
在结构体中定义了一个int型的位域变量,而用一个bit来表示int时,这一位是用来表示符号位的,
带符号的一个bit的位域变量的取值范围是0或-1(无符号的一个bit的位域变量的取值范围是0或1)
stauts()的返回值1赋给flag时会出现溢出,flag值变为-1
下面的判断-1就可以:
typedef struct xxdata {
int flag: 1;
int other: 31;
} xxdata;
int status() {
return -1;
}
int main() {
xxdata test;
test.flag = status();
if (test.flag == -1) {
cout << "test.flag = -1" << endl;
} else {
cout << "test.flag != -1" << endl;
}
}
test.flag = -1
临时变量溢出
long mul(int m, int n) {
long score;
score = m * n;
return score;
}
在64位操作系统下,int型通常占4个字节,long型通常占8个字节,两个int型变量相乘的值范围是long型变量的值范围。score=m*n 这行代码在执行时,m和n相乘的结果会先存储在一个临时的int变量中,然后再赋值给long变量score,这个临时变量是很容易溢出的。所以,需要在表达式运算前先对m和n做数据类型转换。
正确做法:
long mul(int m, int n) {
long score;
score = static_cast<long>(m) * static_cast<long>(n);
return score;
}
对隐式的类型转换,一般来说向上是安全的,向下会出现数据截断丢失,导致数据错误。事实上,上述正确代码只在long型字节数是int型字节数两倍的情况下才是正确的,如果在某些平台下,long 型和int 型字节数一样的话(如32 位操作系统int型和long型通常都占4个字节),仍然需要注意两个int型相乘结果溢出的问题。
size_t死循环
int main() {
size_t size = sizeof(int);
cout << size << endl;
while (--size >= 0) {
cout << "size = " << size << endl;
}
return 0;
}
while条件永远为真,程序进入死循环
size_t是 sizeof操作符返回的结果类型,size_t在32位系统中是unsigned int,在 64位系统中是 unsigned long int。
当size的值等于0并再次作−−size运算时,size会因溢出再次等于它取值范围内的最大值,所以,size的值恒大于等于0
正确做法:
1、修改while条件
while (--size > 0) {
if (size == 0) break;
}
2、使用int替代size_t