#ifndef和#ifdef __cplusplus

前言:
1,extern可以置于变量声明前; 2,extern也可以置于函数声明前; 通过这种行为它告诉编译器:该变量/函数的定义已经存在在某个地方了,让编译器到其他的模块去寻找它的定义。 3, extern “C” 使用extern“C”主要是因为C++语言在编译的时候为了实现多态,会将函数名和函数结合起来形成另外一种函数名(总之就是说编译后的函数名与你之前自己声明时的函数名会不一样),而C语言中无多态的概念当然也就不会有这种奇异的名字变化问题。这是问题就出现了,当你要在C++中调用C函数时,由于名字的不同,所以它会找不到所调用的这个函数的定义,因而会出错。 为了解决这一C与C++的矛盾冲突,就有了extern “C”。

1、#ifndef 在头文件中的作用

在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量“重定义”的错误。在头文件中实用#ifndef #define #endif能避免头文件的重定义。

例如要编写头文件test.h

#ifndef _TEST_H

#define _TEST_H//一般是文件名的大写

头文件结尾写上一行:

#endif

这样一个工程文件里同时包含两个test.h时,就不会出现重定义的错误了。

把头文件的内容都放在#ifndef和#endif中。不管你的头文件会不会被多个文件引用,你都要加上这个。一般为:

#ifndef<标识>
#define <标识>
......
#endif
<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头

文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,

如:stdio.h
#ifndef _STDIO_H_
#define _STDIO_H_
......
#endif

2、#ifdef __cplusplus

时常在cpp 的代码之中看到这样的代码:

#ifdef __cplusplus

extern "C" {

#endif

//一段代码

#ifdef __cplusplus

}

#endif

C++支持函数重载,而C不支持,两者的编译规则也不一样。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为: void foo( int x, int y ); 该函数被C编译器编译后在符号库中的名字可能为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。下面以例子说明,如何在C++中使用C的函数,或者在C中使用C++的函数。

(1)C++引用C函数的例子

//test.c
#include <stdio.h>
void mytest()
{
    printf("mytest in .c file ok\n");
}

//main.cpp
extern "C"
{
    void mytest();
}
int main()
{
    mytest();
    return 0;
}

 (2)在C中引用C++函数

在C中引用C++语言中的函数和变量时,C++的函数或变量要声明在extern "C"{}里,但是在C语言中不能使用extern "C",否则编译出错。

//test.cpp
#include <stdio.h>
extern "C"
{
     void mytest()
    {
         printf("mytest in .cpp file ok\n");
     }
}

//main.c
void mytest();
int main()
{
    mytest();
    return 0;
}

 (3)综合使用

一般我们都将函数声明放在头文件,当我们的函数有可能被C或C++使用时,我们无法确定是否要将函数声明在extern "C"里,所以,我们应该添加
#ifdef __cplusplus
extern "C"
{
     #endif
     //函数声明
     #ifdef __cplusplus
 }
#endif
如果我们注意到,很多头文件都有这样的用法,比如string.h,等等。
//test.h
#ifdef __cplusplus
#include <iostream>
using namespace std;
extern "C"
{
    #endif
     void mytest();
     #ifdef __cplusplus
}
#endif
这样,可以将mytest()的实现放在.c或者.cpp文件中,可以在.c或者.cpp文件中include "test.h"后使用头文件里面的函数,而不会出现编译错误。
//test.c
#include "test.h"
void mytest()
{
       #ifdef __cplusplus
       cout<< "coutmytest extern ok " <<endl;
       #else
       printf("printfmytest extern ok n");
       #endif
}
//main.cpp
#include "test.h"
int main()
{
     mytest();
     return 0;
}

 

 

posted @ 2012-08-02 21:52  always on the way  阅读(2360)  评论(0编辑  收藏  举报