设为首页 加入收藏

TOP

C++编译链接的那些小事(一)
2014-02-08 13:37:11 来源: 作者: 【 】 浏览:323
Tags:编译 链接 那些 小事

  最近,有同事向我多次问及C++关于编译链接方面的问题,包括如下:

  1:什么样的函数以及变量可以定义在头文件中

  2:extern "C"的作用

  3:防止重复包含的宏的作用

  4:函数之间是怎么链接起来的

  我认为,这些问题不难,书上基本上都有,但要是没有真正思考过,就凭死记硬背,也就是只能"嘴上说说"而已,遇到问题还真棘手,所以我觉得有必要说一下。

  C/C++的编译链接过程

  其实,"编译"这个词大多数时候,我们指的是由一堆。h,.c,.cpp文件生成链接库或者可执行文件的过程。但是拿C/C++来说,其实这是很模糊的,由一堆C/C++文件生成应用程序包括预处理---编译文件---链接(写的比较粗糙,不影响本文论述)。

  首先,要明白什么是编译单元,一个编译单元可以认为是一个。c或者。cpp文件,每一个编译单元首先会经过预处理得到一个临时的编译单元,这里称为tmp.cpp,预处理会把。c或者。cpp直接或者间接包含的其它文件(不只局限于。h文件,只要是#include即可)的内容替换进来,并展开宏调用等。

  下面首先看一个例子:

  a.h

  #ifndef A_H_

  #define A_H_

  static int a = 1;

  void fun();

  #endif

  a.cpp

  [cpp] view plaincopy

  #include "a.h"

  static void hello_world()

  {

  }

  只有a.h和a.cpp这两个文件,及其简单。首先通过g++的-E参数得到a.cpp预处理之后的内容

  coderchen@coderchen:~/c++$ g++ -E a.cpp > tmp.cpp

  查看tmp.cpp

  # 1 "a.cpp"

  # 1 "<built-in>"

  # 1 "<command-line>"

  # 1 "a.cpp"

  # 1 "a.h" 1

  static int a = 1;

  void fun();

  # 2 "a.cpp" 2

  static void hello_world()

  {

  }

  tmp.cpp就是只经过预处理得到的文件,这个文件才是编译器能够真正看到的文件。这个过程就是预处理。

  其中#define A_H_的作用是防止重复包含a.h这个头文件,很多人都知道这一点,但是再仔细问,我见过大多数人都说不清楚。

  这种宏是为了防止一个编译单元(cpp文件)重复包含同一个头文件。它在预处理阶段起作用,预处理器发现a.cpp内已经定义过A_H_这个宏的话,在a.cpp中再次发现#include "a.h"的时候就不会把a.h的内容替换进a.cpp了。

  编译器看到tmp.cpp的时候,会编译成一个obj文件,最后由链接器对这一个对obj文件进行链接,从而得到可执行程序。

  编译错误和连接错误

  编译错误指的是一个cpp编译单元在编译时发生的错误,这种错误一般都是语法错误,拼写错误,参数不匹配等。

  以main.cpp为例(只有一个main函数)

  int main()

  {

  hello_world();

  }

  编译(加-c参数表示只编译不链接)

  coderchen@coderchen:~/c++$ g++ -c -o main.o main.cpp

  main.cpp: In function 'int main()':

  main.cpp:4: error: 'hello_world' was not declared in this scope

  这种错误就是编译,原因是hello_world函数未声明,把void hello_world();这条语句加到main函数前面,再次编译

  coderchen@coderchen:~/c++$ g++ -c -o main.o main.cpp

  coderchen@coderchen:~/c++$

  编译成功,虽然我们调用了hello_world函数,却没有定义这个函数。好,接下来,我们把这个main.o文件链接下,

  coderchen@coderchen:~/c++$ g++ -o main main.o

  main.o: In function `main':

  main.cpp:(。text+0x7): undefined reference to `hello_world()'

  collect2: ld returned 1 exit status

   

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++中的位运算符 下一篇C++和C#之间互相调用经验详谈

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·PostgreSQL 索引 - (2025-12-25 22:20:43)
·MySQL Node.js 连接 (2025-12-25 22:20:41)
·SQL 撤销索引、表以 (2025-12-25 22:20:38)
·Linux系统简介 (2025-12-25 21:55:25)
·Linux安装MySQL过程 (2025-12-25 21:55:22)