Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant `array of cardinal` produces error 'Constant expression violates subrange bounds"

Why the following code:

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

Would produce the following compilation error under Delphi XE4 (both win32 and win64):

[dcc32 Error] Debug.pas(66): E1012 Constant expression violates subrange bounds

Isn't value $800000 within the range of Cardinal?

like image 467
Edwin Yip Avatar asked Feb 23 '19 07:02

Edwin Yip


2 Answers

You are using a feature introduced in XE7.

Declaring a dynamic array constant.

Dynamic arrays_Delphi xe7 and

String-Like_Operations_Supported_on_Dynamic_Arrays


In XE4, this is evaluated as a set, where the ordinality cannot exceed 255.

Hence the error E1012 Constant expression violates subrange bounds

Fix it by declaring:

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
like image 137
LU RD Avatar answered Nov 13 '22 22:11

LU RD


From a memory perspective, $800000 indeed is within the range of Cardinal.

I thought it the Cardinal($800000) typecast would fix it, but it doesn't.

Delphi XE7 and up actually compile your code correctly.

This also fails up until Delphi XE6 with the same error:

const
  CardinalArray: array of Cardinal = [257];

I think the reason is that the Delphi compiler sees [257] as a set, despite the left side indicating it is supposed to be an array.

This fails in XE4, but compile fine in XE7 and up:

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.

Output:

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

If you can live with a non-dynamic array, then the below example works in Delphi XE4 (I tested it as far back as Delphi 2007, for XE and earlier, you have to replace System.SysUtils with SysUtils)).

Note the switches:

  • from array of Cardinal to array[0..15] of Cardinal
  • from [ and ] to ( and )
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.
like image 21
Jeroen Wiert Pluimers Avatar answered Nov 13 '22 23:11

Jeroen Wiert Pluimers