为什么Pascal中的常量数组实际上不是常量?

11
  Program ConstTest;
  Const constVar = 1;
  Begin
    constVar := 3;
    WriteLn(constVar);
  End.

很明显上面的代码无法编译,因为更改常量的值是不合适的。 但是以下代码可以编译,并且会返回"1; 5; 3;",即使数组是const类型的:

Program ConstTest;
  Const constArr:Array [1..3] Of ShortInt = (1,2,3);
  Var i:ShortInt;
  Begin
    constArr[2] := 5;
    For i:=1 To 3 Do WriteLn(constArr[i],'; ');
  End.

那么,是什么导致了这种行为?为什么一个常量实际上不是常量?

我正在使用Win32的FreePascal编译器2.2.0。


请参阅 https://dev59.com/MXVD5IYBdhLWcg3wNY5Z 和 https://dev59.com/F3E85IYBdhLWcg3wkkY8。 - Andreas Rejbrand
2个回答

12

你拥有的是一个类型常量。类型常量不同于普通常量(也称为真常量),后者是你的constVar。请注意,你不需要在constVar上指定类型;如果你这样做了,你可能会发现编译器也允许你给它分配新值:

const
  constVar: Integer = 1;

Free Pascal手册描述了类型常量:

与普通常量不同的是,可以在运行时为它们分配值。这是Turbo Pascal中的一个古老概念,已被初始化变量支持所取代:有关详细信息,请参见第4.4节,第183页。

将值赋给类型常量的支持由{$J}指令控制:它可以被关闭,但默认情况下是开启的(为了与Turbo Pascal兼容)。始化变量始终是允许的。

对于已初始化的变量,在声明中用var替换const。它会在进入作用域时获取其值。或者,在声明类型常量之前关闭$J指令:

{$J-}
const
  constArr: array [1..3] of ShortInt = (1, 2, 3);
{$J+}

至于是否之后重新打开它,这取决于您。


由于它们存储在内存中的方式,因此可修改类型常量。实际上,正是因为它们被存储在内存中,所以最初是可以修改的。普通常量不作为独立的对象存储在内存中。当编译器遇到在程序中使用的普通常量时,它会将其替换为常量的值,就像您在其位置使用文字一样。另一方面,类型常量位于内存中的自己位置,在代码中引用一个类型常量时,其值从内存中读取,就像使用任何其他变量一样。当没有可用于字面意义的语法时,可以使用类型常量——例如,您不能有数组或记录字面意义。


0

好的,如果你也了解C语言,这里有一些类比:

在[Turbo/Free] Pascal中,编写以下代码:

const
     MIN = 5;
     MAX = 10;

相当于在C中执行以下操作:

#define MIN 5
#define MAX 10

也就是说,它是像其他帖子所说的编译时符号替换。

对于记录和数组(类型常量),"const" 表达式只是一种初始化与链接器符号关联的内存块的方法。

待办事项:反例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接