C++预处理宏定义

  • Post author:
  • Post category:其他


在看程序的时候看到了#ifdef之标志,感觉有写混淆,于是就查了查,结果就把预处理宏定义之类的给翻出来了,重新整理一下。

1、C++提供的预处理,宏定义、文件包含、条件编译三种,预处理是编译之前要做的工作,不进行语法检查,

预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作。说白了,就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。

2、宏定义:

#define


标识符



字符串,于是就是把程序中设计到的字符串换成相应的具体数据,有利于统一进行修改。宏定义使用的时候有几条语法规则要记牢:

(1)宏名一般用大写
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:

数组

大小常用宏定义
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4

)宏定义末尾不加分号;
(5)宏定义写在函数的花括号外边,

作用域

为其后的程序,通常在文件的最开头。
(6)可以用

#undef

命令终止宏定义的

作用域
(7)宏定义允许嵌套


8)字符串” “中永远不包含宏
(9)宏定义不分配内存,

变量

定义分配内存。

(10)宏定义不存在类型问题,它的参数也是无类型的。



(以上摘自百度)


3、文件包含:#include<>是预处理好的。

4、条件编译:


一般情况下,源程序中所有的行都参加编译。但有时希望对其中一部分内容只在满足一定条件下才进行编译,即对一部分内容指定编译条件,这就是“条件编译”(conditional compile)




1:情况1:




#ifdef _XXXX




…程序段1…




#else




…程序段2…




#endif




这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。




例:




#define NUM




………….




………….




………….




#ifdef NUM




printf(“之前NUM有过定义啦!:) \n”);




#else




printf(“之前NUM没有过定义!:( \n”);




#endif




}




如果程序开头有#define NUM这行,即NUM有定义,碰到下面#ifdef NUM的时候,当然执行第一个printf。否则第二个printf将被执行。




我认为,用这种,可以很方便的开启/关闭整个程序的某项特定功能。




2:情况2:




#ifndef _XXXX




…程序段1…




#else




…程序段2…




#endif




这里使用了#ifndef,表示的是if not def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。例子就不举了。




3:情况3:




#if 常量




…程序段1…




#else




…程序段2…




#endif




这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。




我认为,这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。




2013年11月8日 再编辑



.头文件中的#ifndef

头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。

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

#ifndef <标识>

#define <标识>

……

……

#endif

<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

#ifndef _STDIO_H_

#define _STDIO_H_

……

#endif




2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。

#ifndef AAA

#define AAA



int i;



#endif

里面有一个变量定义

在vc中链接时就出现了i重复定义的错误,而在c中成功编译。

结论:

(1).当你第一个使用这个头的.cpp文件生成.obj的时候,int i 在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,int i 又被定义然后两个obj被另外一个.cpp也include 这个头的,连接在一起,就会出现重复定义.

(2).把源程序文件扩展名改成.c后,VC按照C语言的语法对源程序进行编译,而不是C++。在C语言中,若是遇到多个int i,则自动认为其中一个是定义,其他的是声明。

(3).C语言和C++语言连接结果不同,可能(猜测)时在进行编译的时候,C++语言将全局

变量默认为强符号,所以连接出错。C语言则依照是否初始化进行强弱的判断的。(参考)

解决方法:

(1).把源程序文件扩展名改成.c。

(2).推荐解决方案:

.h中只声明 extern int i;在.cpp中定义




<x.h>

#ifndef __X_H__

#define __X_H__

extern int i;

#endif //__X_H__

<x.c>

int i;

注意问题:

(1).变量一般不要定义在.h文件中。

问题来自学习过程,资料来自网络,结果来自整理,仅供参考。

#ifndef#ifdef#endif含义及解析2008-03-12 21:04Q:

#ifndef的主要作用是什么?

#ifndef的主要作用是什么?是不是防止重复定义,具体来说是怎么防止的?

A:

防止重复编译

以test.h为例:

#ifndef TEST_H

#define TEST_H

#endif

A:

条件编译




A:

#ifndef XXX

#define XXX

….

#endif

一般是用来防止重复包含头文件

第一次包含头文件时 XXX没有被定义 第二次再用时 XXX 已经被定义拉

就不在包含这个头文件

A:

如果一个文件中(a.h):

#ifndef _A

#define _A

….

#endif //_A

那么在如下情况下,a.h在预编译时只被展开一次

#include “a.h”

#include “a.h”

A:

条件指示符#ifndef检查预编译常量在前面是否已经被定义.如果在前面没有被定义,则条件指示符的值为真,于是从#inndef到#endif之间的所有语句都被包含进来进行处理.相反,如果#inndef指示符的值为假,则它与#endif指示符之间的行将被忽略.

A:

环境判断,判断操作系统。判断cpu类型。判断动态dll是输入还是输出。

条件编译等

A:

条件指示符#ifndef检查预编译常量在前面是否已经被定义.如果在前面没有被定义,则条件指示符的值为真,于是从#inndef到#endif之间的所有语句都被包含进来进行处理.相反,如果#inndef指示符的值为假,则它与#endif指示符之间的行将被忽略.

A:




如果重复调用头文件时,第一次是没有被定义的,所以,就定义它,但第二次调用此头文件时,由于第一次已经定义,所以,这次就不重复定义了,

#ifnded 翻译过来,就是,“如果没有被定义,则……”

A:

条件指示符#ifndef 的最主要目的是防止头文件的重复包含和编译

A:

《C++编程思想》P37

重复声明问题在C++中很少出现,因为第个数据类型(带有函数的结构)一般有自己的头文件。但我们如果希望创建使用某个数据类型的另一个数据类型,必须在另一个头文件中包含它的头文件。在整个项目中,很可能有几个文件包含同一个头文件。在编译期间,编译器会几次看同一个头文件。除非做适当的处理,否则编译器将认为是结构重复声明。

典型的防止方法是使用预处理器隔离这个头文件。如果有一个头文件名为FOO。H,一般用“名字分解”产生预处理名,以防止多次包含这个头文件。FOO。H的内部可以如下:

#ifndef FOO_H

#define FOO_H

//Rest of header here…

#endif //FOO_H

注意:不用前导下划线,因为标准C用前导下划线指明保留标识符。