C++面试常见问题--------01预编译和宏的使用

C++预处理器

预处理器是一些指令,它将指示编译器在实际编译之前需要完成的预处理。预处理必须要在对程序进行词法与语义分析、代码生成与优化等通常的编译过程之前进行,经过预处理的程序不再包含之前的预处理命令。

所有的预处理器指令都以#号开始,并且前面不可以出现除了空白字符以外的字符。预处理器指令不是C++指令,所以不需要以 结尾。所有的C++程序实例都有预处理器指令 #include,这个宏用于把头文件包含在源文件中。

预处理器指令是C++统一规定的,但不是C++本身的组成部分,因此编译器无法对其进行识别和编译。

#define预处理

#define预处理器指令用于创建符号常量,这个符号常量被称为宏。在预编译时,所有的宏都会被替换成相应的字符,

#define DEBUG		//DEBUG是宏
#define SQR(x) x*x //求两个数的平方,注意陷阱
int a = 2;
cout<<SQR(a+1)<<endl; //在预编译时会被替换为 2+1*2+1 ,结果是5而不是9
//若真的想求两个数的平方可以做如下改写
#define SQR(x) ((x)*(x))
cout<<SQR(a+1)<<endl; //此时会得到正确答案9

参数宏

C++可以用#define来定义一个带有参数的宏。

#define MIN(a,b)  (a<b?a:b)

内联函数(inline)实现起来比带参数的宏更加方便与安全,因此带参数的宏已经较少使用了。

条件编译

一下指令可以是程序有选择的对部分源码进行编译

#ifdef DEBUG
//代码
#endif
//如果之前已经在上面定义了DEBUG,就会执行上面的代码部分,否则在预处理阶段就会直接跳过该部分,编译器也不会对其进行编译。

#和##运算符

###预处理器运算符在C++和C中都可用:#用于将宏的代替文本转换为用引号引起来的字符串,##用于连接两个参数。

#define STR(X)   #x
cout<<STR(hello world)<<endl; //此时会直接输出hello world
#define PEW(a,b) (int)(a##e##b)
cout<<PEW(2,2)<<endl; //在预编译时被替换为2e2 ,最后结果是200

宏的优点

  • 提高程序的可读性也方便修改
  • 提高程序运行效率:宏在预处理时可以完成与函数调用相同的功能,同时又避免了函数的入栈与出栈操作,减小了系统开销,提高了运行效率。
  • 宏是由预处理器处理的,通过字符串操作能轻松的完成很多编译器无法实现的功能。(宏定义中的#与##
#include<iostream>
using namespace std;
#define FMALLY_CLASS(who) \
class fmally_##who{\
}; #define ADD(arg_a,arg_b) printf(#arg_a"+"#arg_b"=%d\n",arg_a+arg_b)
int main(){
ADD(2,233); FMALLY_CLASS(mengziyue);
fmally_mengziyue ziyue; FMALLY_CLASS(menglihua);
fmally_menglihua lihua;
}

宏的缺点

  • 由于可能是直接嵌入的,代码量可能较多。
  • 嵌套定义肯能引起可读性较差,并且容易出错。
  • 对于带参数的宏来说,仅仅是字符的替换,且缺乏编译器的检测,可能称为错误的隐患。

参考链接:

  1. 菜鸟教程——C++预处理器
  2. 宏定义的优缺点

C++面试常见问题——01预处理与宏定义的更多相关文章

  1. c c++面试c工程开发之宏定义和条件编译

    多数c语言的初学者对c工程开发过程各个阶段的作用理解不到位,而这方面的的知识又是实际开发过程中经常用到的技能点,所以就成为面试考察中一个重要的考察方面.例如:头文件的作用.头文件的内容:链接的作用和意 ...

  2. define预处理以及宏定义

    define的定义方式 无参一般形式:#define 标认符 字符串                     比如:#define COUTD "%d\n" 带参一般形式:#def ...

  3. c 预处理的宏定义

    概念 以“#”号开头的都是预处理命令 例如 #include <stdio.h>宏定义 宏定义无参数的宏名后不带参数# 表示这是一条预处理命令, define 为宏定义命令.“标识符”为所 ...

  4. 标C编程笔记day04 预处理、宏定义、条件编译、makefile、结构体使用

    预处理:也就是包括须要的头文件,用#include<标准头文件>或#include "自己定义的头文件" 宏定义,如:#define PI 3.1415926 查看用宏 ...

  5. C预处理之宏定义

    #include <stdio.h> //定义不带参数的宏 #define PI 3.14 /*********************************************** ...

  6. C语言预处理理论-宏定义2

    宏定义21.带参宏和带参函数的区别(1)宏定义是在预处理期间处理的,而函数是在编译期间处理的.这个区别带来的实质差异是:宏定义最终是在调用宏的地方把宏体原地展开,而函数是在调用函数处跳转到函数中去执行 ...

  7. C语言预处理理论-宏定义1

    宏定义1宏定义的规则和使用解析(1)宏定义的解析规则就是:在预处理阶段由预处理器进行替换,这个替换是原封不动的替换.(2)宏定义替换会递归进行,直到替换出来的值本身不再是一个宏为止.#define M ...

  8. 【C语言】预处理、宏定义、内联函数 _

    一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件   1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的 ...

  9. 【C语言】预处理、宏定义、内联函数

    一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件 1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的汇编 ...

随机推荐

  1. Linux centosVMware 配置Tomcat监听80端口、配置Tomcat虚拟主机、Tomcat日志

    一.配置Tomcat监听80端口 关闭tomcat报错 [root@davery src]# /usr/local/tomcat/bin/shutdown.sh 重装tomcat即可 vim /usr ...

  2. webpack配置文件里loader的执行顺序:从下到上,从右到左; css-loader开启css模块化modules: true,

    注释: options:{ importLoaders: 2 } 解决样式文件里使用@import 'xxx.xxx' 的问题 module: { rules: [{ test: /\.scss$/, ...

  3. 七 异常处理的两种方式(创建全局异常处理器&自定义异常)

    1 创建全局异常处理器 实现HandlerExceptionResolve接口 package com.springmvc01; import javax.servlet.http.HttpServl ...

  4. nrm 源管理器

    什么是nrm nrm 是一个 npm 源管理器,允许你快速地在 npm 源间切换. 安装nrm 在命令行执行命令,npm install -g nrm,全局安装nrm. 使用 执行命令nrm ls查看 ...

  5. 【转载】XShell 连接 VirtualBox CentOS7

    1.安装 XShell 网址:http://sw.bos.baidu.com/sw-search-sp/software/07a1d9cec0638/Xshell-5.0.1339.exe 尽量不要安 ...

  6. PHP 三元运算符

    $a = $a ? $a : 1;//第一种 $a = $a ? : 1;//第二种 第二种写法从 PHP 5.3 引入,表示若 $a 返回值为真时,取 $a 的返回值. 此外,在 PHP7 中引入了 ...

  7. 新闻网大数据实时分析可视化系统项目——12、Hive与HBase集成进行数据分析

    (一)Hive 概述 (二)Hive在Hadoop生态圈中的位置 (三)Hive 架构设计 (四)Hive 的优点及应用场景 (五)Hive 的下载和安装部署 1.Hive 下载 Apache版本的H ...

  8. CH8 IO库

    8.1 #include <iostream> #include <string> #include <sstream> #include <fstream& ...

  9. 前端学习笔记系列一:1.export default / export const

    export default 是默认导出 export const 是命名导出 参考:Javascript (ES6), export const vs export default(基本上就是翻译这 ...

  10. C++面试常见问题——11重载、覆盖、隐藏

    重载.覆盖.隐藏 重载 在同一类定义的成员函数中,参数不同的同名函数为重载关系.重载与虚函数无关. class A{ private: int x; public: void fun(int); // ...