[c++][工程构建] c 和 c++ 关于编译和链接的一些说明

前言:

从源代码到目标二进制文件,中间经历很多过程,其中之一就是编译,如果我们将  “ 汇编 + 编译 ” 看做一个整体,那么编译可以认为是从 源代码 到 二进制码的一个转变,这个实体的变动有很多附加动作,其中之一就是符号表的生成,这也是非常重要的一环,软件调试正是依赖于符号表来重现函数调用栈的。

 

编译的兼容性:

C++标准允许每个编译器设计人员自定义名称符号表(symbol table)中条目的格式,因此由不同编译器对相同源文件实施编译的最终结果可能是不一样的,因为符号表的格式不通,比如func函数,在通用编译器输出的符号表中是func,而在yk自定义的编译器输出的符号表中是func_yk,这样在链接时就会出现互相找不到的问题,虽然他们代表的代码逻辑都是一样的。
因此,尽量整个工程编译。如果无法整个工程编译,那么就用objdump命令逐条核实二进制文件的符号表;亦或者,确认各个二进制文件的编译器使用的是同一个。

 

C 和 C++混合编程需要注意:

语言的链接性(符号表的翻译和查找规则) ,链接程序要求每个函数的函数名都是独一无二的(这是编译器要求的)。

  • 在C语言中,不存在函数的多态,因此事OK的;
  • 在c++中,存在函数的多态,这就会存在冲突,因此c++编译器会为相同的函数名打上不同的标签。

综上,c编译器和c++编译器在编译时的处理时不一样的,那么既有c又有c++的程序,在定义函数的时候,就需要指明当前函数该如何处理。

默认情况下,编译器会根据文件后缀是.c还是.cpp来自动处理

但是如果想在.cpp文件中引用c函数,那么就需要使用extern "C" void func(void)来申明;

同理在.c文件中,需要用extern "C++" void func(void)来声明c++库/源文件中的函数。

 

写代码时文件拆分思路:

.h文件中包含属性域和方法声明,.c文件中包含方法的实现。这样在使用此文件提供的方法的时候,只要包含.h头文件即可。这也是一种“面向对象”的设计思路。
包含头文件意味着在预编译的时候声明了属性域,并且声明了方法,那么在链接的时候就不存在找不到符号表的问题,但是这里需要避免重复include,方法就是

???.c
#include xxx.h

xxx.h
#ifndef _XXX_H
#define _XXX_H
...
...
...
...
#endif

不要在头文件中声明变量,头文件中仅用来定义变量类型就好,千万不要出现某个实实在在的变量,比如可以定义结构体,定义枚举类型,定义联合体,但是不要在其中声明某个结构体实例。因为会导致变量重复定义的情况出现。

头文件中一般包含如下内容:函数声明,使用#define和const定义的常量,结构体声明,类声明,模板声明,内联函数
总之一句话,不要在头文件中出现任何格式的“实例”,头文件只做声明用。

 

内部链接属性 和 外部链接属性:

什么是链接属性?

以编译单元为单位(h文件如果不适用gcc进行编译则视为非编译单元,因为它是在预编译阶段被#include复制到源代码文件中),内部的变量和函数在编译时对外部是否导出符号表,如果其他编译单元在链接时能够看到,则认为此变量和函数是外部链接属性,否则是内部链接属性。

一个编译单元(.cpp)编译成obj文件后,至少还会有未解决符号表、导出符号表、地址重定向表。而如果这个名称是内部连接的话,那在导出符号表中不存储它的入口。也就是别的obj文件无法链接到这个名称。而外部连接刚好相反,在导出的符号表中有它入口。

 

PS:

1)编译器会提供栈容编译选项,编译时可以指定;

2)volatile关键字:告诉编译器“虽然程序没有修改某个变量,但是这个变量也可能会改变,因此在编译时不要做优化”,比如某个指向硬件缓冲区的指针,缓冲区里的内容由硬件驱动来改变,因此随时都可能改变而且应用软件也不知道,这种情况下,程序就应该按部就班的执行,而不是让编译器自作主张地优化语句。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值