[英]which is the order that a compiler compiles
好吧,我想知道编译器“读取”代码的顺序是哪一个。 例如:
假设我有以下代码片段:
int N, M;
N = M = 0;
在这种情况下,编译器将为N和M分配内存的一部分(int,4个字节),然后在第二行(我怀疑的地方)分配两个东西,一个:
编译器“读”N等于M并等于零。
要么
编译器“读取”零,将其放入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*/
在这种情况下,在第二行,(从我的理解),编译器从左到右“读取”,当编译器读取将要打印的内容(保留在逗号后面,这个空间的名称是什么?) ,首先“读取”++并在下面增加变量,在这种情况下是i,然后分配给%d进行打印。
按顺序,这是编译器“读取”的顺序? 我有一些老师告诉我编译器从右到左“读”,从分号(;),但编译器实际上有一个命令? 如果我上面说的是错的,请纠正我。(我不会说英语很好)
谢谢!
只有lexical anaylizer从左到右读取源代码。 语法分析器构建AST并以各种方式读取它们,具体取决于它找到的特定节点。
对于表达式,保持表达式的AST可以按顺序读取,以生成后缀表达式,更适合于基于堆栈的求值程序(最容易实现)。
对于赋值(确实是表达式),AST首先读取并生成代码,然后为LHS生成代码,然后生成写入到内存的指令。
对于函数调用,可以从包含参数表达式的最后一个节点解析AST到第一个节点(如果使用C调用约定来执行调用)。
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);
差异是临时变量。 在这种情况下,你的老师是正确的,它是从分号从右到左的,因为:
它必须首先处理我的价值。 然后它可以打印出来。 实际上,如果你按照每个操作或指令将它全部分解为一个单独的行,它实际上是从上到下,如上所示。
根据C ++标准(和C标准)
赋值运算符(=)和复合赋值运算符都是从右到左分组。
所以在这个声明中
N = M = 0;
编译器指定0到M并且符合标准
返回一个引用左操作数的左值
这是在你的例子0中,在tuen被分配给N.
对于经验证据,我编译: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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.