1.内存分配方式有哪几种?
(1)从静态存储区域分配。内存在程序编译时就已经分配好了,这块内存在程序的整个运行期间都存在,如全局变量、static变量等。
(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数之行结束时这些存储单元自动被释放。栈内存分配运算使用内置于处理器的指令集,效率很高,但分配的内存容量有限。
(3)从堆上分配,亦称动态内存分配。程序在运行时用malloc或new申请所需要的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。
2.什么是野指针?
野指针不是NULL指针,是指向“垃圾”内存的指针。一般不会错用NULL指针,因为用if语句很容易判断。但是野指针是很危险的,if语句对它不起作用。
3.野指针成因
(1)指针变量没有被初始化
(2)指针p被free或者delete之后,没有被置为NULL,让人误以为p是个合法的指针。
4.常见的内存错误和对策
(1)内存分配未成功,却使用了它。解决办法是,在使用内存之前检查指针是否为NULL。
(2)内存分配虽然成功,但是尚未初始化就引用它。
(3)内存分配成功并且已经初始化,但是操作越过了内存的边界。
(4)忘记了释放内存,造成内存泄漏。动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。
(5)释放了内存却继续使用它。
5.段错误的调试方法
(1)利用gdb逐步查找段错误
(2)分析core文件
(3)段错误时启动调试
(4)利用backtrace和objdump进行分析
6.带参宏定义与自定义函数区别
#define S(a,b) a*b
area=S(3,2)
int S(int a,int b)
{ int s;
s=a*b;
return(s);
}
这两个有什么区别
#define S(a,b) a*b
area=S(3,2)
尽量少使用宏定义。宏定义是把S(a,b)简单地替换成a*b
这样会产生问题,最典型的两种:
(1).缺括号,比如aera=S(x+y,x-y),会被替换成x+y*x-y
(2).自增运算符
定义宏
#define S(a) (a)*(a)
结果S(a++),变成(a++)*(a++)这个大家都知道,在不同编译环境下会有不同结果。
也就是说,宏只是编译前简单替换代码内容,而函数真正产生代码。
宏是编译期的,函数是运行期的;
宏不是实体,而函数是一个可寻址的实体;
宏只是编译期替换,在程序里每遇到S(a,b),就用a*b代替,a和b两个实体并没有由宏实际产生,而函数S会在栈中定义两个对象a和b。
宏没有生存期、作用域之类的概念,而函数就有。
函数在运行过程中会在栈中产生函数调用过程活动记录,而宏则没有。
7.头文件尖括号<>和双引号""有什么区别
使用尖括号表示在包含文件目录中去查找,而不在源文件目录下去查找;使用双引号则表示首先在当前的原文件目录中查找,再去包含目录中去查找。
8.文件包含命令还要说明
(1)包含命令中的文件名可以用双引号也可以用尖括号括起来。
(2)一个include命令只能指定一个被包含文件,若有多个文件要包含,则需要用多个include命令。
(3)文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
9.常用宏定义
#define 定义一个预处理宏
#undef 取消宏的定义
#include 包含文件命令
#include_next 与#include相似, 但它有着特殊的用途
#if 编译预处理中的条件命令, 相当于C语法中的if语句
#ifdef 判断某个宏是否被定义, 若已定义, 执行随后的语句
#ifndef 与#ifdef相反, 判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined 与#if, #elif配合使用, 判断某个宏是否被定义
#line 标志该语句所在的行号
# 将宏参数替代为以参数值为内容的字符窜常量
## 将两个相邻的标记(token)连接为一个单独的标记
#pragma 说明编译器信息
#warning 显示编译警告信息
#error 显示编译错误信息
10.结构体和联合体区别
(1)struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻, union中只存放了一个被选中的成员, 而struct的所有成员都存在。在struct中,各成员都占有自己的内存空间,它们是同时存在的。一个struct变量的总长度等于所有成员长度之和。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度。
(2)对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的。