我试图理解编译器是如何从表达式i=i 1中“看到”i 1部分的。我理解i=3就是把值3放在变量I的位置内存里。
我对i=i1的猜测是,编译器期望从“=”运算符的右侧得到一个值,因此它从变量i的位置内存中获取值(赋值后为3)并将其加1,“i1”表达式(31=4)的最终结果作为值存储回变量i的位置内存中。这是正确的吗?
如果是,这意味着“=”运算符右侧的任何变量/变量和文字的组合将始终被替换为存储在其中的值,并且这些值可以与来自其他变量/文字的值相加/相减等(如在x 1表达式中),而这些计算的最终结果也将是文字值(例如:5、文字字符串等),并且也将像值一样存储在“=”运算符左侧的单个变量中。
我也很好奇这段代码在汇编中是怎么看到的,i ( i = i 1)的这个增量主要有哪些操作;
#include <stdio.h>
int main()
{
int i = 3;
i = i + 1; // i should have the value of 4 stored back in it;
return 0;
}
这不适用于一般情况。这取决于目标平台。如果您想检查程序集,可以使用-S
参数和gcc
进行检查。当我对你的代码这样做时,它给了我这个:
/tmp$ cat main.s
.file "main.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $3, -4(%rbp)
addl $1, -4(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 9.2.1-8) 9.2.1 20190909"
.section .note.GNU-stack,"",@progbits
对这里发生的事情进行简短的解释。首先,我们推送堆栈指针的值。这样我们以后就可以跳回去。
.cfi_startproc
pushq %rbp
然后我们用这段代码设置堆栈框架。它对应于声明变量。
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
然后我们有了这个。评论是我的。
movl $3, -4(%rbp) # i = 3;
addl $1, -4(%rbp) # i = i + 1;
最后,我们从主函数返回
movl $0, %eax # Store 0 in the "return register"
popq %rbp # Restore stackpointer
.cfi_def_cfa 7, 8
ret # return
请注意,线条之间没有1-1的关系。即使是非常简单的线条也不行。
另请注意,C 对程序的可观察行为施加要求,而不是对生成的程序集施加要求。例如,编译器可能会删除 main 函数的整个主体,因为变量 i
没有以可观察的方式使用。如果您使用优化,它会。当我使用 -O3
重新编译您的代码时,我得到了这个:
/tmp/$ cat main.s
.file "main.c"
.text
.section .text.startup,"ax",@progbits
.p2align 4
.globl main
.type main, @function
main:
.LFB11:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
.LFE11:
.size main, .-main
.ident "GCC: (Debian 9.2.1-8) 9.2.1 20190909"
.section .note.GNU-stack,"",@progbits
问题内容: 被Java编译过程弄糊涂 好的,我知道这一点:我们编写Java源代码,与平台无关的编译器将其转换为字节码,然后与平台相关的jvm将其转换为机器代码。 因此,从一开始,我们就编写Java源代码。编译器javac.exe是.exe文件。.exe文件到底是什么?Java编译器不是用Java编写的,然后为什么会有执行该文件的.exe文件?如果编译器代码是用Java编写的,那么在编译阶段如何执行
至少在GCC中,如果我们提供生成汇编代码的选项,编译器会通过创建一个包含汇编代码的文件来服从。但是,当我们简单地运行命令而没有任何选项时,它不会在内部生成汇编代码吗? 如果是,那么为什么它需要首先生成一个汇编代码,然后将其翻译成机器语言?
问题内容: 我想知道如何检查JIT编译器是否已关闭。我有以下代码旨在关闭JIT编译器。问题是,我不确定它是否确实在这样做。所以我想知道是否有一种方法可以检查JIT是否关闭。我看了Compiler类,但没有类似的方法。 码: 任何帮助或指导将不胜感激。 问题答案: 我不相信您可以在运行时关闭JIT。 如果要认真地对Java程序进行基准测试,则绝对应该忽略前几次运行。在Java中获得可靠的基准测试是一
似乎默认情况下,Clang采用了GNU汇编程序语法。 如何用Clang编译一个汇编文件使用ARM语法像this(指令)和this(指令)?
对象类是每个类的基类,即每个类都扩展了对象类。Object类中有一个公共String toString()方法,而String类中也存在同样的方法。现在,String类还扩展了Object类,方法toString返回一个String类型。 我的问题是-:在编译Object类时,它将搜索String.class,而String类将搜索Object.class,从而创建一种相互依赖的类型。这种依赖是如