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

delphi中的可变初值

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

    因此,在下面的代码中,第一次单击按钮时,第一条消息显示一个整数值。 在同一程序运行中每次单击按钮时,都会使用相同的内存位置,因此3存储在何处?

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

    它包含当时堆栈帧中的任何值。在您的情况下,这将是发件人。如果你把整数输入一个对象,你会注意到“模式”。

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

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

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

    int1 := 3;
    

    声明,因为它没有效力。(您可以添加另一个 showmessage(inttostr(int1)) 在那一行之后调用,看看这是否有区别。)另一种可能是用于 int1

        3
  •  2
  •   mghie    15 年前

    只有在两次单击Button1之间不执行其他代码时,才会出现这种情况,最重要的是,这些代码使用的堆栈空间与到达过程TForm1的代码相同(或更多)。Button1Click()使用的堆栈空间相同。除非覆盖堆栈上的值,否则它们仍将包含相同的值。

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

    分配应该被优化掉,你可以看到这一点,因为线不应该在边沟区域有蓝点。还应该有一个编译器提示。

    编辑:

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

        4
  •  1
  •   Toon Krijthe Paul    15 年前

    局部变量位于堆栈框架中。并且它们没有初始化。

    调用前堆栈:

    > 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    15 年前

    你希望它是一样的吗?如果是这样,您可以使用本地常量:

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

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

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

    我认为任何内存管理器都可以将所有变量初始化为零(0x000)。这也是在.Net中完成的。