好吧,我想知道编译器“读取”代码的顺序是哪一个。 例如:
假设我有以下代码段:
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进行打印。
按顺序,编译器“读取”的顺序是什么?我有一些老师告诉我编译器从右到左“读”,从分号(;),但编译器实际上有一个命令?如果我上面提到的事情是错误的,请纠正我。(我不会说英语很好)
谢谢!
答案 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;