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
?
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
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:
array of Cardinal
to array[0..15] of Cardinal
[
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With