2015-10-30 64 views
2

我有點困惑。在開發一個基於預定義參數的函數的過程中,根據其類型傳遞給sprintf函數所需的精確參數,我發現了非常奇怪的行爲(類似「This is%f%d example」,typeFloat,typeInt)。聯盟浮動和int

請看看下面的剝離工作代碼:

struct Param { 
enum { typeInt, typeFloat } paramType; 
union { 
    float f; 
    int i; 
}; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
Param p; 
p.paramType = Param::typeInt; 
p.i = -10; 

char chOut[256]; 
printf("Number is %d\n", p.paramType == Param::typeInt ? p.i : p.f); 
printf("Number is %f\n", p.paramType == Param::typeInt ? p.i : p.f); 
return 0; 
} 

我的預期產出將是printf("Number is %d\n", p.paramType == Param::typeInt ? p.i : p.f);

Number is -10 

但它實際上印刷

Number is 0 

我已經把Param p初始化後的斷點,儘管p.paramType定義爲typeIntif的實際輸出爲-10.0000。檢查p.f給出了一些未定義的值,p.i也如預期的那樣顯示-10。 但在觀察窗口中的p.paramType == Param::typeInt ? p.i : p.f評估爲-10.000000。

我添加了打印作爲浮動,現在輸出

Number is 0 
Number is -10.000000 

因此,實際上爲什麼發生這種情況第二個printf?這有可能是Visual Studio中的一個錯誤(我使用VS2012)?

更新:

std::cout<< (p.paramType == Param::typeInt ? p.i : p.f); 

給出-10正確的值。

回答

5

這是因爲所得到的表達p.paramType == Param::typeInt ? p.i : p.f的類型總是漂浮(只有取決於paramType是不同的),但你的第一格式串預期的整數。

如您所願下面應該工作:

printf("Number is %d\n", (int)(p.paramType == Param::typeInt ? p.i : p.f)); 

cout版本給你所期望的輸出,因爲插入的表達式的類型(float)自動推導,所以它格式化爲一個浮動。它與你的第二個printf基本相同。

+0

謝謝您的回覆。我無法將完整表達式轉換爲int。paramType也可以浮動(我只是用int作爲上面的例子)。爲什麼它總是浮動的,如果我提供一個數字的整數部分? – Izzy

+1

如果您不想將其轉換爲int,那麼將其作爲整數打印出來也沒有意義。因此,要麼總是打印一個浮點數,要麼當你打印一個int時,實際上給它一個int :-)表達式的結果(如'?:')只能是單一類型;當兩個子表達式是不同類型時,[隱式類型轉換完成](http://stackoverflow.com/q/8535226/21475)。 – Cameron

+0

啊我明白了。我今天學了些新東西 :)。如果語句只能返回一種類型,我不知道三元關係。但是我不能將所有內容都轉換爲int,因爲它可能是float而不是int。解決方案實際上是讓所有浮動並將格式設置爲%.0f,將浮點數整數轉換爲整數。 – Izzy

1

問題是雙重的。首先是printf()。不要在C++代碼中使用printf()。原因與第二個問題有關。 printf()沒有類型安全。它不知道你給了它什麼類型。

第二個原因是類型的工作方式。您的三元if語句總是返回float,因爲這是最右邊的類型。由於int可以隱式轉換爲float,因此不會發生任何「不良」情況(除非您打開各種「額外」警告)。因此p.i被轉換爲float,但您要告知printf()預計會有int。因此,發生未定義的行爲。你的程序不會崩潰但它不會給你你所期望的。

+0

我喜歡'printf',即使在C++中也是如此。這很簡單。是的,如果你沒有正確使用它,從安全角度來看有一個很好的論點,但是這個論點可以擴展到C++中的很多東西:-) – Cameron

+1

在我看來,使用'std :: ostream'(例如,通過'std :: cout')*也很簡單。這當然更具可擴展性。 – inetknght

+1

非常真實。儘管如此,我從未真正需要可擴展性。 – Cameron