代码之家  ›  专栏  ›  技术社区  ›  kjack

delphi中的变量初始值

  •  6
  • kjack  · 技术社区  · 16 年前

    我相信局部整数变量在delphi中没有初始化为零。初始值是该内存位置的任何值。 因此,在下面的代码中,第一次单击按钮时,第一条消息显示一个整数值。 为什么第二次点击时,它不显示3,而是显示相同的整数 价值?每次我单击按钮时,它都会继续显示相同的整数值。只有当我停止并重新启动程序时,该值才会不同。 3存储在哪里,因为在程序的同一运行中每次单击按钮时,似乎都会使用相同的内存位置?

    procedure TForm1.Button1Click(Sender: TObject);
    
    var
    int1 : integer;
    
    begin
       showmessage(inttostr(int1)) ;
       int1 := 3;
    end;
    
    end.
    
    6 回复  |  直到 16 年前
        1
  •  12
  •   Lieven Keersmaekers    16 年前

    kjack,

    它包含当时堆栈帧中的任何值。在您的情况下,这将是发件人。如果你取整数并将其类型转换为对象,你会注意到“模式”。

    procedure TForm1.Button1Click(Sender: TObject);
    
    var
    int1 : integer;
    
    begin
       ShowMessage(TObject(int1).ClassName);
       showmessage(inttostr(int1)) ;
       int1 := 3;
    end;
    
    end.
    
        2
  •  5
  •   Community CDub    8 年前

    首先,你是对的,局部变量 aren't initialised .

    你也不能保证 int1 每次调用时都存储在相同的内存位置。在这种情况下,您每次看到相同值的原因可能是 使用相同的位置(偶然),但Delphi编译器已经优化了你的最终

    int1 := 3;
    

    声明,因为它没有效果。(您可以添加另一个 showmessage(inttostr(int1)) 在那条线之后打电话,看看是否有什么不同。)另一种可能性是,用于 int1 在对按钮处理程序的调用之间(例如在Windows消息循环中)重复使用,并且恰好总是将其重置为您看到的值。

        3
  •  2
  •   mghie    16 年前

    为了测试这一点,您可以添加另一个带有OnClick处理程序的按钮,该处理程序调用的方法具有比ShowMessage()更多的参数。如果在两次单击Button1之间单击该按钮,int1的值确实应该会发生变化。这是因为Button1Click()中int1的堆栈位置将用于其他处理程序中的一个参数,并被覆盖。

    应该优化分配,你可以看到这一点,因为线条在空白区域不应该有蓝点。还应该有编译器提示。

    编辑: 正如您所评论的,当点击另一个按钮时,行为似乎没有变化。由此,我只能假设VCL代码(在调用OnClick处理程序之前执行)使用了如此多的堆栈空间,以至于int1的内存位置总是用一些(稳定的)值初始化。此代码总是相同的,因此如果所涉及对象(应用程序、父窗体和按钮)的地址没有改变,则值也将保持不变。OTOH重启应用程序将在未初始化的局部变量中产生一个新的、同样稳定的值。

    请注意,这完全取决于在处理程序之前执行的VCL代码,因此对VCL的更改也可能会改变它。甚至可能是各种Delphi版本的行为已经不同了。

        4
  •  1
  •   Toon Krijthe    16 年前

    局部变量位于堆栈帧中。而且它们没有初始化。

    如果你访问一个方法两次,那么堆栈指针就有可能是euqal,它给出了相同的值。

    例子:

    调用前堆栈:

    > More stack  (memory location X)
    

    如果调用Button1Click,堆栈如下:

    > Int1
    > Return address
    > Sender
    > Self pointer
    > More stack  (memory location X)
    

    如果下一次调用Button1Click时,堆栈指针仍在位置X上,并且没有其他函数更改了值,您将为Int1找到相同的值。

    如果你有安全的信息,清除局部变量总是明智的(但你有机会让优化器删除这些状态。所以你需要禁用优化)。

    为了好玩,添加另一个按钮:

    procedure TForm1.Button2Click(Sender: TObject);
    var
      int1 : integer;
    begin
      showmessage(inttostr(int1)) ;
      int1 := 777;
    end;
    

    并检查:

    • 单击1:垃圾
    • 再次单击1:3
    • 单击2:3
    • 单击1:777
        5
  •  1
  •   Vegar    16 年前

    你希望它是一样的吗?如果是这样,你可以使用局部const:

    procedure TForm1.Button1Click(Sender: TObject);
    const
      i: integer = 0;
    begin
      i := i + 1;
      edit1.text := intToStr(i);
    end;
    

    不过,您必须确保“可分配类型常量”已打开。

        6
  •  0
  •   oɔɯǝɹ    16 年前

    初始化变量可能由内存管理器完成,也可能不由其完成。