【问题标题】:Constant `array of cardinal` produces error 'Constant expression violates subrange bounds"常量“基数数组”产生错误“常量表达式违反子范围界限”
【发布时间】:2019-02-23 07:38:58
【问题描述】:

为什么是下面的代码:

const
  ANSICOLORS: array of cardinal = [
    $000000,//0
    $800000,//1, compilation error starts with this value
    $008000,//2
    $808000,//3
    $000080,//4
    $800080,//5
    $008080,//6
    $D0D0D0,//7
    $3F3F3F,//8
    $FF0000,//9
    $00FF00,//A
    $FFFF00,//B
    $0000FF,//C
    $FF00FF,//D
    $00FFFF,//E
    $FFFFFF];//F

在Delphi XE4(win32和win64)下会产生如下编译错误:

[dcc32 错误] Debug.pas(66): E1012 常量表达式违反子范围界限

$800000不是在Cardinal的范围内吗?

【问题讨论】:

    标签: delphi compiler-errors delphi-xe4


    【解决方案1】:

    您正在使用 XE7 中引入的功能。

    声明一个动态数组常量。

    Dynamic arrays_Delphi xe7

    String-Like_Operations_Supported_on_Dynamic_Arrays


    在 XE4 中,这被评估为一个集合,其中序数不能超过 255。

    因此出现错误E1012 Constant expression violates subrange bounds

    通过声明来修复它:

    const
      ANSICOLORS: array[0..15] of cardinal = (
        $000000,//0
        $800000,//1, 
        $008000,//2
        $808000,//3
        $000080,//4
        $800080,//5
        $008080,//6
        $D0D0D0,//7
        $3F3F3F,//8
        $FF0000,//9
        $00FF00,//A
        $FFFF00,//B
        $0000FF,//C
        $FF00FF,//D
        $00FFFF,//E
        $FFFFFF);//F
    

    【讨论】:

      【解决方案2】:

      从内存的角度来看,$800000确实在Cardinal的范围内。

      我认为Cardinal($800000) 类型转换会修复它,但它没有。

      Delphi XE7 及更高版本实际上可以正确编译您的代码。

      这也失败了,直到 Delphi XE6 出现同样的错误:

      const
        CardinalArray: array of Cardinal = [257];
      

      我认为原因是 Delphi 编译器将 [257] 视为 set,尽管左侧表明它应该是 array

      这在 XE4 中失败,但在 XE7 及更高版本中编译正常:

      program Cardinals;
      
      {$APPTYPE CONSOLE}
      
      uses
        System.SysUtils;
      
      const
        CardinalArray: array of Cardinal = [257]; // fails until Delphi XE4 with "E1012 Constant expression violates subrange bounds"
      
      const
        ANSICOLORS: array of Cardinal = [
          $000000,//0
          $800000,//1, compilation error starts with this value
          $008000,//2
          $808000,//3
          $000080,//4
          $800080,//5
          $008080,//6
          $D0D0D0,//7
          $3F3F3F,//8
          $FF0000,//9
          $00FF00,//A
          $FFFF00,//B
          $0000FF,//C
          $FF00FF,//D
          $00FFFF,//E
          $FFFFFF];//F
      
      var
        AnsiColor: Cardinal;
      
      begin
        try
          for AnsiColor in AnsiColors do
            Writeln(Format('$%6.6x', [AnsiColor]));
        except
          on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
        end;
      end.
      

      输出:

      $000000
      $800000
      $008000
      $808000
      $000080
      $800080
      $008080
      $D0D0D0
      $3F3F3F
      $FF0000
      $00FF00
      $FFFF00
      $0000FF
      $FF00FF
      $00FFFF
      $FFFFFF
      

      如果您可以使用非动态数组,那么下面的示例适用于 Delphi XE4(我早在 Delphi 2007 就对其进行了测试,对于 XE 及更早版本,您必须将 System.SysUtils 替换为 SysUtils) )。

      注意开关:

      • array of Cardinalarray[0..15] of Cardinal
      • []()
      program Cardinals;
      
      {$APPTYPE CONSOLE}
      
      //{$R *.res}
      
      uses
        System.SysUtils;
      
      const
        ANSICOLORS: array[0..15] of Cardinal = (
          $000000,//0
          $800000,//1, compilation error starts with this value
          $008000,//2
          $808000,//3
          $000080,//4
          $800080,//5
          $008080,//6
          $D0D0D0,//7
          $3F3F3F,//8
          $FF0000,//9
          $00FF00,//A
          $FFFF00,//B
          $0000FF,//C
          $FF00FF,//D
          $00FFFF,//E
          $FFFFFF);//F
      
      var
        AnsiColor: Cardinal;
      
      begin
        try
          for AnsiColor in AnsiColors do
            Writeln(Format('$%6.6x', [AnsiColor]));
        except
          on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
        end;
      end.
      

      【讨论】:

      • 我从我仍然拥有的命令行编译器运行它,指示 14.0 和 15.0,所以我假设 XE4 和 XE5。感谢您验证它。修正了答案。
      • XE5编译器版本为26.0,BDS版本为12.0。这意味着 *\RAD Studio\14.0\bin 包含 XE6 而 *\15.0\bin 包含 XE7。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多