文章目录


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