Bil*_*ill 4 delphi delphi-2010
此代码用于设置组件,生成编译器警告:
[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);
Run Code Online (Sandbox Code Playgroud)
这可以以某种方式进行类型转换以防止编译器警告吗?
在你的情况下,ord()返回integer,所以必须明确地键入式浇铸cardinal,通过改变ord()成cardinal()这样:
iPrecision := Max(50, 100 - (3 + 2 * cardinal(iActive and iInProximity)) * iRadius);
Run Code Online (Sandbox Code Playgroud)
你将摆脱警告,你的代码将几乎相同.
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.
Run Code Online (Sandbox Code Playgroud)
我相信你会希望这个程序的输出是50.但事实并非如此.输出为4294962396.
发生的事情是你100-X在无符号的上下文中执行X>100.执行此操作时,您将获得整数溢出,结果是一个非常大的正值.由于您使用的是无符号算术,因此无法将此值视为负值,因为unsigned中没有负值.
当然,如果启用了溢出检查的编译器选项,则会遇到运行时错误.但即使这不是你想要的.获得所需答案的简单方法是使用带符号算术执行操作.
{$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.
Run Code Online (Sandbox Code Playgroud)
并且该程序产生50的期望输出.
如果由于某种原因,您需要将值存储回无符号变量,那么在计算之外执行此操作.由于上述原因,重要的是使用有符号值执行计算.
....
var
Precision: Cardinal;
begin
Precision := CalcPrecision(1000, True, True);
Writeln(Precision);
Readln;
end.
Run Code Online (Sandbox Code Playgroud)
当然,即使是使用带符号算术编写的输入值,也可以提出会超出计算量的输入值.但在实践中,你会发现这种输入极不可能.另一方面,当使用非常合理的输入数据执行无符号时,很容易使方程式跳闸.
| 归档时间: |
|
| 查看次数: |
2976 次 |
| 最近记录: |