int與unsigned等轉換(轉)
當不同型別的資料進行操作時,應當首先將其轉換成相同的資料型別,然後進行操作,轉換規則是由低階向高階轉換。轉換規則如下圖所示:
有符號數與無符號數之間運算問題 以下實驗均在virual c++6中執行通過 這個問題測試是否懂得C語言中的整數自動轉換原則,有些開發者懂得極少這些東西。當表示式中存在有符號型別和無符號型別時所有的運算元都自動轉換為無符號型別。因此,從這個意義上講,無符號數的運算優先順序要高於有符號數,這一點對於應當頻繁用到無符號資料型別的嵌入式系統來說是豐常重要的。 首先進行一個實驗,分別定義一個signed int型資料和unsigned int型資料,然後進行大小比較: unsigned int a=20; signed int b=-130; a>b?還是b>a?實驗證明b>a,也就是說-130>20,為什麼會出現這樣的結果呢? 這是因為在C語言操作中,如果遇到無符號數與有符號數之間的操作,編譯器會自動轉化為無符號數來進行處理,因此a=20,b=4294967166,這樣比較下去當然b>a了。 再舉一個例子: unsigned int a=20; signed int b=-130; std::cout<<a+b<<std::endl; 結果輸出為4294967186,同樣的道理,在運算之前,a=20,b被轉化為4294967166,所以a+b=4294967186
減法和乘法的運算結果類似。 如果作為signed int型資料的b=-130,b與立即數之間操作時不影響b的型別,運算結果仍然為signed int型: signed int b=-130; std::cout<<b+30<<std::endl; 輸出為-100。 而對於浮點數來說,浮點數(float,double)實際上都是有符號數,unsigned 和signed字首不能加在float和double之上,當然就不存在有符號數根無符號數之間轉化的問題了。
- #include <iostream>
- /*
- 當表示式中存在符號型別和無符號型別時
-
所有的運算元都自動轉換為無符號型別
- */
- usingnamespace std;
- char getChar(int x,int y){
- char c;
- unsigned int a=x;
- unsigned int b=a+y;
- (a+y>10)?(c=1):(c=2);
- return c;
- }
- void main(){
- char c1=getChar(7,4);
- char c2=getChar(7,3);
- char c3=getChar(7,-7);
- char c4=getChar(7,-8);
- printf(”c1=%d\n”,c1);
- printf(”c2=%d\n”,c2);
- printf(”c3=%d\n”,c3);
- printf(”c4=%d\n”,c4);
- system(”pause”);
- }
這樣一個題,據說是微軟面試題:
unsigned int i=3; cout<<i * -1; 問結果是多少。 第一反應:-3。不過結果似乎不是這樣的,寫了個程式,運行了一下,發現是:4294967293。很詭異的一個數字,怎麼也想不明白為什麼會是這麼個奇怪的數字。但是在我發現這數的十六進位制數是FFFFFFFD時,我想我已經離答案很近了… 這個涉及到了混合著不同資料型別的表示式中的資料型別的轉換問題。在總結轉換問題之前,先說明一下各種資料型別(只說明numeric型別的),下表來自MSDN: 對上表補充說明一下: 1)在32位機上,int型和unsigned int型都是32位的(4個位元組)。 2)enum會跟據最大值來決定型別,一般來說為int型,如果超出int型所能表示的範圍,則用比int型大的最小型別來表示(unsigned int, long 或者unsigned long) 3)關於型別的大小。一般用所能表示的資料範圍來比較型別的大小,如char型<unsigned char型<short型…在表示式中,一般都是由小的型別向大的型別轉換(強制型別轉換除外) 下面結合自己查的資料,加上自己不斷地舉各種情況程式設計,總結一下關於型別轉換(僅限於算術表示式中關於整數型別的轉換)的一些問題(如有缺漏,歡迎補充,感激不盡) 1、所有比int型小的資料型別(包括char,signed char,unsigned char,short,signed short,unsigned short)轉換為int型。如果轉換後的資料會超出int型所能表示的範圍的話,則轉換為unsigned int型; 2、bool型轉化為int型時,false轉化為0,true轉換為1;反過來所有的整數型別轉化為bool時,0轉化為false,其它非零值都轉為true; 3、如果表示式中混有unsigned short和int型時,如果int型資料可以表示所有的unsigned short型的話,則將unsigned short型別的資料轉換為int型,否則,unsigned short型別及int型都轉換為unsigned int型別。舉個例子,在32位機上,int是32位,範圍–2,147,483,648 to 2,147,483,647,unsigned short是16位,範圍0 to 65,535,這樣int型的足夠表示unsigned short型別的資料,因此在混有這兩者的運算中,unsigned short型別資料被轉換為int型; 4、unsigned int 與long型別的轉換規律同3,在32位機上,unsigned int是32位,範圍0 to 4,294,967,295,long是32位,範圍–2,147,483,648 to 2,147,483,647,可見long型別不夠表示所有的unsigned int型,因此在混有unsigned int及long的表示式中,兩者都被轉換為unsigned long; 5、如果表示式中既有int 又有unsigned int,則所有的int資料都被轉化為unsigned int型別。 經過這番總結,前面提出的問題的答案應該就很明顯了吧。在表示式i*-1中,i是unsigned int型,-1是int型(常量整數的型別同enum),按第5條可以知道-1必須轉換為unsigned int型,即0xffffffff,十進位制的4294967295,然後再與i相乘,即4294967295*3,如果不考慮溢位的話,結果是12884901885,十六進位制0x2FFFFFFFD,由於unsigned int只能表示32位,因此結果是0xfffffffd,即4294967293。參考: