您的位置 首页 > 数码极客

c和c如何互相调用

C语言是面向过程的,而C++是面向对象的

C和C++的区别:

C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。

C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。 所以C与C++的最大区别在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”。

C与C++的最大区别:在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”,而就语言本身而言,在C中更多的是算法的概念。那么是不是C就不重要了,错!算法是程序设计的基础,好的设计如果没有好的算法,一样不行。而且,“C加上好的设计”也能写出非常好的东西。

1.弁言  C++说话的建树初志是“a better C”,可是这并不料味着C++中近似C说话的全局变量和函数所接纳的编译和毗连编制与C说话完全不异。作为一种欲与C兼容的说话,C++保留了一局部过程 式说话的特点(被世人称为“不彻底地面向工具”),因而它可以界说不属于任何类的全局变量和函数。可是,C++现实了局是一种面向工具的轨范设计说话,为了支 持函数的重载,C++对全局函数的措置编制与C有较着的不合。

2.从标准头文件说起

某企业已经给出如下的一道面试题:为什么标准头文件都有近似以下的构造?

#ifndef __INCvxWorksh

#define __INCvxWorksh

#ifdef __cplusplus

extern "C" {

#endif

/*...*/

#ifdef __cplusplus

}

#endif

#endif /* __INCvxWorksh */

显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的浸染是防止该头文件被频频引用。那么

#ifdef __cplusplus

extern "C" {

#endif

#ifdef __cplusplus

}

#endif

的浸染又是什么呢?我们将不才文逐一道来。

3.深层揭密extern "C"  extern "C" 包含双重寄义,从字面上即可获得:首先,被它润饰的方针是“extern”的;其次,被它润饰的方针是“C”的。让我们来详细解读这两重寄义。

被extern "C"限定的函数或变量是extern类型的;

extern是C/C++说话中剖明函数和全局变量浸染规模(可见性)的关头字,该关头字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:

extern int a;

仅仅是一个变量的声明,其并不是在界说变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被界说一次,不然会出现毗连错误。

通常,在模块的头文件中对本模块供给给其它模块引用的函数和全局变量以关头字extern声明。例如,若是模块B欲引用该模块A中界说的全局变量和函数 时只需包含模块A的头文件即可。如许,模块B中挪用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,可是并不会报错;它会在毗连阶段中从模块A编 译生成的方针代码中找到此函数。

与extern对应的关头字是static,被它润饰的全局变量和函数只能在本模块中使用。是以,一个函数或变量只可能被本模块使用时,其不成能被extern “C”润饰。

被extern "C"润饰的变量和函数是按照C说话编制编译和毗连的;

未加extern “C”声明时的编译编制

首先看看C++中对近似C的函数是若何编译的。

作为一种面向工具的说话,C++支撑函数重载,而过程式说话C则不支撑。函数被C++编译后在符号库中的名字与C说话的不合。例如,假设某个函数的原型为:

void foo( int x, int y );

该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不合的编译器可能生成的名字不合,可是都接纳了不异的机制,生成的新名字称为“mangled name”)。

_foo_int_int如许的名字包含了函数名、函数参数数目及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不不异的,后者为_foo_int_float。

同样地,C++中的变量 除支撑局部变量外,还支撑类成员变量和全局变量。用户所编写轨范的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在停止编译时,与 函数的措置类似,也为类中的变量取了一个并世无双的名字,这个名字与用户轨范中同名的全局变量名字不合。

未加extern "C"声明时的毗连编制

假设在C++中,模块A的头文件如下:

// 模块A头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

int foo( int x, int y );

#endif

在模块B中引用该函数:

// 模块B实现文件 moduleB.cpp

#include "moduleA.h"

foo(2,3);

实际上,在毗连阶段,毗连器会从模块A生成的方针文件moduleA.obj中探求_foo_int_int如许的符号!

加extern "C"声明后的编译和毗连编制

加extern "C"声明后,模块A的头文件变为:

// 模块A头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

extern "C" int foo( int x, int y );

#endif

在模块B的实现文件中仍然挪用foo( 2,3 ),其成效是:

(1)模块A编译生成foo的方针代码时,没有对其名字停止不凡措置,接纳了C说话的编制;

(2)毗连器在为模块B的方针代码探求foo(2,3)挪用时,探求的是未经改削的符号名_foo。

若是在模块A中函数声了然foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。

所以,可以用一句话归纳综合extern “C”这个声明的真实目的(任何说话中的任何语法特征的降生都不是随意而为的,来历于真实世界的需求驱动。我们在思虑问题时,不能只勾留在这个说话是怎样 做的,还要问一问它为什么要这么做,念头是什么,如许我们可以更深切地舆解良多问题):

实现C++与C及其它说话的同化编程。

明白了C++中extern "C"的设立念头,我们下面来详细分析extern "C"通常的使用技巧。

4.extern "C"的惯用法  (1)在C++中引用C说话中的函数和变量,在包含C说话头文件(假设为cExam)时,需停止下列措置:

extern "C"

{

#include "cExam"

}

而在C说话的头文件中,对其外部函数只能指定为extern类型,C说话中不支撑extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下:

/* c说话头文件:cExam */

#ifndef C_EXAMPLE_H

#define C_EXAMPLE_H

extern int add(int x,int y);

#endif

/* c说话实现文件:cExam */

#include "cExam"

int add( int x, int y )

{

return x + y;

}

// c++实现文件,挪用add:c

extern "C"

{

#include "cExam"

}

int main(int argc, char* argv[])

{

add(2,3);

return 0;

}

若是C++挪用一个C说话编写的.DLL时,当网罗.DLL的头文件或声明接口函数时,应加extern "C" { }。

(2)在C中引用C++说话中的函数和变量时,C++的头文件需添加extern "C",可是在C说话中不能直接引用声了然extern "C"的该头文件,应该仅将C文件中将C++中界说的extern "C"函数声明为extern类型。

笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下:

//C++头文件 cppExam

#ifndef CPP_EXAMPLE_H

#define CPP_EXAMPLE_H

extern "C" int add( int x, int y );

#endif

//C++实现文件 cppExampp

#include "cppExam"

int add( int x, int y )

{

return x + y;

}

/* C实现文件 cFile.c

/* 如许会编译出错:#include "cExam" */

extern int add( int x, int y );

int main( int argc, char* argv[] )

{

add( 2, 3 );

return 0;

}

若是深切理解了第3节中所阐述的extern "C"在编译和毗连阶段阐扬的浸染,就能真正理解本节所阐述的从C++引用C函数和C引用C++函数的惯用法。对第4节给出的示例代码,必要特别寄望各个细节。

这些是C/C++能做的

服务器开发工程师、人工智能、云计算工程师、信息安全(黑客反黑客)、大数据 、数据平台、嵌入式工程师、流媒体服务器、数据控解、图像处理、音频视频开发工程师、游戏服务器、分布式系统、游戏辅助等

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“c和c如何互相调用,微服务之间如何互相调用,两个类之间如何互相调用方法”边界阅读