C
语言中的
for
语句使用最为灵活,不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况。因此,这个语句的使用频率是最高的,当然它的处理情况比上面两种循环要复杂一些。它的形式如下:
for(
表达式
1;
表达式
2;
表达式
3)
语句
1
它的执行过程是先求解表达式
1
的值,然后再计算表达式
2
的值。如果其值为真,就执行语句
1
,然后再执行表达式
3
。如果其值为假,就直接跳出循环不再执行语句
1
和表达式
3
。如果在
C
++里还会有作用域的范围不同样的。
下面就是
LCC
处理
for
循环的代码:
#023 case FOR:
#024 forstmt(genlabel(4), swp, lev + 1);
#025 break;
第
24
行是调用函数
forstmt
来处理
for
语句。
而函数
forstmt
的代码如下:
#001 static void forstmt(int lab, Swtch swp, int lev)
#002 {
#003 int once = 0;
#004 Tree e1 = NULL, e2 = NULL, e3 = NULL;
#005 Coordinate pt2, pt3;
#006
#007 t = gettok();
#008 expect('(');
#009 definept(NULL);
#010
#011 if (kind[t] == ID)
#012 e1 = texpr(expr0, ';', FUNC);
#013 else
#014 expect(';');
#015
#016 walk(e1, 0, 0);
#017 pt2 = src;
#018 refinc *= 10.0;
#019
第
7
行获取下一个记号。也就是
for
单词后面的左括号开始记号。
第
8
行就是处理左括号。
第
9
行创建了执行点。
第
11
行是判断是否有第一个表达式,如果有就进入第
12
行处理,调用函数
texpr
来处理表达式
1
,并生成树
e1
返回来。如果没有表达式
1
,就在第
14
行直接处理下一个分号。
#020 if (kind[t] == ID)
#021 e2 = texpr(conditional, ';', FUNC);
#022 else
#023 expect(';');
#024
第
20
行是判断第二个表达式是否存在,如果存在就调用函数
texpr
来处理第二个表达式。如果不存在就在第
23
行里处理下一个分号。
#025 pt3 = src;
#026 if (kind[t] == ID)
#027 e3 = texpr(expr0, ')', FUNC);
#028 else
#029 {
#030 static char stop[] = { IF, ID, '}', 0 };
#031 test(')', stop);
#032 }
#033
第
26
行是判断第三个表达式是否存在,如果存在就调用函数
texpr
来处理第三个表达式。如果不存在,就需要处理右括号了。
#034 if (e2)
#035 {
#036 once = foldcond(e1, e2);
#037 if (!once)
#038 branch(lab + 3);
#039 }
#040
第
34
行是判断第二个表达式是否存在,如果存在就查找循环是否需要执行一次,如果不需要执行就跳到第三个标号。
#041 definelab(lab);
#042 statement(lab, swp, lev);
#043
#044 definelab(lab + 1);
#045 definept(&pt3);
第
41
行是定义第一个标号。
第
42
行是处理循环体的语句
1
。
第
44
行是定义第二个标号。
#046 if (e3)
#047 walk(e3, 0, 0);
#048
#049 if (e2)
#050 {
#051 if (!once)
#052 definelab(lab + 3);
#053 definept(&pt2);
#054 walk(e2, lab, 0);
#055 }
#056 else
#057 {
#058 definept(&pt2);
#059 branch(lab);
#060 }
#061
#062 if (findlabel(lab + 2)->ref)
#063 definelab(lab + 2);
#064
#065 }
第
46
行和第
47
行是计算第三个表达式。
第第
49
行到第
55
行是处理第二个表达式,如果第二个表达式值为真就需要跳转到第一个标号运行语句。
第
52
行是生成第
4
个标号,由于不能判断是否需要运行一次时,就需要计算表达式的值,才能决定。
第
57
行到第
60
行是没有第二个表达式,所以无条件跳到第一个标号那里继续运行语句
1
。
通过运行上面的代码就会生成下面形式的汇编代码:
表达式
1
标号
1
:语句
1
标号
2
:表达式
3
标号
4
:如果表达式
2
值不等于
0
就跳到标号
1
标号
3
:
上面的优化代码,如果当常量判断表达式
2
要运行一次时,就直接从标号
1
开始运行了,不用跳到标号
4
作一次判断。如果不是常量判断出来的,就需要多一个跳转,先跳到标号
4
那里运行,作表达式
2
的计算再作出选择。