2011-10-12 41 views
9

GCC警告我說下面的代碼段包含可能改變的值的隱式轉換:爲什麼GCC警告這種隱式轉換?

#include <stdlib.h> 
float square = rand(); 

然而,以下不產生任何警告:

float square = 100; 

警告由GCC給出是如下:

tests/ChemTests.cpp:17:23: error: conversion to ‘float’ from ‘int’ may alter its value 

我不明白,爲什麼前者將給予警告,因爲rand()爲p大致聲明並返回一個int,就像100整數字面量。

爲什麼第一行給出編譯器警告但不是第二行,即使兩者都有從intfloat的隱式轉換?

+0

我發現我沒有得到警告,除非我使用'-Wconversion'選項。 –

回答

14

當鑄件可能導致精度損失時,GCC發出此警告。 (換句話說,該值可能被「改變」)

在第一種情況下,rand()返回int。由於並非所有可存儲在int中的值均可表示爲float,因此它會發出此警告。

在第二種情況下,100可以安全地鑄造到float而沒有任何精確度損失。

+0

這是否意味着'float f = 123456789'會出錯? –

+0

它不會出錯,但它應該給出警告。這一刻我沒有GCC在我面前,但我只是在Visual Studio中測試它,並給出警告:'警告C4305:'初始化':從'int'截斷爲'float' – Mysticial

5

要添加一些東西到Mysticial寫的(這是正確的):你的C的實現使用32 bits IEEE 754 single precision binary floating-pointint是32位的float。在「你的」int你可以有31位的數字和1位的符號。在「你的」浮點數中,mantissa是24位,並且有1位的符號。顯然int s需要超過24位加號才能表示,不能完全轉換爲「你的」float。 (我使用「你的」來代表「你的」編譯器,你使用的編譯器.C標準沒有說明確切的長度爲floatint)。

現在,rand()可以生成任何int數字,所以編譯器必須給你警告。 100是編譯時已知的數字文字,因此編譯器可以靜態檢查該數字是否可以轉換。

(即使沒有解釋浮點的工作原理,你的int是32位,只支持整數。你必須保存在某個地方,其中小數點),所以必須有一個「價格」一分錢一分貨,如果兩個intfloat具有相同的長度,價格是精度。)

對你提出的意見作出迴應,在float中與「0」相鄰(因此0 ...號碼全部可以精確表示)的最大數量是16777215(即尾數= 16777215,exp onent = 0)和16777216(尾數= 1,指數= 24,因爲它是1 * 2^24)。 16777217不能完全表示。 16777218是。

0

並非每個int都可以表示爲float。具體而言,如果int中設置的最高位和最低位之間的比特數大於FLT_MANT_DIG - 1(在<float.h>中定義),則不能將其精確地表示爲float。 (同樣適用於doubleDBL_MANT_DIG - 1。)編譯器警告您可能會損失精度,因爲聲明rand()意味着rand()可能返回任何int,包括那些不能表示爲float的。

GCC應該足夠了解智能時候int文字可以精確地表示:

float f= 1<<FLT_MANT_DIG; // yes 
float g= (1<<FLT_MANT_DIG) - 1; // yes 
float h= (1<<FLT_MANT_DIG) + 1; // no 
float i= (1<<(FLT_MANT_DIG + 1)); // yes 

GCC應該吐出只初始化h警告。

順便說一句,如果RAND_MAX小於或等於(1<<FLT_MANT_DIG) - 1,你可以放心地分配rand()float,即使編譯器會抱怨你。

相關問題