You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi的array of const中识别Cardinal类型?

问题分析

Delphi 的 array of const 依赖 TVarRec 类型存储参数,但 TVarRec 的 VType 枚举中没有专门的 vtCardinal 类型。由于 Cardinal 和 Integer 是同内存大小的无符号/有符号整数,编译器会将 Cardinal 隐式转换为 Integer 存入 VInteger 字段,导致超过 Integer 最大值的 Cardinal 值被解析为负数。

解决方案

以下提供两种实用的解决方式:

方案1:修改 vtInteger 分支的处理逻辑

在现有 vtInteger 分支中,判断值是否为负数(对应超出 Integer 范围的 Cardinal 值),将其转换为 Cardinal 类型输出,无需修改调用代码:

{$APPTYPE CONSOLE}

uses
  SysUtils;

procedure GetSomething(const Input: array of const);
var
  LIndex: Integer;
begin
  for LIndex := Low(Input) to High(Input) do
  begin
    case Input[LIndex].VType of
      vtWideString: Writeln('WideString = ''', WideString(Input[LIndex].VWideChar), '''');
      vtInt64: Writeln('Int64 = ', Input[LIndex].VInt64^);
      vtCurrency: Writeln('Currency = ', CurrToStr(Input[LIndex].VCurrency^));
      vtInteger: 
        begin
          if Input[LIndex].VInteger < 0 then
            Writeln('Cardinal = ', Cardinal(Input[LIndex].VInteger))
          else
            Writeln('Integer = ', Input[LIndex].VInteger);
        end;
      vtBoolean: Writeln('Boolean = ', BoolToStr(Input[LIndex].VBoolean, True));
      vtChar: Writeln('Char = ''', Input[LIndex].VChar, '''');
      vtExtended: Writeln('Extended = ', FloatToStr(Input[LIndex].VExtended^));
      vtString: Writeln('ShortString = ''', Input[LIndex].VString^, '''');
      vtPChar: Writeln('PChar = ''', Input[LIndex].VPChar, '''');
      vtAnsiString: Writeln('AnsiString = ''', Ansistring(Input[LIndex].VAnsiString), '''');
      vtWideChar: Writeln('WideChar = ''', Input[LIndex].VWideChar, '''');
      vtPWideChar: Writeln('PWideChar = ''', Input[LIndex].VPWideChar, '''');
      vtUnicodeString : Writeln('UnicodeString = ''', string(Input[LIndex].VUnicodeString), '''');
    else
      Writeln('Unsupported');
    end;
  end;
end;
var
  x: cardinal;
begin
  x := 3147483647;
  try
    GetSomething(['some string', 123, x, 'something else', 12.3, false]);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

输出结果:

UnicodeString = 'some string'
Integer = 123
Cardinal = 3147483647
UnicodeString = 'something else'
Extended = 12,3
Boolean = False

方案2:调用时显式转换为 Int64

将 Cardinal 值转换为 Int64 后传入,此时会被识别为 vtInt64 类型,在对应分支中处理为 Cardinal:

// 调用处修改
GetSomething(['some string', 123, Int64(x), 'something else', 12.3, false]);

// GetSomething 中的 vtInt64 分支修改
vtInt64:
  begin
    if (Input[LIndex].VInt64^ >= 0) and (Input[LIndex].VInt64^ <= Cardinal(High(Integer)) + 1) then
      Writeln('Cardinal = ', Cardinal(Input[LIndex].VInt64^))
    else
      Writeln('Int64 = ', Input[LIndex].VInt64^);
  end;

这种方式更适合需要明确区分 Int64 和 Cardinal 的场景。

内容的提问来源于stack exchange,提问作者HobitZlobny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:45:38