C++和C的混合编译

本文介绍了C++和C混合编译时遇到的函数名修饰问题,以及如何通过extern "C"关键字来解决。详细探讨了extern "C"的含义,以及在创建和使用C静态库和C++静态库时的注意事项,包括在C++程序中调用C库和C程序调用C++库的示例。通过extern "C",可以实现C和C++代码的兼容,但要注意C++库失去函数重载特性的潜在问题。
摘要由CSDN通过智能技术生成

简介

C++ 语言的创建初衷是 “a better C”,但是这并不意味着 C++ 中类似 C 语言的全局变量和函数所采用的编译和连接方式与 C 语言完全相同。作为一种欲与 C 兼容的语言, C++ 保留了一部分过程式语言的特点(被世人称为"不彻底地面向对象"),因而它可以定义不属于任何类的全局变量和函数。但是, C++ 毕竟是一种面向对象的程序设计语言,为了支持函数的重载, C++ 对全局函数的处理方式与 C 有明显的不同。

本文将介绍如何通过 extern “C” 关键字在 C++ 中支持 C 语言 和 在C语言中如何支持 C++

某企业曾经给出如下的一道面试题

为什么标准头文件都有类似以下的结构?

//head.h
#ifndef HEAD_H
#define HEAD_H

#ifdef __cplusplus
extern "C" {
   
#endif

    /*...*/

#ifdef __cplusplus
}
#endif

#endif /* HEAd_H */

问题分析

  • 这个头文件head.h可能在项目中被多个源文件包含(#include “head.h”),而对于一个大型项目来说,这些冗余可能导致错误,因为一个头文件包含类定义或inline函数,在一个源文件中head.h可能会被#include两次(如,a.h头文件包含了head.h,而在b.c文件中#include a.h和head.h)——这就会出错(在同一个源文件中一个结构体、类等被定义了两次)。
  • 从逻辑观点和减少编译时间上,都要求去除这些冗余。然而让程序员去分析和去掉这些冗余,不仅枯燥且不太实际,最重要的是有时候又需要这种冗余来保证各个模块的独立

为了解决这个问题,上面代码中的

#ifndef HEAD_H
#define  HEAD_H
/*……………………………*/
#endif /* HEAD_H */

就起作用了。如果定义了HEAD_H,#ifndef/#endif之间的内容就被忽略掉。因此,编译时第一次看到head.h头文件,它的内容会被读取且给定HEAD_H一个值。之后再次看到head.h头文件时,HEAD_H就已经定义了,head.h的内容就不会再次被读取了。

那么下面这段代码的作用又是什么呢?

#ifdef __cplusplus
extern "C" {
   
#endif
/*.......*/
#ifdef __cplusplus
}
#endif

我们将在后面对此进行详细说明。

关于 extern “C”

前面的题目中的 __cplusplus 宏,这是C++中已经定义的宏,是用来识别编译器的,也就是说,将当前代码编译的时候,是否将代码作为 C++ 进行编译。

首先从字面上分析extern “C”,它由两部分组成:extern关键字、“C”。下面我就从这两个方面来解读extern "C"的含义。

首先,被它修饰的目标是 extern 的;其次,被它修饰的目标是 C 的。

extern关键字

被 extern “C” 限定的函数或变量是 extern 类型的。

extern是C/C++语言中表明函数全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。

被extern修饰的函数,需要在编译阶段去链接该目标文件,并且与extern对应的关键字是 static,被static修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其一般是不可能被extern “C”修饰的。

**注意:**例如语句 extern int a; 仅仅是对变量的声明,其并不是在定义变量 a ,声明变量并未为 a 分配内存空间。定义语句形式为 int a; 变量 a 在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

被 extern “C” 修饰的变量和函数是按照 C 语言方式编译和连接的。</

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值