导航:首页 > 源码编译 > 地址由编译器产生吗

地址由编译器产生吗

发布时间:2022-05-31 19:02:36

Ⅰ 为什么C语言变量的地址每一次运行都是一样的,在360隔离沙箱里运行也是一样的

变量地址是由编译器决定的

360隔离沙箱是不让程序写入磁盘,不是不让程序加载内存

Ⅱ 什么是编译器

编译器

编译器是一种特殊的程序,它可以把以特定编程语言写成的程序变为机器可以运行的机器码。我们把一个程序写好,这时我们利用的环境是文本编辑器。这时我程序把程序称为源程序。在此以后程序员可以运行相应的编译器,通过指定需要编译的文件的名称就可以把相应的源文件(通过一个复杂的过程)转化为机器码了。

[编辑]编译器工作方法
首先编译器进行语法分析,也就是要把那些字符串分离出来。然后进行语义分析,就是把各个由语法分析分析出的语法单元的意义搞清楚。最后生成的是目标文件,我们也称为obj文件。再经过链接器的链接就可以生成最后的可执行代码了。有些时候我们需要把多个文件产生的目标文件进行链接,产生最后的代码。我们把一过程称为交叉链接。

一个现代编译器的主要工作流程如下:

* 源程序(source code)→预处理器(preprocessor)→编译器(compiler)→汇编程序(assembler)→目标程序(object code)→连接器(链接器,Linker)→可执行程序(executables)

工作原理

编译是从源代码(通常为高级语言)到能直接被计算机或虚拟机执行的目标代码(通常为低级语言或机器言)。然而,也存在从低级语言到高级语言的编译器,这类编译器中用来从由高级语言生成的低级语言代码重新生成高级语言代码的又被叫做反编译器。也有从一种高级语言生成另一种高级语言的编译器,或者生成一种需要进一步处理的的中间代码的编译器(又叫级联)。

典型的编译器输出是由包含入口点的名字和地址以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的可执行程序。

编译器种类

编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码,这种编译器又叫做“本地”编译器。另外,编译器也可以生成用来在其它平台上运行的目标代码,这种编译器又叫做交叉编译器。交叉编译器在生成新的硬件平台时非常有用。“源码到源码编译器”是指用一种高级语言作为输入,输出也是高级语言的编译器。例如: 自动并行化编译器经常采用一种高级语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语言构造进行注释(如FORTRAN的DOALL指令)。

预处理器(preprocessor)

作用是通过代入预定义等程序段将源程序补充完整。

编译器前端(frontend)

前端主要负责解析(parse)输入的源程序,由词法分析器和语法分析器协同工作。词法分析器负责把源程序中的‘单词’(Token)找出来,语法分析器把这些分散的单词按预先定义好的语法组装成有意义的表达式,语句 ,函数等等。 例如“a = b + c;”前端词法分析器看到的是“a, =, b , +, c;”,语法分析器按定义的语法,先把他们组装成表达式“b + c”,再组装成“a = b + c”的语句。 前端还负责语义(semantic checking)的检查,例如检测参与运算的变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树(abstract syntax tree,或 AST),这样后端可以在此基础上进一步优化,处理。

编译器后端(backend)

编译器后端主要负责分析,优化中间代码(Intermediate representation)以及生成机器代码(Code Generation)。

一般说来所有的编译器分析,优化,变型都可以分成两大类: 函数内(intraproceral)还是函数之间(interproceral)进行。很明显,函数间的分析,优化更准确,但需要更长的时间来完成。

编译器分析(compiler analysis)的对象是前端生成并传递过来的中间代码,现代的优化型编译器(optimizing compiler)常常用好几种层次的中间代码来表示程序,高层的中间代码(high level IR)接近输入的源程序的格式,与输入语言相关(language dependent),包含更多的全局性的信息,和源程序的结构;中层的中间代码(middle level IR)与输入语言无关,低层的中间代码(Low level IR)与机器语言类似。 不同的分析,优化发生在最适合的那一层中间代码上。

常见的编译分析有函数调用树(call tree),控制流程图(Control flow graph),以及在此基础上的变量定义-使用,使用-定义链(define-use/use-define or u-d/d-u chain),变量别名分析(alias analysis),指针分析(pointer analysis),数据依赖分析(data dependence analysis)等等。

上述的程序分析结果是编译器优化(compiler optimization)和程序变形(compiler transformation)的前提条件。常见的优化和变新有:函数内嵌(inlining),无用代码删除(Dead code elimination),标准化循环结构(loop normalization),循环体展开(loop unrolling),循环体合并,分裂(loop fusion,loop fission),数组填充(array padding),等等。优化和变形的目的是减少代码的长度,提高内存(memory),缓存(cache)的使用率,减少读写磁盘,访问网络数据的频率。更高级的优化甚至可以把序列化的代码(serial code)变成并行运算,多线程的代码(parallelized,multi-threaded code)。

机器代码的生成是优化变型后的中间代码转换成机器指令的过程。现代编译器主要采用生成汇编代码(assembly code)的策略,而不直接生成二进制的目标代码(binary object code)。即使在代码生成阶段,高级编译器仍然要做很多分析,优化,变形的工作。例如如何分配寄存器(register allocatioin),如何选择合适的机器指令(instruction selection),如何合并几句代码成一句等等。

Ⅲ 关于C的地址问题

例如
int a[10];
数组的起始地址就是数组名。
这个数组名就是起始地址,是在编译的时候,放在了一个叫“符号表”的地方,
每个符号对应一个地址,这样在使用这个符号访问的时候,它会从符号表中找到这个符号对应的起始地址。从而达到数组的访问。
数组内存空间上是连续分布的。只是对于
不同类型的数组,它的移动长度不一样。
例如
int a[10];
a+1;是地址移动了4个字节,因为int占4个字节。
char a[10];
a+1;是地址移动了1个字节,因为char占1个字节。
严格的说,不存在多维数组,只不过这个数组存储的类型是个数组而已。
可以理解为数组类型的数组。

Ⅳ 编译器是什么

简单讲,编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。一个现代编译器的主要工作流程:源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables)
高级计算机语言便于人编写,阅读交流,维护。机器语言是计算机能直接解读、运行的。编译器将汇编或高级计算机语言源程序(Source program)作为输入,翻译成目标语言(Target language)机器代码的等价程序。源代码一般为高级语言 (High-level language), 如Pascal、C、C++、Java、汉语编程等或汇编语言,而目标则是机器语言的目标代码(Object code),有时也称作机器代码(Machine code)。
对于C#、VB等高级语言而言,此时编译器完成的功能是把源码(SourceCode)编译成通用中间语言(MSIL/CIL)的字节码(ByteCode)。最后运行的时候通过通用语言运行库的转换,编程最终可以被CPU直接计算的机器码(NativeCode)。
编译是从源代码(通常为高级语言)到能直接被计算机或虚拟机执行的目标代码(通常为低级语言或机器语言)的翻译过程。然而,也存在从低级语言到高级语言的编译器,这类编译器中用来从由高级语言生成的低级语言代码重新生成高级语言代码的又被叫做反编译器。也有从一种高级语言生成另一种高级语言的编译器,或者生成一种需要进一步处理的的中间代码的编译器(又叫级联)。
典型的编译器输出是由包含入口点的名字和地址, 以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的EXE,
所以我们电脑上的文件都是经过编译后的文件。

Ⅳ 高级语言源程序编译后产生的地址是逻辑地址还是物理地址

由于操作系统技术的发展,可重用二进制程序技术使用了内存重定位技术,所以从汇编的角度来看即不是逻辑地址也不是物理地址。而且这个概念有些不同,编译后产生的地址是相对地址,是相对于可执行头部位置的地址。而逻辑地址是指在指令系统内部使用的用来访问内存的一个逻辑表示,通常表现为相对于某个段基地址的偏移量。
当可执行程序被载入内存之后,才会有逻辑地址存在,此时可执行程序被如何加载于何处,地址为多少,由操作系统决定,此时cpu访问程序用的是逻辑地址。一个程序一旦被编译确定之后基本上变量初始化的顺序固定,资源分配位置也固定,设置有编译器使用预分配机制,然后采用相对地址引用。
注意:某些工具书也称二进制可执行文件内所有的相对地址范围是逻辑地址空间,相对地址就是逻辑地址。因为两者的访问方式相似,逻辑地址变换依赖cpu或者附加变换机构(硬件),而二进制程序地址空间变换需要操作系统插手管理。
反汇编分析中常常将二进制内部地址称为逻辑地址,因为反汇编器不能还原原来汇编代码的地址跳转空间特性,因此得到一个相对于二进制数据起点位置的相对地址,而和内存和物理存储都没有关系。

Ⅵ c语言问题

呵呵,你们说什么呢?说那么多有什么用!

兄弟,告诉你

一个变量的地址就是这个变量所占几个内存单元中第一个内存单元的地址,即首地址。

例如 int i;
int * p=&i;

很显然 i 在内存中占四个连续的字节

其中这四个连续的字节中首地址即第一个字节的地址就是变量i的地址。
指针的实质就是地址。

Ⅶ 变量是在编译时就指定了内存地址还是在运行时由系统指定内存地址的(关于谭浩强指针章节里的一个疑问)

地址分为线性地址和物理地址,编译后分配的是线性地址,物理地址是实际内存的地址,线性地址和物理地址的转换由操作系统完成,所以同样的程序运行的物理地址不是固定的

Ⅷ C++关于地址的问题

这里关键的一点是因为类是顺序数据结构。

你的程序中类变量a,整型变量c和d都是在栈上分配的。至于把先分配的变量安排在栈的低地址处还是高地址处是由编译器决定的,这和栈的后进先出性质无关。虽然将先分配的变量分配在低地址处符合人们的常规理解,但是相反的策略有更好的性能。所以编译器确实是按先分配的变量先入栈的规则为变量安排空间的。
在本例中(假设Windows),编译器可能会把d安排在(注意,这些地址值不是在编译时决定的硬地址值,而是运行时由运行环境决定的,但它们之间的相对位置是不变的)12ffe0至12ffe3,把c安排在12ffe4至12ffe7,把a安排在12ffe8至12ffef(8字节)。即:
12ffe0 : d 4字节
12ffe4 : c 4字节
12ffe8 : a 8字节
12fff0 : 编译器填充的局部变量

而在类内,编译器是不可以决定把前面的变量安排在低地址还是高地址的,只能是低地址!原因有二:
1)类和结构体、数组等一样,是顺序结构,也就是说要保证按低地址到高地址的顺序分配空间。
例如数组int a[20];
如果按倒序分配空间,那么访问数组时a[0]就成了访问最后一个元素了而a[19]才是第一个元素,注意,在c/c++中,a[b]等价与b[a]等价与*((a) + (b))。
结构体和累也是相同的原因,因为classname.membername和
classpoint->membername中的.和->操作符都是根据membername变量在classname中的偏移来读取数据的,而偏移是正的,是顺序的。

2)类的继承机制要求类变量的成员要按顺序分配空间,因为类变量地址开始处总是类的虚函数表指针(如果有的话),然是是基类的变量,然后是第一层继承类的变量,依此类推。如果按倒序排序,将难以实现多态性。

Ⅸ 编译器的工作原理

编译 是从源代码(通常为高级语言)到能直接被计算机或虚拟机执行的目标代码(通常为低级语言或机器语言)的翻译过程。然而,也存在从低级语言到高级语言的编译器,这类编译器中用来从由高级语言生成的低级语言代码重新生成高级语言代码的又被叫做反编译器。也有从一种高级语言生成另一种高级语言的编译器,或者生成一种需要进一步处理的的中间代码的编译器(又叫级联)。
典型的编译器输出是由包含入口点的名字和地址, 以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的EXE,
所以我们电脑上的文件都是经过编译后的文件。

阅读全文

与地址由编译器产生吗相关的资料

热点内容
程序员16k测试 浏览:541
新人程序员如何定计划 浏览:505
毕业设计单片机仿真 浏览:835
阿里ai云服务器 浏览:435
小程序云服务器可以绑个人账户吗 浏览:727
王者荣耀体验服ios怎么登陆安卓的 浏览:285
客户想要的与程序员理解的 浏览:669
硅谷一普通程序员的一天 浏览:456
算法实现两个集合合并 浏览:75
班长命令什么意思 浏览:139
51单片机c语音 浏览:733
悦翔v3压缩比 浏览:715
oppo怎样修改手机里的文件夹名称 浏览:219
PHP图片上传替换 浏览:140
androidtv桌面 浏览:810
miui10版本怎么隐藏app 浏览:53
阿里云服务器怎么输入命令 浏览:426
如何通过服务器连接网络 浏览:664
一张大事年表pdf 浏览:397
鸡兔同笼java编程 浏览:611