可以在这里下载书籍笔记和答案。
欢迎star/fork参加我的编译器项目
1.1
以C++语言为例:
a.词法错误
int a=$; //$报错
b.语法错误
int c = .+ a; //.号报错
c.静态语义错误
int a=1;
int c=a+b;//b没有定义
d.动态语义错误
访问权限错误,也可能不报错,但是实际上C++:“生成一些代码,在运行时执行适当的检查…有些规则的贯彻可能带来极高的、根本无法接受的代价,语言的实现有可能根本不去检查他们”,也就是说,这个程序"根本就是错误的程序"
编译器只是在尽可能的范围内,检测了一些动态语义错误,而静态语义错误则能全部检测出来。具体能检测多少,由语言的实现决定。
class Object
{
public:
int a;
};
int main() {
Object *b = (Object*)new Object;
delete(b);
cout << (*b).a;
}
e.违反语言定义的错误
这样,不去调用析构而仅仅释放内存,得出来的就会是编译器运行也不会报错的违反语言定义的错误。
class Object
{
public:
int a;
};
int main() {
Object *b = (Object*)new Object;
free(b);
cout << (*b).a;
}
1.2
编译式和解释式的语言各有优点。解释式语言拥有更好的性能,而编译式语言则能够带来更大的灵活性,并且可以对程序做出更好的诊断。
1.3
1.4
Pascal辗转相除
时间复杂度更相减损更高一点。
1.5
make依赖管理会导致一些不必要的编译
比如:
局部变量修改的情况;局部符号表改变但不影响到其它文件;字符的改变但没有单词的改变等等
1.6
lint检查C程序中潜在的错误,包括(但不限于)可疑的类型组合、未使用的变量、不可达的代码以及不可移植的代码。lint会产生一系列程序员有必要从头到尾仔细阅读的诊断信息。使用lint的好处是:1.它可以检查出被编译器漏掉的错误; 2.可以关联很多文件进行错误的检查和代码分析,具有较强大灵活性
1.8
我希望c++的static赋值能更方便一点
但是因为c++的static被所有对象共享,只能在类外赋值
如果在类内赋值了,相当于每一次新建对象都修改了这个值,肯定会增加复杂度
1.9
报错
没有
如果增加了数组越界的语义检查,会增加O(n)的时间复杂度。
1.11
因为要判断语法,语义,是否正确,还要对边界和访问权限等等进行检查。
能够发现的是异常的错误,比如越界,空指针,溢出;而逻辑上的错误是无法发现的。