美文网首页
预处理和内存管理

预处理和内存管理

作者: MinoyJet | 来源:发表于2017-04-28 16:06 被阅读0次

预处理和内存管理

1. 什么是预处理?

预处理是 C 和 C++ 语言独有的特色,它允许开发人员定义宏,编译器在编译文件时会首先进行一次预编译,将宏替换成实际定义的内容。

2. 定义一个宏实现两个数的交换

许多人觉得此题非常容易,马上写出了代码,例如:

#define  swap(x, y)  int z = x; x = y; y = z

这样的代码实现了面试题的功能,但是存在一定缺陷。例如,如果程序中已经定义了变量 z ,那么使用 swap 宏时,就会出现 “ 重复定义 ” 的错误。
所以在定义宏时应尽量避免定义额外的变量,例如:

#define  swap(x, y)  x ^= y; y ^= x; x ^= y

或者如果 x + y 不会溢出时,还可以用:

#define  swap(x, y)  x = x + y; y = x - y; x = x - y

3. 简述含参数的宏与函数的区别

  • 宏是编译期进行的,编译器在编译程序时,首先进行预编译,也就是将代码中的宏替换为宏定义的内容;而函数是运行期进行的。
  • 程序中使用宏不会进行参数类型检查;而函数则会进行参数类型检查。
  • 宏只是编译期进行直接替换,不会定义参数类型,不会计算参数表达式;而函数会在栈中定义局部变量和函数参数。
  • 宏没有生存期、作用域之类的概念;而函数则有。

4. 编写一个宏 MIN ,返回两个数的较小者

刚看到题目的时候,我会毫不犹豫的写出下面的定义:

#define  MIN(x, y)  (x > y ? y : x)

然而这是一种错误写法,引文宏只是编译期进行直接文本替换。如果使用下面的代码调用宏 MIN ,就会出错:

MIN(a&0x10, b);  // a&0x10 > b ? b : a&0x10;

& 运算符的优先级低于 > 运算符,因此结果会出错。正确的形式应该是:

#define  MIN(x, y)  ((x) > (y) ? (y) : (x))

5. #include <math.h> 和 #include "math.h" 有何区别?

  • **#include <math.h> **:表示编译器从标准库路径查找 math.h 文件
  • #include "math.h":表示编译器先查找工程路径,如果没有找到,再查找标准库路径

6. 解释堆和栈的区别

堆和栈实际是一块物理内存,堆主要用来动态分配内存,较大的数据需要在堆中分配。从堆栈内存的低端向上分配;而栈主要存储函数参数、返回值和局部变量,是从堆栈内存的高端向下分配。堆是动态分配,比如用 new 分配,在使用后需要手工释放;栈属于静态分配,在对象使用后无需手动释放内存。

7. 内存的分配方式

内存分配主要有 3 种方式,分别为静态存储区分配、堆分配和栈分配。

  • 静态存储区分配是在编译时就确定的。例如,程序中的全局变量或静态变量就存储在静态存储区中。
  • 堆分配又称为动态分配,例如程序中使用 new、malloc 函数分配的内存。采用堆分配的内存,用户在使用后需要手动释放该内存,否则会出现内存泄露。
  • 栈分配属于静态分配,函数参数、函数返回值等都在栈中进行分配。函数调用后会自动释放栈空间。栈分配的特点是执行效率高,但是空间有限。

相关文章

网友评论

      本文标题:预处理和内存管理

      本文链接:https://www.haomeiwen.com/subject/xozozttx.html