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.
當然,你可以想出輸入值會溢出計算,即使它是使用有符號算術編寫的。但在實踐中,你會發現這種輸入是極不可能的。另一方面,當使用非常合理的輸入數據執行無符號運算時,可以很容易地將您的等式上移。
我選擇嘗試後者,因爲iPrecision和iRadius是我無法更改的組件屬性...但我仍然收到警告。 – Bill
我想現在我會使用{$ WARNINGS OFF}和{$ WARNINGS ON} – Bill
@Bill:檢查我的編輯到「BoolValues」的聲明。我測試並編譯了我發佈的代碼,並生成零警告。不要放棄這麼快。 :-) –