1.简述Makefile的作用
makefile文件和make工具一起使用,用于控制工程项目的编译和链接,也可以用来编写手册页和程序的安装。make工具用于解释执行makefile文件中的内容。makefile文件中通常包含源文件和目标文件的依赖关系以及从源文件生成目标文件的规则。make工具可以根据makefile判断哪些文件需要被重新编译,目标文件的构建顺序等。
Makefile:
1.需要生成的目标文件
2.生成目标文件所需要的依赖文件
3.生成目标文件的编译规则命令行
2.sizeof与strlen的区别:
strlen 是函数, 测量的是字符的实际长度,以'\0' 结束。sizeof 是运算符,测量的是一个变量或者类型的大小。
3.什么是野指针?如何避免野指针。
定义:野指针是指向未知地址的指针
产生原因:1.定义一个指针变量时没有初始化
2.动态分配内存空间后用free()释放内存空间,但没有将指针置为空指针
3.对指针的操作超出了指针变量的作用域
危害:1.指向不可访问的地——>段错误
2.指向一个可用的,但无明确意义的空间——>程序正常运行,但有隐患
3.指向一个可用的,而且正在被使用的空间——>突然被改变,程序运行会有影响,程序会崩溃,数据被破坏
如何避免:对指针进行初始化
1.将指针置为NULL
2.用malloc分配内存(注意:检查是否分配成功)
3.用已有合法的可访问的内存地址对指针初始化
4.c语言分配内存的方式有哪些?
c语言中常见的内存错误有哪些?
1.从静态存储区域分配:全局变量,用static 定义的变量。(存在于整个程序的运行期间)
2.从栈上创建:函数内的局部变量函数。(随函数结束自动释放)
3.从堆上创建:用malloc或者new申请的内存空间。(用free或者delete释放)
5.Static全局变量与普通变量的区别?
Static局部变量与普通局部变量的区别?
Static函数与普通函数的区别?
1.Static全局变量与普通变量的区别:static全局变量和普通全局变量的存储方式相同但是作用域不同。普通全局变量的作用域是整个源程序,当一个源程序由多个原文件组成时,普通全局变量在各个源文件中都是有效的。而static全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。
2.Static局部变量与普通局部变量的区别:static局部变量和普通局部变量的存储方式与作用域都不同。普通局部变量只在声明它的函数被调用时才会分配栈空间,并且只能在该函数内使用。而static局部变量存储在数据段或bss段中(静态存储区),并且源文件的所有函数都可以使用它。
3.Static函数与普通函数的区别:static函数与普通函数的作用域不同。普通函数的定义和声明默认情况下是extern的,在源程序的所有文件中可见,但static函数只是在声明他的文件中可见,不能被其他文件所用。
6.#include <> 和 #include "" 有什么区别?
1.#include< > 引用的是编译器的类库路径里面的头文件。
2. #include" " 引用的是该程序目录的相对路径中的头文件。
7.char *const p; char const *p; const char *p 三者的区别。
1.char *const p:指针p的指向不可以改变,但是指针指向的值可以改变(只读变量p)
2.char const *p:指针p的指向可以改变,但是指针指向的值不可以改变(只读位置)
3.const char *p:指针p的指向不可以改变,且指针指向的值也不可以改变。
nullptr 和 NULL
nullptr是c++11中的关键字,表示空指针
NULL是一个宏定义,在c中NULL为(void*)0,而在c++中NULL为整数0
在c++中(void *)不能转化为任意类型的指针
即 int *p=(void*)是错误的
int *p=nullptr是正确的
原因:
对于函数重载:若c++中 (void *)支持任意类型转换,函数重载时将出现问题下列代码中fun(NULL)将产生二义性
void fun(int i) {cout<<"1";}; void fun(char *p) {cout<<"2";}; int main() { fun(NULL); //输出1,c++中NULL为整数0 fun(nullptr); //输出2,nullptr 为空指针常量。是指针类型 }
在C++中,有哪4个与类型转换相关的关键字?这些关键字各有什么优点?应该在什么场合下使用?
static_cast、const_cast、reinterpret_cast、dynamic_cast
(1)static_cast
特点:静态转换(编译处理)。
应用场合:主要用于C++中内置的基本数据类型之间的转换,但是没有运行时类型的检测来保证转换的安全性。
- 用于基类和子类之间的指针或引用之间的转换,这种转换把子类的指针或引用转换为基类表示是安全的;进行下行转换,把积累的指针或引用转换为子类表示时,由于没有进行动态类型检测,所以是不安全的。
- 把void类型的指针转换成目标类型的指针(不安全)。
- 不能用于两个不相关的类型转换。
- 不能把const对象转换成非const对象。
(2)const_cast
特点:去常转换(编译时)。
应用场合:const_cast操作不能在不同的种类间转换。相反,它仅仅把它作用的表达式转换成常量。它可以使一个本来不是const类型的数据转换成const类型的,或者把const属性去掉。
(3)reinterpret_cast
特点: 重解释类型转换
应用场合:它有着和c风格强制类型转换同样的功能;它可以转化任何的内置数据类型为其他的类型,同时它也可以把任何类型的指针转化为其他的类型;它的机理是对二进制进行重新的解释,不会改变原来的格式。
(4)dynamic_cast < type-id > ( expression )
该运算符将expression转换成type_id类型的对象。type_id必须是类的指针,类的引用或者空类型的指针。
- 如果type_id是一个指针类型,那么expression也必须是一个指针类型,如果type_id是一个引用类型,那么expression也必须是一个引用类型。
- 如果type_id是一个空类型的指针,在运行的时候,就会检测expression的实际类型,结果是一个由expression决定的指针类型。
- 如果type_id不是空类型的指针,在运行的时候指向expression对象的指针能否可以转换成type_id类型的指针。
- 在运行的时候决定真正的类型,如果向下转换是安全的,就返回一个转换后的指针,若不安全,则返回一个空指针。
- 主要用于上下行之间的转换,也可以用于类之间的交叉转换。上行转换时和static_cast效果一样,下行转换时,具有检测功能,比static_cast更安全。
下列与栈结构有关联的是:
- 数组的定义与使用
- 操作系统的进程调用
- 函数的递归调用
- 选择结构的执行
递归与栈:系统的“递归工作栈”作为递归函数运行期间使用的数据存储区。每一层递归所需信息构成一个“工作记录”,其中包括所有的实际参数,所有的局部变量以及上一层的返回地址。每进入一层递归,就产生一个新的工作记录压入栈顶。