这是编译器编译的顺序

时间:2013-12-20 23:48:24

标签: c++ c compiler-construction compilation

好吧,我想知道编译器“读取”代码的顺序是哪一个。 例如:

假设我有以下代码段:

int N, M;

N = M = 0;

在这种情况下,编译器会为N和M分配一部分内存(int,4个字节),然后在第二行(我怀疑的地方)分配两个东西,一个:

编译器“读取”N等于M并等于零。

OR

编译器“读取”零,将其放入M的内存中,然后获取M的值,即零,并将其放在N的内存中。

换句话说,它是从右到左,还是从左到右?

我不知道我是否明白我的怀疑,但是在我做的测试中:

int i=0; /*I declared the variable i, and assign zero value to it*/

printf("%d", i++); /*Prints 0*/

printf("%d", i); /*Prints 1*/

我理解上面的代码,在第二行,编译器似乎(从我的不好)从左到右“读取”,指定类型%d的i值,并且在打印之后,变量i递增,因为在第三行它打印为1。

下面的代码片段颠倒了++的位置:

int i=0; /*I declared i variable to zero*/

printf("%d", ++i); /*Prints 1*/

printf("%d", i); /*Prints 1*/

在这种情况下,在第二行,(从我理解的)编译器从左到右“读取”,当编译器读取将要打印的内容时(保留在逗号后面,这是什么名字) space?),首先“读取”++并将变量增加到i,在这种情况下是i,然后分配给%d进行打印。

按顺序,编译器“读取”的顺序是什么?我有一些老师告诉我编译器从右到左“读”,从分号(;),但编译器实际上有一个命令?如果我上面提到的事情是错误的,请纠正我。(我不会说英语很好)

谢谢!

4 个答案:

答案 0 :(得分:2)

只有lexical anaylizer从左到右读取源代码。语法分析器构建AST并以各种方式读取它们,具体取决于它找到的特定节点。

对于表达式,可以按顺序读取保存表达式的AST,以生成后缀表达式,更适合基于堆栈的求值程序(最容易实现)。

对于赋值(确实是表达式),AST首先读取并生成代码,然后是LHS,然后生成写入内存指令。

对于函数调用,可以从包含参数表达式的最后一个节点解析AST到第一个节点(如果使用C调用约定来执行调用)。

答案 1 :(得分:2)

I understand the above code, at the second line, the compiler seems(from what i undestood)"read" from left to right, assigning to the type %d the i value, and after print, the variable i is incremented, because at the third line it is printed as 1.

这不是正在进行的事情。

当你调用i ++时,i会增加1.然后返回增量发生前的值。

所以你的:printf("%d", i++)

实际上在做:

int i = somevalue;
int temp = i;
i = i + 1;
printf("%d", temp);

打印后我没有增加。它实际上是在打印之前。

当你这样做时:printf("%d", ++i)

它确实:

int i = somevalue;
i = i + 1;
printf("%d", i);

区别在于临时变量。 在这种情况下,你的老师是正确的,它是从分号从右到左,因为:

必须首先处理I的值。然后它可以打印出来。 实际上,如果你按照每个操作或指令将它全部分成一个单独的行,它实际上是从上到下,如上所示。

答案 2 :(得分:1)

根据C ++标准(和C标准)

  

赋值运算符(=)和复合赋值运算符all   从右到左分组。

所以在这个陈述中

N = M = 0;

编译器将0分配给M并指定标准

  

返回一个引用左操作数

的左值

在您的示例0中,在tuen中将其分配给N。

答案 3 :(得分:1)

对于经验证据,我编译:     int M,N;     N = M = 0;

没有编译器选项,在我的Mac上并反汇编它:

0000000100000f10    pushq   %rbp
0000000100000f11    movq    %rsp,%rbp
0000000100000f14    movl    %edi,0xfc(%rbp)
0000000100000f17    movq    %rsi,0xf0(%rbp)
0000000100000f1b    movl    $0x00000000,0xe4(%rbp)
0000000100000f22    movl    0xe4(%rbp),%eax
0000000100000f25    movl    %eax,0xe0(%rbp)
0000000100000f28    movl    $0x00000000,0xe8(%rbp)
0000000100000f2f    movl    0xe8(%rbp),%eax
0000000100000f32    movl    %eax,0xec(%rbp)
0000000100000f35    movl    0xec(%rbp),%eax
0000000100000f38    popq    %rbp
0000000100000f39    ret

所以看起来编译器决定将其编译为:     N = 0;     M = 0;