Assembler,assembler

如何混和使用c与c编程?

Assembler,assembler


在用C的项目源码中,经常会不可避免的会看到下面的代码:1#ifdef __cplusplus2extern "C" {3#endif45/*...*/67#ifdef __cplusplus8}9#endif它到底有什么用呢,你知道吗?而且这样的问题经常会出现在面试or笔试中 。下面我就从以下几个方面来介绍它:1、#ifdef _cplusplus/#endif _cplusplus及发散2、extern "C"2.1、extern关键字2.2、"C"2.3、小结extern "C"3、C和C互相调用 4、C和C混合调用特别之处函数指针3.1、C的编译和连接3.2、C的编译和连接3.3、C中调用C的代码3.4、C中调用C的代码1、#ifdef _cplusplus/#endif _cplusplus及发散在介绍extern "C"之前,我们来看下#ifdef_cplusplus/#endif_cplusplus的作用 。
很明显#ifdef/#endif、#ifndef/#endif用于条件编译,#ifdef_cplusplus/#endif_cplusplus——表示如果定义了宏_cplusplus,就执行#ifdef/#endif之间的语句,否则就不执行 。在这里为什么需要#ifdef _cplusplus/#endif_cplusplus呢?因为C语言中不支持extern "C"声明,如果你明白extern"C"的作用就知道在C中也没有必要这样做,这就是条件编译的作用!在.c文件中包含了extern "C"时会出现编译时错误 。
既然说到了条件编译,我就介绍它的一个重要应用——避免重复包含头文件 。还记得腾讯笔试就考过这个题目,给出类似下面的代码(下面是我最近在研究的一个开源web服务器——Mongoose的头文件mongoose.h中的一段代码):01#ifndef MONGOOSE_HEADER_INCLUDED02#define MONGOOSE_HEADER_INCLUDED0304#ifdef __cplusplus05extern "C" {06#endif /* __cplusplus */0708/*.................................09* do something here10*.................................11*/1213#ifdef __cplusplus14}15#endif /* __cplusplus */1617#endif /* MONGOOSE_HEADER_INCLUDED */然后叫你说明上面宏#ifndef/#endif的作用?为了解释一个问题,我们先来看两个事实:这个头文件mongoose.h可能在项目中被多个源文件包含(#include"mongoose.h"),而对于一个大型项目来说,这些冗余可能导致错误,因为一个头文件包含类定义或inline函数,在一个源文件中mongoose.h可能会被#include两次(如,a.h头文件包含了mongoose.h,而在b.c文件中#includea.h和mongoose.h)——这就会出错(在同一个源文件中一个结构体、类等被定义了两次) 。
从逻辑观点和减少编译时间上,都要求去除这些冗余 。然而让程序员去分析和去掉这些冗余,不仅枯燥且不太实际,最重要的是有时候又需要这种冗余来保证各个模块的独立 。为了解决这个问题,上面代码中的#ifndef MONGOOSE_HEADER_INCLUDED#define MONGOOSE_HEADER_INCLUDED/*……………………………*/#endif /* MONGOOSE_HEADER_INCLUDED */就起作用了 。
如果定义了MONGOOSE_HEADER_INCLUDED,#ifndef/#endif之间的内容就被忽略掉 。因此,编译时第一次看到mongoose.h头文件,它的内容会被读取且给定MONGOOSE_HEADER_INCLUDED一个值 。之后再次看到mongoose.h头文件时,MONGOOSE_HEADER_INCLUDED就已经定义了,mongoose.h的内容就不会再次被读取了 。
2、extern "C"首先从字面上分析extern "C",它由两部分组成——extern关键字、"C" 。下面我就从这两个方面来解读extern "C"的含义 。2.1、extern关键字在一个项目中必须保证函数、变量、枚举等在所有的源文件中保持一致,除非你指定定义为局部的 。首先来一个例子:1//file1.c:2int x=1;3int f(){do something here}4//file2.c:5extern int x;6int f();7void g(){x=f();}在file2.c中g()使用的x和f()是定义在file1.c中的 。
extern关键字表明file2.c中x,仅仅是一个变量的声明,其并不是在定义变量x,并未为x分配内存空间 。变量x在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误 。但是可以声明多次,且声明必须保证类型一致,如:1//file1.c:2int x=1;3int b=1;4extern c;5//file2.c:6int x;// x equals to default of int type 07int f();8extern double b;9extern int c;在这段代码中存在着这样的三个错误:x被定义了两次b两次被声明为不同的类型c被声明了两次,但却没有定义回到extern关键字,extern是C/C语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用 。

推荐阅读