程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C中signed與unsigned,signedunsigned

C中signed與unsigned,signedunsigned

編輯:關於C語言

C中signed與unsigned,signedunsigned


1 unsigned int i=3;
2 cout<<i * -1;
問結果是多少。

第一反應:-3。不過結果似乎不是這樣的,寫了個程序,運行了一下,發現是:4294967293。

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。   在C語言中,signed要求最高位是符號位,以下表示數據大小,而unsigned則全部位都表示大小。如果用8位二進制表示的話,signed范圍就是-128到127,unsigned就是

0到255,C語言中專門用兩個關鍵字來描述兩種表示方法,於是,就產生了一些不可思議的問題。

1、溢出

  在有符號運算中可能會產生溢出問題,歸納起來就是:兩個整數相加可能會溢出,兩個負數相加也可能會溢出,一正一負相加肯定不會溢出。在《C深度剖析》中看到一個有趣的問題。

 1 #include <stdio.h>
 2 #include <string.h>
 3 int main(void)
 4 {
 5   char a[1000];
 6   int k = 0;
 7   for (; k < 1000; k++) 
 8     {
 9       a[i] = -1-i;  
10 
11   }
12   printf("%d\n", strlen(a));
13   return 0;
14 }

  最終的結果是255。因為數組a[1000]是char類型的,在C語言中明確規定char類型占一個字節內存空間,且在x86的gcc平台上 char默認是signed,一開始,k=0,a[0]=-1,隨著k不斷增大,當k=127,則a[127]=-128,對應的二進制是 10000000,我們知道-128是編譯器能表示的最小值,當k=128,a[128]當然不可能存儲-129這個值了,因為最高位發生了溢出,所以在 計算機中儲存的補碼值是01111111,。隨著k繼續增大,當k=254時,a[254]在計算機中存放的補碼是00000001,而 k=255,a[255]對應的存儲值是00000000,即0,strlen函數遇到第一個0就停止,所有最後的結果是k從0到254,總共長度是 255。

2、signed和unsigned混合運算

  C語言中除了char類型,編譯器默認其他整型都是signed,在x86的gcc平台上包括char在內所有整型都是signed。

 1 #include <stdio.h>
 2 
 3 int main(void)
 4 {
 5 unsigned a = 10;
 6 unsigned b = -10;
 7 if (a) printf("yes\n"); else printf("no\n");
 8 if (b) printf("yes\n"); else printf("no\n");
 9 
10 int c = b;
11 printf("%d\n", c);
12 if (c) printf("yes\n"); else printf("no\n");
13 
14 int d = -20;
15 int e = a + d;
16 printf("%d\n", e);
17 if (e) printf("yes\n"); else printf("no\n");
18 
19 return 0;
20 }

最後結果是

yes
yes
-10
yes
-10
yes

  從上面例子可以看出,在C語言中,有符號數可以賦值給無符號數,結果是一個無符號數,而無符號數也可以賦值給有符號數,結果還是一個無符號數;在混合運算中,只要有一個無符號數,都會將有符號數轉化成無符號數參加運算,結果也以無符號保存。

 

注意:signed 和 unsigned 在電腦中的存儲形式是一樣的,只是解釋方法不同,即一個有符號,一個無符號。

%d打印的是signed類型的,而%u才是打印的unsignd類型的,用不同的打印相當於一個類型轉換了。當然C++比較直觀,能直接自動識別出類型並打印值。

就用上面的例子:

unsigned c = 3;
printf("%d\n",(c*(-1)));       //  打印出的是-3    
printf("%u\n",(c*(-1)));       //  打印出的是4294967293

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved