整型提升

整型提升C程序設計語言中的一項規定:在表達式計算時,各種整形首先要提升為int類型,如果int類型不足以表示則要提升為unsigned int類型;然後執行表達式的運算。[1]

這一規則是由C語言的發明人丹尼斯·里奇肯·湯普遜創設的:[2]

"A character, a short integer, or an integer bit-field, all either signed or not, or an object of enumeration type, may be used in an expression wherever an integer maybe used. If an int can represent all the values of the original type, then the value is converted to int; otherwise the value is converted to unsigned int. This process is called integral promotion."

這段話的大意是:表達式中可以使用整數的地方,就可以使用枚舉類型,或有符號或無符號的字符、短整數、整數位域。如果一個int可以表示上述類型,則該值被轉化為int類型的值;否則,該值被轉化為unsigned int類型的值。這一過程被稱作integral promotion。

整型提升的意義在於:表達式的整型運算要在CPU的相應運算器件內執行,CPU內整型運算器(ALU)的操作數的字節長度一般就是int的字節長度,同時也是CPU的通用寄存器的長度。因此,即使兩個char類型的相加,在CPU執行時實際上也要先轉換為CPU內整型操作數的標準長度。通用CPU(general-purpose CPU)是難以直接實現兩個8比特字節直接相加運算(雖然機器指令中可能有這種字節相加指令)。所以,表達式中各種長度可能小於int長度的整型值,都必須先轉換為int或unsigned int,然後才能送入CPU去執行運算。

C語言標準中僅規定了:

char的长度 ≤ short int的长度 ≤ int的长度

這意味着short int與int的長度相等的可能。這種情形下,unsigned short就無法提升為int表示,只能提升為unsigned int。[3]

示例程序如下:

#include <stdio.h>
int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;

if ( a == 0xb6)  printf("a");   
if ( b == 0xb600) printf("b");  
if ( c == 0xb6000000) printf("c");  
}

x86架構上的Visual C++gcc編譯下,上述程序輸出為 c 。這是因為在這些環境下,編譯器把char定義為signed char(C語言標準沒有規定char類型是有符號還是無符號);表達式a==0xb6被整型提升,其中char類型的a提升為int類型並為一個負值,因此這個表達式的結果為false;表達式b==0xb600被整型提升,其中short類型的b提升為int類型並為一個負值,因此這個表達式的結果為false;表達式c == 0xb6000000沒有做整型提升,==運算符的兩段都是int類型的負值,其結果為true。

C語言的單操作數的+運算符(即「前綴+」),一個主要作用就是實現對操作數的整型提升。例如:

#include <stdio.h>
int main()
{
 char a = 1; 

 printf("%u", sizeof(a) );   
 printf("\n");  
 printf("%u", sizeof( +a ) );  
}

在x86的32位gcc編譯後,輸出為:

 1
 4

參考文獻

  1. ^ ([//web.archive.org/web/20141027021828/https://msdn.microsoft.com/en-us/library/fc9te331.aspx 頁面存檔備份,存於網際網路檔案館) Integral promotion in MSDN]
  2. ^ Brian Kernighan, Dennis Ritchie: The C Programming Language. Also known as "K&R C". 2nd ed., Prentice Hall 1988; ISBN 0-13-110362-8.
  3. ^ Integral promotion question in stackoverflow. [2015-01-27]. (原始內容存檔於2016-05-31).