符号表

Javac早期(编译期)

耗尽温柔 提交于 2020-02-12 08:45:11
从Sun Javac的代码来看,编译过程大致可以分为3个过程: 解析与填充符号表过程。 插入式注解处理器的注解处理过程。 分析与字节码生成过程。 Javac编译动作的入口是com.sun.tools.javac.main.JavaCompiler类,上述3个过程的代码逻辑集中在这个类的compile()和compile2()方法中,整个编译最关键的处理就由图中标注的8个方法来完成,下面我们具体看一下这8个方法实现了什么功能。 解析与填充符号表 解析步骤由上图中的parseFiles()方法(过程1.1)完成,解析步骤包括了经典程序编译原理中的词法分析和语法分析两个过程。 词法、语法分析 词法分析是 将源代码的字符流转变为标记(Token)集合 ,单个字符是程序编写过程的最小元素,而标记则是编译过程的最小元素,关键字、变量名、字面量、运算符都可以成为标记,如“int a=b+2”这句代码包含了6个标记,分别是int、a、=、b、+、2,虽然关键字int由3个字符构成,但是它只是一个Token,不可再拆分。在Javac的源码中,词法分析过程由com.sun.tools.javac.parser.Scanner类来实现。 语法分析是 根据Token序列构造抽象语法树的过程 ,抽象语法树(Abstract Syntax Tree,AST)是一种用来描述程序代码语法结构的树形表示方式

实训25 共享数据块和系统功能的调用

对着背影说爱祢 提交于 2020-02-06 18:17:03
实训25 共享数据块与系统功能的调用 关键字:共享数据块和符号表中的变量 为全局变量。可供所有逻辑块使用 注意符号表中的变量 描述 。 功能块中的变量 成为变量声明表,与符号表区别开来。 变量声明表里面的额变量是局部变量,符号表里的是全局变量。 关键字: 实际参数 "P#DB1.DBX0.0 INT 4" 表示的是 共享数据表里面 的4个 数组元素的地址 。 在声明视图里查看 共享数据表的声明表 地址 0.0 对应数组的第一个地址。 数据块(DB)用来分类存储设备或者生产线中变量的值。 数据块分为 共享数据块 (DB) 和 背景数据块 (DI) 共享数据块 和符号表中的变量为全局变量,可供所有逻辑块使用。 CPU使用OPN指令分别打开一个共享数据块和一个背景数据块 。 打开新的数据块时,原来被打开的数据块将会自动关闭。 快递定义数据块的大小 然后单击 数据块 DB2 打开 只有一个 临时占位符变量 DB_VAR 将DB_VAR 变量名称改为 press 然后类型 选择 数组 ARRAY 下表中 建立了一个数组 ,array (数据类型是 int ) 一个int 变量 voltage 一个int 变量 current 这个数据块 放在 C语言中 一个类似于结构体 的数据块 +0.0 表示 数组的起始地址为0 , *2 表示数元素的大小是2B +8.0 表示改行上面的四个元素是8B

4. 其他流程控制工具

本小妞迷上赌 提交于 2020-02-05 02:09:48
4. 其他流程控制工具 除了刚刚介绍过的 while 语句,Python 中也会使用其他语言中常见的流程控制语句,只是稍有变化。 4.1. if 语句 可能最为人所熟知的编程语句就是 if 语句了。例如: >>> >>> x = int(input("Please enter an integer: ")) Please enter an integer: 42 >>> if x < 0: ... x = 0 ... print('Negative changed to zero') ... elif x == 0: ... print('Zero') ... elif x == 1: ... print('Single') ... else: ... print('More') ... More 可以有零个或多个 elif 部分,以及一个可选的 else 部分。 关键字 ' elif ' 是 'else if' 的缩写,适合用于避免过多的缩进。 一个 if ... elif ... elif ... 序列可以看作是其他语言中的 switch 或 case 语句的替代。 4.2. for 语句 Python 中的 for 语句与你在 C 或 Pascal 中可能用到的有所不同。 Python 中的 for 语句并不总是对算术递增的数值进行迭代(如同 Pascal)

6. 模块

梦想与她 提交于 2020-02-05 02:02:37
6. 模块 如果你从Python解释器退出并再次进入,之前的定义(函数和变量)都会丢失。因此,如果你想编写一个稍长些的程序,最好使用文本编辑器为解释器准备输入并将该文件作为输入运行。这被称作编写 脚本 。随着程序变得越来越长,你或许会想把它拆分成几个文件,以方便维护。你亦或想在不同的程序中使用一个便捷的函数, 而不必把这个函数复制到每一个程序中去。 为支持这些,Python有一种方法可以把定义放在一个文件里,并在脚本或解释器的交互式实例中使用它们。这样的文件被称作 模块 ;模块中的定义可以 导入 到其它模块或者 主 模块(你在顶级和计算器模式下执行的脚本中可以访问的变量集合)。 模块是一个包含Python定义和语句的文件。文件名就是模块名后跟文件后缀 .py 。在一个模块内部,模块名(作为一个字符串)可以通过全局变量 __name__ 的值获得。例如,使用你最喜爱的文本编辑器在当前目录下创建一个名为 fibo.py 的文件, 文件中含有以下内容: # Fibonacci numbers module def fib(n): # write Fibonacci series up to n a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print() def fib2(n): # return Fibonacci

C++中引用和指针

微笑、不失礼 提交于 2020-02-05 00:51:40
C++中使用指针的优点 1.指针能够有效的表示数据结构; 2.能动态分配内存,实现内存的自由管理; 3.能较方便的使用字符串; 4.便捷高效地使用数组; 5.指针直接与数据的储存地址有关。比如:值传递不如地址传递高效, 因为值传递先从实参的地址中取出值,再赋值给形参代入函数计算;而指 针则把形参的地址直接指向实参地址,使用时直接取出数据,效率提高,特别在频繁赋值等情况下(注意:形参的改变会影响实参的值!) 引用与指针的区别 1.从现象上看,指针在运行时可以改变其所指向的值,而引用一旦和某个对象绑定后就不再改变。这句话可以理解为:指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变。 2.从内存分配上看,程序为指针变量分配内存区域,而不为引用分配内存区域,因为引用声明时必须初始化,从而指向一个已经存在的对象。引用不能指向空 3.从编译上看,程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变指向的对象(指针变量中的值可以改),而引用对象不能改。这是使用指针不安全而使用引用安全的主要原因。从某种意义上来说引用可以被认为是不能改变的指针。 4

C 里面 ---变量名-- 和 --地址-- 的关系探讨 <转>

风格不统一 提交于 2020-02-04 20:02:43
变量名不占空间 变量:用来标识(identify)一块内存区域,这块区域的值一般是可以更改的,这就是它“变”的由来,但是我们可以通过使用如const等一些修饰符号来限定这一内存区域的操作特性(characteristic),即变量的操作特性。用const修饰的使变量不能更改的就和常量一样的变量叫做常变量。 变量名:是一个标识符(identifier),用来指代一块内存区域,即变量,使用变量使我们操作内存以区域(area),以块(block)为单位,提高了方便性。 你的机器代码中,是不会出现变量名的;变量名是给我们程序员操作内存来使用的。 想想在汇编年代,没有变量名,我们操作内存,都是用地址来直接操作的,还要控制区域大小;当然汇编语言已经有了简单的变量。 对于编译器,它会搜集我们的变量名,比如我们定义了一个全局的int a;那么编译器都为我们做了什么呢? 它会为程序预留4个字节的空间(假设在32位平台),并把我们的变量名“a”保存进符号表,并用这个符号表的索引对应实际的空间。 如果下面出现b = a;那么它就会根据符号表找到变量的真正的物理位置,取得它的值,赋给b。 这是写编译器需要做的,我们需要建立符号表。 但是实际在汇编层次上,操作的都是地址而已,不存在任何名称了。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 除了变量名不是内存地址,其他名都是地址。对么

c语言变量名和地址的关系

假如想象 提交于 2020-02-04 20:01:35
在汇编编译器编译时直接将变量名转换成内存地址,变量名并不占内存空间 在编译的时候编译器会把程序中出现的所有变量名都换成相对内存地址,变量名不占内存 变量名不占空间 变量:用来标识(identify)一块内存区域,这块区域的值一般是可以更改的,这就是它“变”的由来,但是我们可以通过使用如const等一些修饰符号来限定这一内存区域的 操作特性 (characteristic),即 变量的操作特性 。用const修饰的使变量不能更改的就和常量一样的变量叫做常变量。 变量名:是一个标识符(identifier),用来指代一块内存区域,即变量,使用变量使我们操作内存以区域(area),以块(block)为单位,提高了方便性。 你的机器代码中,是不会出现变量名的;变量名是给我们程序员操作内存来使用的。 想想在汇编年代,没有变量名,我们操作内存,都是用地址来直接操作的,还要控制区域大小;当然汇编语言已经有了简单的变量。 对于编译器,它会搜集我们的变量名,比如我们定义了一个全局的int a;那么编译器都为我们做了什么呢? 它会为程序预留4个字节的空间(假设在32位平台),并把我们的变量名“a”保存进符号表,并用这个符号表的索引对应实际的空间。 如果下面出现b = a;那么它就会根据符号表找到变量的真正的物理位置,取得它的值,赋给b。 这是写编译器需要做的,我们需要建立符号表。 但是实际在汇编层次上

发一篇关于 数组名称 和 指针区别 的专题探讨

99封情书 提交于 2020-02-04 20:01:11
char p_arr[] = " p_arr : hello world " ; 声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值时一个常量 ,指向这段空间的起始位置。 数组名是符号地址常量 ( 一个常量指针,这个值不能被改变 ) ,在编译时求值并存在编译器的符号表里面,其值就是个内存地址;所以可以认为程序没有给他分配空间,数组名只是代表了那个数组空间; 与指针不一样,指针指向一块空间, 同时指针本身也存储在某个空间 ;可以认为数组名存在在符号表里,符号表是编译器用的,我们管不到;p_arr和&p_arr值是一样的,本来对常量取地址是非法的,但是标准组织没有定对数组名取地址是非法还是合法,所以因编译器而异. 引用chinaunix上一个叫dump_crash会员的发言: C专家编程里解释的很好: 经典的错误:在一个文件定义了数组,却在另外一个文件声明其为指针。代码如下: /*File name: main.c*/ extern int* array; /*声明指针*/ int main(void) { array[0]=1; /*用指针访问数据*/ return 0; } /*File name: def.c*/ int array[5]={0}; /*定义的却是数组*/ 1。编译器对数组名和指针变量的处理方式

使用strip, eu-strip, objcopy等剥离与导回符号表及调试信息

若如初见. 提交于 2020-01-30 01:47:17
1.符号表信息和调试信息 符号表信息(symbols)和调试信息(debug info)是由不同段区分的。 使用 readelf -S binfile 可以查看ELF文件的所有段。 调试信息相关的段: # readelf -S a.out | grep debug [27] .debug_aranges PROGBITS 0000000000000000 000016d0 [28] .debug_info PROGBITS 0000000000000000 00001700 [29] .debug_abbrev PROGBITS 0000000000000000 00001a0f [30] .debug_line PROGBITS 0000000000000000 00001adb [31] .debug_str PROGBITS 0000000000000000 00001bd2 符号表相关的段: # readelf -S a.out | grep tab [32] .symtab SYMTAB 0000000000000000 00001e18 [33] .strtab STRTAB 0000000000000000 00002670 [34] .shstrtab STRTAB 0000000000000000 00002a8f 注: 下文中提及的符号表相关段将不包括

指针和引用的区别

北慕城南 提交于 2020-01-14 06:27:12
引自 http://www.cnblogs.com/jiu0821/p/4127382.html 1.指针与引用的区别: 指针是一块内存的地址值,而引用是一块内存的别名。 从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。 在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的: 指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。 而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。