[英]is using a constant without an explicit cast invoke undefined behavior?
在調用一個函數或從一個函數返回一個期望值為T
類型的值的值時,是否使用不帶顯式強制轉換的常量文字調用未定義的行為?
例如,我們有一個函數的原型是long foo(unsigned long x);
調用: foo(4); //does this invoke UB?
foo(4); //does this invoke UB?
long foo(unsigned long x) { x += 10; return 10; } // does this invoke UB ?
我們應該寫foo((unsigned long)4)
並return (long)10
嗎?
不,這都是定義明確的。
兩種類型之間存在一個隱式轉換規則,因此int
會簡單地轉換為unsigned long
,並且程序會按預期運行。
文字4
類型為int
。 (在C節6.4.4.1整數常量中,類似的節在C ++中也可用)
在C和C ++中都很好地定義了從int
到unsigned long
隱式轉換。 (在C第6.3.3.1節中)
我們應該寫foo((unsigned long)4)並返回(long)10嗎?
您的兩個示例均定義良好,因此盡管可以接受這種轉換是多余的。
考慮下面的C代碼:
// foo.c
int foo(unsigned long x) { }
和
// main.c
int foo();
int main()
{
foo(4); // UB
foo((unsigned long)4); // OK
}
foo(4)
調用是UB,因為在調用范圍內沒有原型的函數時,必須手動確保參數匹配。 默認參數提升出現,僅此而已。
當然,從編寫健壯的代碼的角度來看,編寫強制轉換是一個不好的解決方案。 更好的解決方案是編寫一個原型:
int foo(unsigned long);
包含在兩個.c
文件中的頭文件中。
return 10;
case永遠不能是UB,因為編譯器在編譯函數體內的代碼時會知道函數的真實返回類型。
不,這沒有意義,因為這樣的參數在C和C ++中都是通過值傳遞的 :
long foo(unsigned long x);
您可能認為它是技術上的,因為x
參數是在foo
內部定義的本地自動變量,並分配有傳遞參數的值:
unsigned long x = 4;
如果參數的類型與參數不匹配,則編譯器將嘗試進行隱式轉換。 例如,將double
類型的參數靜默轉換為unsigned long
類型,即使這意味着信息丟失(盡管您可能會收到編譯器警告)。
但是,當您將x
參數的類型標記為引用時,可能會遇到麻煩(僅C ++):
long foo(unsigned long& x);
在這里,編譯器不允許您將其稱為foo(4)
,因為您現在通過引用傳遞,並且不能這樣修改4
。 但是,如果參數用const
限定符標記,則可以傳遞它:
long foo(const unsigned long& x);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.