2010-08-14 46 views
23

通常,C要求將二元運算符的操作數提升爲更高級操作數的類型。這可以被利用來避免冗長的石膏填充代碼,例如:移位和整數提升?

if (x-48U<10) ... 
y = x+0ULL << 40; 

然而,我發現,至少用gcc,此行爲不會對bitshifts工作。即

int x = 1; 
unsigned long long y = x << 32ULL; 

我希望右手操作的類型,使,使得轉換成功的左側操作數晉升爲unsigned long long。但是,相反,GCC打印一個警告:

warning: left shift count >= width of type 

是gcc破,還是標準作出一些例外的bitshifts類型提升規則?

+0

無論如何,無論警告如何,它會促進嗎? (畢竟這只是一個警告)。 – 2010-08-14 06:14:28

+1

難道你不能只使用一個短的宏來產生詳細的演員?像'#define ULL(x)((unsigned long long)x)'? – Borealid 2010-08-14 06:16:32

+1

@Robert:不,它產生了一個無操作,就好像我寫了簡單的'<< 32'。 @Borealid:是的,我可以,但我喜歡編寫可在任何地方複製和粘貼的代碼(例如其他項目),而無需額外的定義/標題。我討厭像'typedef unsigned int uint;'這樣的東西。 – 2010-08-14 06:21:53

回答

23

所謂的通常的算術轉換適用於很多二元運算符,但不是全部。例如,它們不適用於移位運算符,||,逗號運算符和賦值運算符。這是用於比特移位運算符的規則:

6.5.7 ... 3語義...
整數優惠在每個操作數的執行。結果的類型是提升的左操作數的類型。如果右操作數的值爲負或大於或等於提升的左操作數的寬度,則行爲未定義。

+1

謝謝,這就是我一直在尋找的東西。 – 2010-08-14 07:22:10

0

真正的麻煩在於,升級只適用於您的平臺定義爲int的任何內容。正如其他一些答案所述,移位運算符會將左操作數提升爲int。但是,這裏的int被定義爲32位值。整數轉換不會升級到long long(64位)。