Compile

.cpp->(预处理).i->编译.s->汇编.o->链接.exe

c++中文件没有任何意义,仅仅告知编译器对待编译该文件的方式,以.cpp对待?以.s对待?等等

预编译 .i

在编译之前对程序内容进行取舍处理,使得一些语句参加编译,而另一些语句不参加编译

预处理指令

在编译之前对文件的处理

文件包含

include指示预编译将包含的头文件内容附加在程序文件中,以参加编译

#include <标准库文件>
#include “用户自定义文件”

区别:<>包含的文件为标准库文件,编译器在搜索路径时会在默认系统头文件路径中搜索,而””包含的用户自定义文件,编译器会在源文件目录进行搜索,若搜索不到,再到默认头文件库中搜索

条件编译

  • c++编译时不允许出现属性的重定义(不同cpp文件全局变量的重定义,单一cpp文件中变量的重定义,等等重定义均不允许)
  • 头文件卫士
    保护嵌套的include指令中的文件属性的名称不能被重复定义

    #if #elif #else #ifdef #ifndef #endif

防止头文件的重复包含和编译
解决方案

  • #ifndef name
    #define name

  • 优点为可以防止多次包含不同名但相同内容的文件,因为是根据是否有同名变量来判断是否在此包含文件的

  • pragma once

  • 交由编译器处理,可以防止该文件被多次包含,但是同内容不同名的文件仍会被包含进来,但是容易发现

宏定义

#define

无参宏定义

#define 宏名 字符串

1
2
3

#define INTEGER int

使用宏名来表示代码中的字符串,但是在预处理时会使用字符串来代换宏名,称为宏代换宏展开

  • 字符串可以是常数、表达式、格式串等 无需””括起
  • 宏定义方便程序修改

带参宏定义

#define 宏名(形参表) 字符串

1
2
3
4
5

#define Multiply(a,b) a*b

int a = Multiply(3,5)//调用 a=15

  • 对于带参的宏,预编译时不仅要展开,还要将实参代入
  • 使用带参数的宏定义可完成函数调用的功能,又能减少系统开销,提高运行效率

取消宏定义

#undef

宏定义的作用域是宏定义命令其到宏定义源程序结束,可使用#undef来终止其作用域

#undef 宏名 字符串
#undef 宏名(形参表) 字符串

编译 .s

  • 词法分析

  • 语法分析

  • 语义分析

  • 代码优化

编译主要将代码转成汇编代码,即一条一条的指令

汇编 .obj

在汇编阶段主要是将指令代码翻译汇编成二进制文件

链接 .exe

编译器将生成的多个.o文件来链接到一起生成一个可执行的.exe文件

VS2017配置预处理相关属性

在项目简介方案属性中可以设置预编译内容写入到文件,但是选定该选项为true时,不再编译生成obj文件,而是生成.i文件与debug目录下,因此无法生成.exe文件