2012-03-05 55 views
3
char a; 
char b; 
char c; 

a = b + c; 

a = (char)((int)b+(int)c); 

在第一行中,它將暗示從char轉換爲int。在第二行中,它是明確的。編譯器生成的二進制文件是否有區別?這兩行代碼中顯式和隱式類型轉換有什麼區別?

請從嵌入式系統的角度考慮這個問題。

+4

試着編譯一下,看看有沒有什麼區別! – Dan 2012-03-05 17:24:46

+0

你總是可以部分編譯彙編並檢查生成的代碼如果你使用的是gcc,使用-S標誌來完成這 – Dason 2012-03-05 17:26:57

+0

請尊重回答嵌入式系統,如富士通 – bubble 2012-03-05 17:27:19

回答

4

我對標準的閱讀表明這是留給實現和優化器的。

第5.1.2.3節,第10部分:

實施例2在執行所述片段

char c1, c2; 
/* ... */ 
c1 = c1 + c2; 

的 '' 整數優惠 '' 要求抽象機推進值每個變量的int大小,然後添加兩個整數並截斷總和。如果可以在不溢出的情況下添加兩個字符,或者使用默認情況下的溢出包裝來產生正確的結果,則實際執行只需要產生相同的結果,可能會省略促銷。

我的理解是,標準可以讓編譯器決定是否可以使用8位加法,只要結果不會與添加int並將轉換爲字符區分開來。

注意回到我的嵌入式世界(九十年代中期)天,我們用我們的8位平臺上的C編譯器,Whitesmith編譯器68HC11,產生了「純」 8位加法的指令加兩個char s。確定你的富士通系統會發生什麼的唯一方法是編譯到程序集並檢查你自己。

5

隨着我的編譯器它產生完全相同的組件兩次:

4: 0f b6 55 ff    movzbl -0x1(%rbp),%edx 
8: 0f b6 45 fe    movzbl -0x2(%rbp),%eax 
c: 01 d0     add %edx,%eax 
e: 88 45 fd    mov %al,-0x3(%rbp) 

11: 0f b6 55 ff    movzbl -0x1(%rbp),%edx 
15: 0f b6 45 fe    movzbl -0x2(%rbp),%eax 
19: 01 d0     add %edx,%eax 
1b: 88 45 fd    mov %al,-0x3(%rbp) 

正如你看到的,這是AMD64組件(由GCC 4.6.2生產)。唯一確定的方法是將其編譯爲目標平臺並檢查程序集。

+2

是你'char's符號或無符號不要緊 – 2012-03-05 17:25:00

+0

@Adam:??這是來自問題的代碼,所以既不簽名也不簽名,只是'char'。但是,結果與'unsigned char'或'signed char'完全一樣。 – 2012-03-05 17:27:19

+0

@Benoit:在GCC的情況下這可能是正確的,我不知道,我不認爲這是由t定義的他標準](http://stackoverflow.com/questions/2054939/char-is-signed-or-unsigned-by-default),但。 – 2012-03-05 17:28:17

2

根據C標準,結果必須相同,嵌入與否。

1

表達式語句(1)和(2)都是等價的。

char a; 
char b; 
char c; 

a = b + c; // (1) 

a = (char)((int)b+(int)c); // (2) 

通過通常的算術轉換規則,bc都轉換爲int(整數促銷)。然後b + c通過賦值運算符的語義轉換爲char

加法運算符:

(C99,6.5.6p4)「如果兩個操作數具有算術類型,通常的算術轉換都對它們執行。「

簡單賦值:

(C99,6.5.16.1p2分配)」以簡單賦值(=),右操作數的值被轉換爲賦值表達式的類型和取代存儲在由左操作數所指定的對象的值 「

整數優惠:

(C99,6.3.1.1p2)」 我f int可以表示原始類型的所有值,該值將轉換爲int;否則,它被轉換爲一個unsigned int。 「

+0

你能告訴如何獲得C90手冊嗎? – bubble 2012-03-23 06:18:53