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。

4

2 回答 2

12

你所拥有的是一个类型化的常量。类型化的常量不同于普通常量(也就是真正的常量),这就是你constVar的。请注意您不需要在constVar;上指定类型。如果您有,您可能会看到编译器也允许您为其分配新值:

const
  constVar: Integer = 1;

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

与普通常量相反,可以在运行时为它们分配一个值。这是 Turbo Pascal 的一个旧概念,已被对初始化变量的支持所取代:有关详细说明,请参阅第4.4节,第183页。

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

对于已初始化的变量,请在声明中替换const为。var它会在进入范围后得到它的价值。$J或者,在 typed-constant 声明之前关闭指令:

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

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


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

于 2010-07-13T21:55:35.807 回答
0

好吧,如果你也知道 C,这里有一些类比:

在 [Turbo/Free] Pascal 中,编写如下内容:

const
     MIN = 5;
     MAX = 10;

等效于在 C 中执行此操作:

#define MIN 5
#define MAX 10

也就是说,就像其他海报所说的那样,它是一个编译时符号替换。

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

TODO:反例。

于 2012-04-21T04:05:25.663 回答