静态库动态库

静态库和动态库是两种共享程序代码的方式,它们的区别是:静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。使用动态库的优点是系统只需载入一次动态库,不同的程序可以得到内存中相同的动态库的副本,因此节省了很多内存。


这种链接方式的好处是:方便程序移植,因为可执行程序与库函数再无关系,放在如何环境当中都可以执行。

是动态链接有一个缺点就是可移植性太差,如果两台电脑运行环境不同,动态库存放的位置不一样,很可能导致程序运行失败。

头文件

编译时,编译器通过头文件.h找到对应的函数库,预编译时将整个.h文件插入目标文件头部,项目中需要有其对应的.c文件进行编译生成中间文件进行连接。
.hpp,本质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该.hpp文件即可,无需再将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中,不再生成单独的obj,采用hpp将大幅度减少调用project中的cpp文件数与编译次数

一个头文件被别的源文件重复包含是经常发生的,如何避免某个头文件被重复包含呢?利用条件编译轻松解决。在头文件的开始加入:

#ifndef HEADER_NAME
#define HEADER_NAME

在头文件的结尾加上:

#endif

C/C++中的预编译指令

程序的编译过程可以分为预处理、编译、汇编三部分,其中预处理是首先执行的过程,预处理过程扫描程序源代码,对其进行初步的转换,产生新的源代码提供给编译器。

  1. #include指令,#include预处理指令的作用是在指令处展开被包含的文件。
    #include \<xxx.h>
    #include “xxx.h”
    第一种方法将待包含的头文件使用尖括号括起来,预处理程序会在系统默认目录或者括号内的路径查找,通常用于包含系统中自带的公共头文件。
    第二种方法将待包含的头文件使用双引号引起来,预处理程序会在程序源文件所在目录查找,如果未找到则去系统默认目录查找,通常用于包含程序作者编写的私有头文件。

2.#define、#undef指令,#define指令定义了一个标识符及一个串,标识符称为宏名,源程序中宏名的每次出现都会用其定义的串进行替换,称为宏替换。
#undef指令取消一个已定义的宏。

3.#if、#elif、#else、#endif指令,这几个指令称为条件编译指令,可对程序源代码的各部分有选择地进行编译。
跟一般的if、else if、else语句类似,如果一个条件上的值为真,则编译它对应的代码,否则提过这些代码,测试下一个条件上的值是否为真。注意,作为条件的表达式是在编译时求值的,它必须仅含常量及已定义过的标识符,不可使用变量,也不可以含有操作符sizeof(sizeof也是编译时求值)。
感觉这主要是用来设置一个宏选择性的编译一部分的代码。

4.#ifdef、#ifndef、#endif指令,这几个也是条件编译指令,其检查后面指定的宏是否已经定义,然后根据检查结果选择是否要编译后面语句。其中#ifdef表示”如果有定义“,#ifndef表示”如果没有定义“。这个通常可以用于防止重复包含头文件的问题

#ifndef MYHEAD_H
#define MYHEAD_H
#include “myHead.h”
#endif

5.#line指令,C语言中可以使用FILE表示本行语句所在源文件的文件名,使用LINE表示本行语句在源文件中的位置信息。#line指令可以重新设定这两个变量的值,其语法格式为
#line number[“filename”]

6.#error指令,#error指令在编译时输出编译错误信息,可以方便程序员检查出现的错误。

7.#pragma指令,该指令用来来设定编译器的状态或者是指示编译器完成一些特定的动作,它有许多不同的参数。
7.1. #pragma once
在头文件的最开始加入这条指令可以保证头文件只被编译一次。它可以实现上述使用#ifndef实现不重复包含头文件同样的功能,但可能会有部分编译系统不支持。

7.2.#pragma message
该指令能够让编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

7.3.#pragma warning
…等等其他参数