前言
面试过程中,发现自己确实对于c和c++实现的原理了解得不够深入,因此借书以解惑!
本书最大的亮点和可读点可以是对于指针部分和多文件工程时对文件内容的管理原则值得一读。
左值和右值
左值是一个具体的变量,右值一定是一个具体类型的值。所以有些可以既可以作为左值,也可以作为右值,但有些只能作为右值。
如 a[i] = b[i] , b[i] = a[i] 中,a[i]在两个式子中的含义是不一样的,在前者a[i]是一个变量,是数组中第i+1个元素的变量名 ; 后者的话 a[i] 是数组中第i+1个元素的值。
首地址
使用& 获得的是变量的首地址,指针存在的是地址,长度为地址的长度,不随指向变量类型的变化而变化。如虽然void 类型的指针可以指向任何类型的变量,但是不能使用*引用指向的值,要引用这个值,必须强制将void指针赋值给与值相应的指针类型。(因为得到的只是一个首地址,我们需要得到一个变量的值,还需要通过变量类型知道变量所占的内存空间大小)
同时,指针变量的值为一个地址值,但是这个地址不一定是有效地址(CPU中内存的地址)。当赋给一个无效的地址时,就不能使用*操作。
没有初始化指针和空指针
指针在没有初始化之前,指针变量没有存储有效地址,如果对其进行*操作就会产生运行时错误。当用NULL 初始化指针时,指针变量存储的内容是0号地址单元,这虽然是有效的地址,但也不允许使用 *操作,因为这次系统地址,不允许应用程序访问。但这个区域可以为程序提供判别条件。
指针的初始化
保证指针指向一个有效的地址,①保证指向一个地址;②指向的地址有效。
小段存储和大端存储
p1 = p2 ,则不仅使得p1和p2 都指向原本p2指向的地址,而且保证*p1 = *p2
数组
- 在c语言中对数组的下标变量的值是不进行合法性检查的,所以允许数组的下标越界。
- 数组名就是指针常量。
函数
- 编译系统只检查调用函数的类型是否与声明的一致,所以声明时不需要给出参数的变量名称。
- 形参。在函数未被调用时,系统不给形参分配存储单元。在函数被调用时,系统立刻给形参分配内存单元;调用结束后,再释放形参所占用的内存单元。
- 传递地址值得时候,系统不会为形参分配新的地址,而是为指针变量分配地址。也就是变量的值是指向实参的存储地址。所以没有复制值的过程。
-
文件结构
- 单文件: 预处理部分,主函数体,其他函数定义
- 一个源文件 + 一个头文件:头文件是用来编写预处理命令、函数原型声明及全局变量声明或定义; 源文件则是包含头文件、编写相应主程序和函数
- 单文件变量的存储地址分配:①全局区(静态区)是存放全局变量和静态变量的存放区域,分为已初始化和未初始化两个区域;②堆区一般由程序员分配和释放。如果程序员没有释放,则在程序结束后,由操作系统收回;③栈由编译器自动分配和释放,存放函数的参数、局部变量等。
多文件结构
- 一般将所有的函数原型和外部变量的声明,以及常数的定义都放在一个头文件里,需要这些头文件的源文件,就可以将它们包含进去。
-
main 函数的整型返回值的作用是向系统返回一个状态码,这在复杂应用程序的过程间通信时会用到,不过它对单一的程序是没有什么意义的。
c语言函数参数的传递方式只有转值一种。它在传递地址值得时候,传递的是值不是地址,传递变量地址值是使用变量指针作为参数。 而c++是有传递地址方式的,使用变量引用作为参数。
不能使用临时数组名作为函数返回值。虽然使用指针将首地址返给主函数,但当函数调用结束后,数组就不存在了,当然这个地址的内容也就不可预测了,所以对这个地址的一系列操作也就无从谈起了。
词法分析中的贪心思想:每一个符号应该包含尽可能多的字符。也就是说,编译器将程序分解为符号的方法是从左到右一个字符一个字符地读入,如果该字符可能组成一个符号,就再读入下一个字符并判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分;如果可能,继续读入下一个字符,重复上述判断。如 a—b 等价与a-- -b
多文件中的函数设计
- 无参数的宏作为常量,而带参数的宏则可以提供比函数调用更高的效率。但预处理只是进行简单的文本代替而不做语法检查,所以会存在一些问题。因此宏定义有许多不安全因素,所以对需要使用无参数宏的场合,建议尽量使用const代替宏定义。
头文件
以下原则:
- 头文件里只写不实际生成的代码和不导致实际分配存储的描述。例如可写函数原型,不写函数定义;可用extern 声明外部变量,但不定义变量;可用包含标准库头文件和其他头文件的预处理命令;可用包含枚举的声明。
- 可用包含各种公用宏定义,但尽量少用宏定义。
- 只用文件包含命令(#include)包含头文件,不用它包含程序文件。
- 通过头文件能解决在一个程序文件里定义,而在另一个程序文件里使用的信息传递问题。
- 因为一个程序文件可能包含多个头文件,由此可能引起同一个头文件的重复包含问题。对头文件使用预处理命令可以避免这一问题。
#ifndef _H_LENTER
#define _H_LENTER
头文件主体
#endif