clq
浏览(10) +
2025-01-09 20:46:04 发表
编辑
关键字:
[2025-01-10 13:19:33 最后更新]
lazarus 的一个超级大 bug
某些语言下不要直接将整数强制转换成浮点数,这在 c/c++ 系语言中是常规操作,但在其他语言中可能产生致命的 bug 。
--------------------------------------------------------
当单元代码使用
{$mode delphi}
编译模式时会发生同整数强制转换为浮点数的诡异 bug 。我查了好久才发现是这个原因,非常的隐蔽。
//理论上它的结果应该是显示 "7"
ShowMessage(FloatToStr(double(7))); //这段代码其实来自 golang ,在 lazarus 的 delphi 兼容模式下会出错
//如果切换回默认 ObjFPC 模式是正确的
在 delphi 编译模式下这并不会是 7 ,明天我把视频发上来。
而且说是 delphi 模式的问题,但实际上至少在 delphi 7 下时是编译不了这段代码的。相当于 delphi 不推荐/不允许将整数强制转换为浮点数。
更为诡异的是,如果你把强制转换去掉,它不但能编译而且结果是正确的!如下这样
ShowMessage(FloatToStr((7))); //这样在哪种模式下都是正确的
所以 pascal 系下,如果 c 系代码写习惯了,一定要记住不要直接将整数强制转换为 浮点数 。
不过为什么要用 delphi 编译模式,不用默认的呢。这是因为默认情况下的结构体等访问成员变量的代码可能会无法编译通过。这种 bug 就像 c 系整数除整数的结果不会是小数,而仍然是整数一样,和我们想当然的数学知识完全不同。
--
冷门小知识点,某些语言下不要直接将整数强制转换成浮点数。
一般是用 trunc() , Round() 等函数来来转换。
--------------------------------------------------------
var
i:integer;
f:double;
begin
f := i; //这样在 delphi 7 下是正确的
f := double(i); //这在 delphi 7 下会编译错误,在 lazarus 的 delphi 模式下会编译通过,但结果是错误的
--------------------------------------------------------
总结,直接赋值整数给浮点数是正确的。强制转换成浮点后再赋值就可能会出错。所以可以考虑做一个专门的转换函数
function IntToFloat(value: Integer): Double;
begin
Result := value;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//理论上它的结果应该是显示 "7"
ShowMessage(FloatToStr(double(7))); //这段代码其实来自 golang ,在 lazarus 的 delphi 兼容模式下会出错
//如果切换回默认 ObjFPC 模式是正确的
ShowMessage(FloatToStr(IntToFloat(7))); //所以最好是自己定义一个转换函数,这样就是正确的
end;
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.