extern “C” #ifndef #ifdef #undef #pragma once

来源:互联网 发布:数据可视化工程师薪酬 编辑:程序博客网 时间:2024/06/08 01:57

最近做CPP相关的东西,然后对CPP项目里面遇到的问题进行一个summary,主要的问题,title里大概表明了,在接下来的blog里面主要是讲一下这些东西的一些用法和应用场景等。算是对学习的一个总结吧。



1、extern “C”和extern

这两个东西的用法和作用是完全不一样的。extern “C”是C++代码调用C的代码,作用就是告诉编译器按照C的方式编译,我们都知道C++里面是支持函数重载,但是C里面是不支持的,那么有一个问题,编译器在编译这些重载函数的时候,为了区分开它们,内部是不是做了一些特殊处理以标记它们呢?(当然每种编译器的方法是有区别的)

#ifdef  __cplusplusextern "C" {#endif/* c的代码*/}

extern置于变量或者函数前,以标示变量或者函数定义在其他文件里面,可以告诉编译器在遇到这些变量或函数的时候在其他文件寻找其定义;实际上也是在声明变量或函数的作用范围,它们可以在其他文件中使用;它只是一个声明而不是一个定义。比如我们在其他文件中使用这些变量或者声明的时候,只需要包含其所在的头文件即可。


2、#ifndef、#ifdef和#undef

ifndef是“if not define”的简称,属于预处理功能的三种(宏定义,头文件包含,预编译)中的第三种预编译。

定义如下(参照百度百科):

#define x //定义一个宏...#endif//C语言在对程序进行编译时,会先根据预处理命令进行“预处理”。C语言编译系统包括预处理,编译和链接等部分。#ifndef x //先测试x是否被宏定义过#define x程序段1 //如果x没有被宏定义过,定义x,并编译程序段 1#else程序段2 //如果x已经定义过了则编译程序段2的语句,“忽视”程序段 1。#endif//终止if

作用:主要的功能就是防止头文件的重复包含和编译;举个例子,最近的一个项目需要用到很多宏函数和宏,然后我们就将所有的宏放在一个头文件,需要用到这些头文件的时候只需要inlude一下就好了,但是因为头文件很多,很多情况下需要重复的include,这样就遇到一个问题,解决办法就是使用#ifndef来解决这个问题。

ifdef是“if define:的简称,属于预编译。

#ifdef 标识符//程序段1#else//程序段2#endif//当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。

举个例子:
#include <iostream>using namespace std;#define DEBUGint main(int argc, char *argv[]){#ifdef DEBUGcout << "Beginning execution of main()" << endl;#endifreturn 0;}//这个cpp会打印这句话;但是加入我们没有define这个DEBUG,就不会打印。

作用:可以区分一些与特定头文件、程序库、其他文件版本的代码

#undef一般与#define连用


#define WIDTH 80  #define ADD( X, Y ) ((X) + (Y))  .  .  .  #undef WIDTH  #undef ADD  
//#undef可以移除宏的当前定义;如果遇到宏冲突的问题可以使用这个办法具体的看这篇博客http://blog.csdn.net/zhang_guyuan/article/details/77330604

3、#pragma once

#pragma once的功能和ifndef类似,都可以保证头文件被只编译一次

#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况。#pragma once则由编译器提供保证:同一个文件不会被编译多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
方式一由语言支持所以移植性好,方式二 可以避免名字冲突
#pragma once方式产生于#ifndef之后,因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受语言天生的支持,不受编译器的任何限制;而#pragma once方式却不受一些较老版本的编译器支持,换言之,它的兼容性不够好。也许,再过几年等旧的编译器死绝了,这就不是什么问题了。
我还看到一种用法是把两者放在一起的:
#pragma once
#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__
... ... // 一些声明语句
#endif
看起来似乎是想兼有两者的优点。不过只要使用了#ifndef就会有宏名冲突的危险,所以混用两种方法似乎不能带来更多的好处,倒是会让一些不熟悉的人感到困惑




 
原创粉丝点击