10

我最近讀了打印字符時會發生哪些積分促銷活動?

unsigned char x=1; 
printf("%u",x); 

調用不確定的行爲,因爲由於格式說明%U,預計的printf一個unsigned int。但是我仍然想知道這個例子中發生了什麼。

我認爲積分促銷規則適用於表達式printf("%u",x)x表示的值。

A.6.1積分促進

字符,短整數,或整數位字段中,所有符號或沒有,或枚舉類型的 對象,可以在表達式無論使用可以使用整數。 如果int可以表示原始類型的所有值,則該值將被轉換爲 爲int;否則該值將轉換爲unsigned int。這個過程被稱爲積分 促銷。

「可能被使用」是什麼意思?這是否意味着'語法正確'或'是定義的行爲'?

在這個例子中x如何被提升?我已閱讀,它提升爲int,但如果printf("%u", (int x))仍然是不確定的行爲,然後我真的不明白爲什麼...

+1

我認爲這個行爲的確是有定義的,因爲你提到的原因。 –

+1

[推薦觀看](http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-7-of-n) –

+1

@luserdroog:所以你認爲「可能被使用」是指應該定義行爲?或者我錯過了你的觀點? – lee77

回答

3

由於printf使用可變參數列表,整數提升應用於其整數參數。在任何正常的C實現中,整數提升將unsigned char轉換爲int。然後,您正在格式化int使用unsigned int的說明符,因此行爲未定義。

在可能使用整數的地方使用字符與您的語句的行爲未由C標準定義的事實之間沒有衝突。儘管您可以使用字符來代替整數,但仍然適用有關可以使用%u打印的規則的規則。如果使用一個字符會生成一個適合於說明符的整數,則會定義該行爲。如果使用一個字符會產生一個不適合於說明符的整數,那麼該行爲不會被C標準定義。

堆棧溢出的其他討論認爲,異常的C實現可能理論上符合C標準,而char類型(普通,有符號和無符號)的類型寬度爲int。在這樣的實現中,並且int不能代表unsigned char的所有值,所以unsigned char必須被提升爲unsigned int。然而,這樣的實現將是異乎尋常和麻煩的(特別是在處理EOF時),並且您可能在實踐中忽略它。

+0

所以有兩個步驟:首先,整數提升發生,因爲x代表一個整數,printf使用可變參數列表。現在有兩種可能性: 1)int不能表示無符號字符可以使用的所有值(這將是相當奇特的)。然後將x提升爲已定義的unsigned int。 2)int可以表示無符號字符可以包含的所有值,所以x被提升爲int。在這種情況下,就不會存在是(printf的範圍內,而解決的va_arg宏)的定義'無符號整數<一些變量名> = '?哪一個也會被定義? – lee77

+0

僅供參考,在「討論SO別處」是在這裏:http://stackoverflow.com/questions/4664100/does-printfx-1-invoke-undefined-behavior –

+1

@ lee77:沒有,不一定任何此類轉讓。當'printf'實現看到'%u'說明符時,它將嘗試獲取'unsigned int'參數的字節。它所採取的手段取決於實施。它不需要通過C賦值表達式。它可以是純粹的組裝或機器語言。唯一可以依賴的規則是:如果使用'unsigned int'說明符,則必須傳遞'unsigned int'。 –

1

如果平臺的int可以代表比unsigned char所有的值就可以了,那麼推廣是到int,否則到unsigned int。所以這取決於你的平臺。

至於「爲什麼」,那是因爲您將x作爲可變參數傳遞,並且變量參數的規則表示標準促銷發生(可能是爲了簡化實現)。

+0

所以你說在上面的語境中「可能被使用」的意思是'句法正確'?或者它有不同的含義? – lee77

+0

促銷是平臺依賴的,合法性不是。 –

1

由於printf使用可變參數列表,它將通過va_arg解壓縮。 C++是指va_arg規則的C標準。 C99標準規定如下:

va_arg宏展開爲具有指定類型和調用中下一個參數的值的表達式。參數ap應該已經被va_startva_copy宏初始化(沒有干預調用相同apva_end宏)。 va_arg宏的每個調用都會修改ap,以便依次返回連續參數的值。參數類型應爲指定的類型名稱,以便可以簡單地通過後綴*類型來獲取指向具有指定類型的對象的指針的類型。如果沒有實際的一個參數,或者如果類型不與實際的一個參數的類型兼容(如晉升根據默認參數提升),該行爲是不確定的,除了以下情況:

  • 一個類型是一個有符號整數類型,另一個類型是相應的無符號整數類型,並且該值可以在兩種類型中表示;
  • 一種類型是指向void的指針,另一種是指向字符類型的指針。

顯然,確定是否實際和預期類型匹配時整數優惠都考慮在內。第一個要點包括有符號與無符號不匹配。

由於x = 1肯定是由unsigned int一個值表示的,並且促進unsigned char產生任一signed int(如果INT_MAX >= UCHAR_MAX)或unsigned int(如果INT_MAX < UCHAR_MAX),這是完全合法的。