文章目錄
- char轉int 高位符號擴展
- 有符號int與無符號int比較
- 關于一個bit的位域變量的取值范圍
- 臨時變量溢出
- size_t死循環
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