编译器的强弱符号
1. 编译器的组成及各部分的功能及作用
1. 词法分析 词法分析器根据词法规则识别出源程序中的各个记号(token),每个记号代表一类单词(lexeme)。源程序中常见的记号可以归为几大类:关键字、标识符、字面量和特殊符号。词法分析器的输入是源程序,输出是识别的记号流。词法分析器的任务是把源文件的字符流转换成记号流。本质上它查看连续的字符然后把它们识别为“单词”。 2. 语法分析 语法分析器根据语法规则识别出记号流中的结构(短语、句子),并构造一棵能够正确反映该结构的语法树。 3. 语义分析 语义分析器根据语义规则对语法树中的语法单元进行静态语义检查,如果类型检查和转换等,其目的在于保证语法正确的结构在语义上也是合法的。 4. 中间代码生成 中间代码生成器根据语义分析器的输出生成中间代码。中间代码可以有若干种形式,它们的共同特征是与具体机器无关。最常用的一种中间代码是三地址码,它的一种实现方式是四元式。三地址码的优点是便于阅读、便于优化。 5. 中间代码优化 优化是编译器的一个重要组成部分,由于编译器将源程序翻译成中间代码的工作是机械的、按固定模式进行的,因此,生成的中间代码往往在时间和空间上有很大浪费。当需要生成高效目标代码时,就必须进行优化。 6. 目标代码生成 目标代码生成是编译器的最后一个阶段。在生成目标代码时要考虑以下几个问题:计算机的系统结构、指令系统、寄存器的分配以及内存的组织等。编译器生成的目标程序代码可以有多种形式:汇编语言、可重定位二进制代码、内存形式。 7 符号表管理 符号表的作用是记录源程序中符号的必要信息,并加以合理组织,从而在编译器的各个阶段能对它们进行快速、准确的查找和操作。符号表中的某些内容甚至要保留到程序的运行阶段。 8 出错处理用户编写的源程序中往往会有一些错误,可分为静态错误和动态错误两类。所谓动态错误,是指源程序中的逻辑错误,它们发生在程序运行的时候,也被称作动态语义错误,如变量取值为零时作为除数,数组元素引用时下标出界等。静态错误又可分为语法错误和静态语义错误。语法错误是指有关语言结构上的错误,如单词拼写错、表达式中缺少操作数、begin和end不匹配等。静态语义错误是指分析源程序时可以发现的语言意义上的错误,如加法的两个操作数中一个是整型变量名,而另一个是数组名等。
2. 编译器怎么区分标识符和字符
首先要清楚标识符和字符的定义
标识符是程序员自己规定的具有特定含义的单词,比如类名称,属性名称,变量名等。
举例子就是 class string
字符是指计算机中使用的字母、数字、字和符号
举例子就是 1,2,3,abc
然后要强调,编译器是无法区分标识符和字符的,只有人事先为其规定好规则的情况下,编译器才会按照标识符的方式去读取。打个比方,我规定了class为类标识符,那当我程序里 出现了class test时,编译器就会认为test是类而不是字符。不知道能不能理解,不过是个好问题
3. 请问编译器的符号表是什么呢 能否举个例子呢谢谢
用到的函数都在里面
调用时查那表
4. 编译器有哪几部分构成.编译原理
1. 词法分析
词法分析器根据词法规则识别出源程序
中的各个记号(token),每个记号代表一类单词(lexeme)。源程序中常见的记号可以归为几大类:关键字、标识符、字面量和特殊符号。词法分析器
的输入是源程序,输出是识别的记号流。词法分析器的任务是把源文件的字符流转换成记号流。本质上它查看连续的字符然后把它们识别为“单词”。
2. 语法分析
语法分析器根据语法规则识别出记号流中的结构(短语、句子),并构造一棵能够正确反映该结构的语法树。
3. 语义分析
语义分析器根据语义规则对语法树中的语法单元进行静态语义检查,如果类型检查和转换等,其目的在于保证语法正确的结构在语义上也是合法的。
4. 中间代码生成
中间代码生成器根据语义分析器的输出生成中间代码。中间代码可以有若干种形式,它们的共同特征是与具体机器无关。最常用的一种中间代码是三地址码,它的一种实现方式是四元式。三地址码的优点是便于阅读、便于优化。
5. C 编译器符号表有哪些内容
符号表内部不记变量的值 每个变量都有自己对应的内空间。变量的值就存放在内存空间中! 如int a = 1; //假设a 的地址为0x 00121001 则这个地址的内存中就放有1这个数据
6. CF编译器常用的符号怎么打、斜杠0 等、
得把打字法退到中文(中国)最初的打字法,就是一个小键盘,就能打出来了\\\\\\\\\/////////看
7. 如何让编译器将特殊符号(比如)视为字符常量输出
通常情况下,再特殊符号前边加字符'\',如果要输出的是“%d”则要在前面加上字符'%'
8. C++中 \ 符号是什么意思,对编译器有影响吗
续行符 , 一行太长 要拆成两行写 ,但要让编译器知道这两行 其实是 “一行”
9. 哪位大牛能告诉我,c语言中的'&'这个符号,到底编译器是怎么识别并运用它的
'&'是多功能运算符,至于如何解释该符号,编译器是根据“上下文”来判断的。
由于在C中每个变量必须先声明后使用,比如有声明 :
int x = 3,y = 5,z;
int *p,fun(int &, int &); // 这里显然是引用操作符啦!
对于
z = x & y; // 很明显的,这是逻辑与(and)运算
x &= y; // 这里也是
p = &x; // 这是取址运算,注意,新版的C中没有 =& 双目运算符
-----------------------------------------------------------------------------------------------------------------------
在C++中,有运算符重载函数,比如
aClass operator&(const aClass &x,const aClass &y);,功能是实施类x和y的逻辑与,并返回aClass的实例,这里operator&中的“&”是被重载的运算符,&x,&y中的“&”是引用操作符。
----------------------------------------------------------------------------------------------------------------------
如果你希望了解编译程序的细节,请参考相关书籍。
10. 全局变量的定义,以及如何处理头文件包含关系
首先测试#ifndef #define #endif 在头文件编译中到底能够起到什么作用能?1.能够控制整个工程对于该头文件的包含,也就是说对于添加了#ifndef #define #endif
的头文件一个工程只会包含一次该头文件。2.只能控制一个.c文件只包含这个头文件一次。下面我们定义一个testGlobal.h文件和两个包含该.h文件的.cpp文件,testGlobal.cpp和
testGlobal2.cpp内容如下:
testGlobal.h
#ifndef TESTGLOBAL_H#define TESTGLOBAL_Hint GlobalCount;#endif
testGlobal.cpp
#include "testGlobal.h"
testGlobal2.cpp
#include "testGlobal.h"
#include <iostream>
void main()
{
std::cout<<GlobalCount<<std::endl;
}
此时编译器会提示,redefined这说明两个C文件中都直接包含了头文件的内容。
接下来我们分析#ifndef #define #endif在防止一个C文件将同一个头文件包含两次的作用。这里重新定义一个文件testGlobal2.h
#ifndef TESTGLOBAL2_H
#define TESTGLOBAL2_H
#include "testGlobal.h"
int GlobalCount2 = 5;
#endif
将testGlobal.h和testGlobal2.h都包含到testGlobal.cpp中,并清除testGlobal2.cpp,此时可以顺利编译。可见#ifndef的声明只对一个.cpp文件而言。
基于上述问题,一般在使用全局变量时,都将全局变量定义到某一个.cpp文件中,在.h文件使用extern从而避免出现重定义的问题。
对于.h文件中的宏定义是有编译器直接替换为常值的,不会编译到.obj文件中,所以不会出现重复定义。同时也可以在.h文件中定义结构体,枚举因为这些都是由
有编译器处理,直接在编译时候替换的,所以也不会报错。
实际上有关全局变量重定义的问题在《深入理解计算机系统》一书中有叙述:链接器在解析全局符号时,会遵循以下原则:
1.不允许有多个强符号
2.强弱符号都有选强
3.多个弱符号,任选其中一个
强符号是指:函数和已初始化的全局变量;成员函数如果定义在类外面,那么是强符号;模板函数的特化版本是强的;
弱符号是指:未初始化的全局变量;成员函数如果定义在类里面,那么是弱符号;模板类中的成员函数无论定义在类内还是类外,都是弱类型;模板函数是弱类型;
实际上强弱符号判断是可能出现问题的。因为编译器实际操作的全局变量可能并不是你希望的,可能造成错误。
如果想在全局变量重复定义就发出警告的话,对于GCC可以添加GCC-warn-common选项。通过我的测试在CCS的c编译器上面,在同一个.c文件中重复定义变量
不会报错编译器是按照强弱符号进行判断的,但是要是在不同文件中定义了相同的变量就会报错。而使用g++编译的C++程序,后缀.cpp上述两种情况都会报错,通不
过编译。
通过以上分析,在定义全局变量不应该定义在.h文件中。