- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在 Embarcadero Delphi 2010 中编写一个简单的应用程序。包含两个周期的简单代码:
procedure TForm1.Button1Click(Sender: TObject);
var
a:array [0..255] of integer;
i:integer;
k,q:integer;
begin
k:=0;
for I := 0 to 255 do
begin
a[i]:=i;
end;
for I := 0 to 255 do
begin
q:= a[i];
k:=k+q;
end;
Label1.Caption:=inttostr(k);
end;
根据 Watch List,在第二个循环中,变量“i”从值 256 开始,到 0 (256, 255, 254, ..., 0),但数组的元素是正确的 (0, 1, 2, 3 ,...)。变量“i”仅在本地声明,没有全局变量。为什么会出现这种情况?这是正常行为吗?
最佳答案
简短的回答是因为编译器优化。长答案是:
在您的 Pascal
中代码,整数I
有两个(实际上是三个)目的。首先,它是循环控制变量(或循环计数器),也就是说,它控制循环运行的次数。其次,它充当数组a
的索引。 。在第一个循环中,它还充当分配给数组元素的值。当编译为机器代码时,这些角色由不同的寄存器处理。
如果在编译器设置中设置了优化,编译器会创建将控制变量从起始值递减到零的代码,如果可以这样做,而不更改最终结果。之所以这样做,是因为可以避免与非零值进行比较,从而更快。
在下面对第一个循环的反汇编中,您可以看到变量 I
的作用处理为:
eax
充当循环控制变量和值分配给数组元素edx
是指向数组元素的指针(增加 4(字节)每转)反汇编:
Unit25.pas.34: for I := 0 to 255 do
005DB695 33C0 xor eax,eax // init
005DB697 8D9500FCFFFF lea edx,[ebp-$00000400]
Unit25.pas.36: a[i]:=i;
005DB69D 8902 mov [edx],eax // value assignment
Unit25.pas.37: end;
005DB69F 40 inc eax // prepare for next turn
005DB6A0 83C204 add edx,$04 // same
Unit25.pas.34: for I := 0 to 255 do
005DB6A3 3D00010000 cmp eax,$00000100 // comparison with end of loop
005DB6A8 75F3 jnz $005db69d // if not, run next turn
自 eax
有两个作用,必须向上计数。请注意,每个循环需要三个命令来管理循环计数: inc eax
, cmp eax, $00000100
和jnz $005db69d
.
在第二个循环的反汇编中,变量 I
的作用处理方式与第一个循环类似,除了 I
未分配给元素。因此循环控制仅充当循环计数器并且可以向下运行。
eax
是循环控制变量edx
是指向数组元素的指针(增加 4(字节)每转)反汇编:
Unit25.pas.39: for I := 0 to 255 do
005DB6AA B800010000 mov eax,$00000100 // init loop counter
005DB6AF 8D9500FCFFFF lea edx,[ebp-$00000400]
Unit25.pas.41: q:= a[i];
005DB6B5 8B0A mov ecx,[edx]
Unit25.pas.42: k:=k+q;
005DB6B7 03D9 add ebx,ecx
Unit25.pas.43: end;
005DB6B9 83C204 add edx,$04 // prepare for next turn
Unit25.pas.39: for I := 0 to 255 do
005DB6BC 48 dec eax // decrement loop counter, includes intrinsic comparison with 0
005DB6BD 75F6 jnz $005db6b5 // jnz = jump if not zero
请注意,在这种情况下,只需要两个命令来管理循环计数: dec eax
和jnz $005db6b5
.
在 Delphi XE7 中,在 Watches 窗口中,变量 I
在第一个循环期间显示为递增值,但在第二个循环期间显示为 E2171 Variable 'i' inaccessible here due to optimization
。在早期版本中,我记得它显示的是递减值,我相信您已经看到了。
关于Delphi "for ... to"语句从结束值运行到开始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35475622/
创建一个“海盗对话”,可以选择左手或右手。我希望它对“左”和“右”的不同拼写做出积极的回答(正如您将在代码中看到的那样),但是,当我为所有非“右”或“左”的输入添加最终的“else”代码时,它给了我一
With 语句 对一个对象执行一系列的语句。 With object statements End With 参数 object 必需的部分
While...Wend 语句 当指定的条件为 True 时,执行一系列的语句。 While condition  ; Version [stat
所以我正在处理的代码有一个小问题。 while True: r = input("Line: ") n = r.split() if r == " ":
我有一个对象数组: var contacts = [ { "firstName": "Akira", "lastName": "Laine", "number"
int main() { int f=fun(); ... } int fun() { return 1; return 2; } 在上面的程序中,当从main函数中调用一个
我的项目中有很多 if 语句、嵌套 if 语句和 if-else 语句,我正在考虑将它们更改为 switch 语句。其中一些将具有嵌套的 switch 语句。我知道就编译而言,switch 语句通常更
Rem 语句 包含程序中的解释性注释。 Rem comment 或 ' comment comment 参数是需要包含的注释文本。在 Rem 关键字和 comment 之间应有一个空格。
ReDim 语句 在过程级中声明动态数组变量并分配或重新分配存储空间。 ReDim [Preserve] varname(subscripts) [, varname(subscripts)]
Randomize 语句 初始化随机数生成器。 Randomize [number] number 参数可以是任何有效的数值表达式。 说明 Randomize 使用 number 参数初始
Public 语句 定义公有变量并分配存储空间。在 Class 块中定义私有变量。 Public varname[([subscripts])][, varname[([subscripts])
Sub 语句 声明 Sub 过程的名称、参数以及构成其主体的代码。 [Public [Default]| Private] Sub name [( arglist )]
Set 语句 将对象引用赋给一个variable或property,或者将对象引用与事件关联。 Set objectvar = {objectexpression | New classname
我有这个代码块,有时第一个 if 语句先运行,有时第二个 if 语句先运行。我不确定为什么会这样,因为我认为 javascript 是同步的。 for (let i = 0; i < dataObje
这是一个 javascript 代码,我想把它写成这样:如果此人回答是,则回复“那很酷”,如果此人回答否,则回复“我会让你开心”,如果此人回答的问题包含"is"或“否”,请说“仅键入”是或否,没有任何
这是我的任务,我尝试仅使用简短的 if 语句来完成此任务,我得到的唯一错误是使用“(0.5<=ratio<2 )”,除此之外,构造正确吗? Scanner scn = new Scanner(
有没有办法在 select 语句中使用 if 语句? 我不能在这个中使用 Case 语句。实际上我正在使用 iReport 并且我有一个参数。我想要做的是,如果用户没有输入某个参数,它将选择所有实例。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: If vs. Switch Speed 我将以 C++ 为例,但我要问的问题不是针对特定语言的。我的意思是一
Property Set 语句 在 Class 块中,声明名称、参数和代码,这些构成了将引用设置到对象的 Property 过程的主体。 [Public | Private] Pro
Property Let 语句 在 Class 块中,声明名称、参数和代码等,它们构成了赋值(设置)的 Property 过程的主体。 [Public | Private] Prop
我是一名优秀的程序员,十分优秀!