2013-06-24 48 views
4

此代碼,它用於設置一個部件,產生一個編譯器警告:預防「組合符號和無符號類型加寬兩個操作數」編譯器警告

 
[DCC Warning] Unit1.pas(742): W1024 Combining signed and unsigned types 
          - widened both operands 
var 
    iPrecision: cardinal; 
    iRadius: cardinal; 
    iActive: boolean; 
    iInProximity: boolean; 

iPrecision := Max(50, 100 - (3 + 2 * ord(iActive and iInProximity)) * iRadius); 

這能以某種方式強制轉換,以防止編譯器警告?

回答

4

在你情況下,ord()返回integer,所以需要明確地輸入到cardinal,chang荷蘭國際集團ord()cardinal()這樣:

iPrecision := Max(50, 100 - (3 + 2 * cardinal(iActive and iInProximity)) * iRadius); 

你將擺脫的警告,您的代碼將幾乎是相同的。

1

可避免任何

  • 編譯器警告更改您Cardinal變量簽署的類型,如Integer
  • 使用輕微的解決方法是這樣的:
 
var 
    ... 
const 
    BoolValues: array[Boolean] of Cardinal = (0, 1); 
begin 
    ... 
    iPrecision := Max(50, 100 - (3 + 2 * BoolValues[iActive and iInProximity]) * iRadius); 
end; 

+0

我選擇嘗試後者,因爲iPrecision和iRadius是我無法更改的組件屬性...但我仍然收到警告。 – Bill

+0

我想現在我會使用{$ WARNINGS OFF}和{$ WARNINGS ON} – Bill

+0

@Bill:檢查我的編輯到「BoolValues」的聲明。我測試並編譯了我發佈的代碼,並生成零警告。不要放棄這麼快。 :-) –

5

Arnaud解釋說ord()返回一個有符號值,它是警告的來源。 Arnaud和Ken都建議如何通過避免使用無符號操作數來消除警告。

我想提供一個替代意見,並建議您改爲選擇使用已簽名的操作數。假設您只使用帶符號的操作數進行計算。考慮下面的程序:

{$APPTYPE CONSOLE} 

uses 
    Math; 

function CalcPrecision(Radius: cardinal; Active, InProximity: boolean): Cardinal; 
begin 
    Result := Max(50, 100-(3+2*Cardinal(Active and InProximity))*Radius); 
end; 

begin 
    Writeln(CalcPrecision(1000, True, True)); 
    Readln; 
end. 

我相信你會希望這個程序的輸出是50.它不是。輸出是4294962396.

會發生什麼是您在未簽名的上下文中執行100-X其中X>100。當你這樣做時,你有整數溢出,結果是一個非常大的正值。由於您使用的是無符號算術,因此不能期望這是一個負值,因爲在無符號數中沒有負值。

當然,如果啓用了用於溢出檢查的編譯器選項,則會遇到運行時錯誤。但即使這不是你想要的。獲得您需要的答案的簡單方法是使用帶符號的算術來執行操作。

{$APPTYPE CONSOLE} 

uses 
    Math; 

function CalcPrecision(Radius: Integer; Active, InProximity: boolean): Integer; 
begin 
    Result := Max(50, 100-(3+2*ord(Active and InProximity))*Radius); 
end; 

begin 
    Writeln(CalcPrecision(1000, True, True)); 
    Readln; 
end. 

而這個程序產生的50

所需的輸出如果由於某種原因,你需要存儲的值返回到一個無符號的變量,然後做了計算之外。由於上述原因,計算是使用帶符號的值執行的,這一點很重要。

.... 
var 
    Precision: Cardinal; 
begin 
    Precision := CalcPrecision(1000, True, True); 
    Writeln(Precision); 
    Readln; 
end. 

當然,你可以想出輸入值會溢出計算,即使它是使用有符號算術編寫的。但在實踐中,你會發現這種輸入是極不可能的。另一方面,當使用非常合理的輸入數據執行無符號運算時,可以很容易地將您的等式上移。

+0

@Bill我很想知道你不喜歡這個答案的是什麼。你可能不瞭解我所做的一點?或者你認爲我所說的不準確。 –

+0

我懷疑它可能是http://stackoverflow.com/questions/17266462/preventing-combining-signed-and-unsigned-types-widened-both-operands-compiler/17266550?noredirect=1#comment25029232_17266550。此外,我的第一個建議是切換到使用單一類型,如果第一個由於某種原因不可能,則使用BoolValue替代。 –

+0

@Ken算術總是可以使用有符號值。您可以輸入無符號值,並將結果存儲爲無符號值。我相信你知道這一點。但是如果你在無符號數字中進行算術運算,那麼預計會出現溢出問題。我猜這個問題在這裏:http://stackoverflow.com/questions/17001728/update-tlabels-in-omnithread和有一個復仇​​DV –

相關問題