宏定义define ifndef endif

宏定义define ifndef endif目录 define 宏定义一 无参宏定义二 带参宏定义 ifndef 条件编译 define 宏定义在 C 或 C 语言源程序中允许用一个标识符来表示一个字符串 称为 宏 define 为宏定义命令 被定义为 宏 的标识符称为 宏名 在编译预处理时 对程序中所有出现的 宏名 都用宏定义中的字符串去代换 这称为 宏代换 或 宏展开 宏定义是由源程序中的宏定义命令完成的 宏代换是由预处理程序自动完成的 优点 1 方便程序的修改 这个就不多说了 2

目录

#define  宏定义

一、无参宏定义

二、带参宏定义

#ifndef 条件编译


#define  宏定义

在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为“宏”。“define”为宏定义命令

被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”

宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。

优点:

 (1) 方便程序的修改。这个就不多说了。

 (2) 提高程序的运行效率。使用带参数的宏定义可完成函数调用的功能,又能减少系统开销,提高运行效率。正如C语言中所讲,函数的使用可以使程序更加模块化,便于组织,而且可重复利用,但在发生函数调用时,需要保留调用函数的现场,以便子函数执行结束后能返回继续执行,同样在子函数执行完后要恢复调用函数的现场,这都需要一定的时间,如果子函数执行的操作比较多,这种转换时间开销可以忽略,但如果子函数完成的功能比较少,甚至于只完成一点操作,如一个乘法语句的操作,则这部分转换开销就相对较大了,但使用带参数的宏定义就不会出现这个问题,因为它是在预处理阶段即进行了宏展开,在执行时不需要转换,即在当地执行。宏定义可完成简单的操作,但复杂的操作还是要由函数调用来完成,而且宏定义所占用的目标代码空间相对较大。所以在使用时要依据具体情况来决定是否使用宏定义。

在C或C++语言中,“宏”分为有参数和无参数两种。

一、无参宏定义

1.  无参宏定义的一般形式为:#define 标识符 字符串

2.  其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。

#include 
   
     #define M ( a+b ) int main( int argc, char * argv[] ) { int s, a, b; printf( "input number a& b: " ); scanf( "%d%d", &a, &b ); s = M*M; printf( "s=%d\n" ,s ); } 
   

上例程序中首先进行宏定义,定义M来替代表达式(a+b),在 s= M * M 中作了宏调用。在预处理时经宏展开后该语句变为: S=(a+b)*(a+b) 但要注意的是,在宏定义中表达式(a+b)两边的括号不能少。否则会发生错误。  

如当作以下定义后:#define M (a)+(b)  在宏展开时将得到下述语句:S= (a)+(b)*(a)+(b)

二、带参宏定义

c语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。

带参宏定义的一般形式为:  #define 宏名(形参表) 字符串

#define M(y) ((y)*(y)+3*(y)) /*宏定义*/ k = M(5); /*宏调用*/

如果想用宏定义实现max函数的话,写法如下:

#include 
   
     using namespace std; #define MAX(a,b) (a 
     
   

因为MAX带有返回值,而且在等号右边,所以if语句的写法必须是这种形式,而不能是 if else;

宏定义也可以实现替换多条语句,如下例子:

#include 
   
     using namespace std; #define fuck(a,b) a++; b++; for(int i=0; i<=10; i++) cout< 
     
   

#ifndef 条件编译

  它是if not define 的简写,是宏定义的一种,实际上确切的说,这应该是预处理功能三种(宏定义、文件包含、条件编译)中的一种—-条件编译。

  在c语言中,对同一个变量或者函数进行多次声明是不会报错的。所以如果h文件里只是进行了声明工作,即使不使用# ifndef宏定义,多个c文件包含同一个h文件也不会报错。

  但是在c++语言中,#ifdef的作用域只是在单个文件中。所以如果h文件里定义了全局变量,即使采用#ifdef宏定义,多个c文件包含同一个h文件还是会出现全局变量重定义的错误。

使用#ifndef可以避免下面这种错误:如果在h文件中定义了全局变量,一个c文件包含同一个h文件多次,如果不加#ifndef宏定义,会出现变量重复定义的错误;如果加了#ifndef,则不会出现这种错误。

示例:

#ifndef x //先测试x是否被宏定义过 #define x 程序段1 //如果x没有被宏定义过,定义x,并编译程序段 1 #endif   程序段2   //如果x已经定义过了则编译程序段2的语句,“忽视”程序段 1

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

了解:条件编译当然也可以用条件语句来实现。 但是用条件语句将会对整个源程序进行编译,生成的目标程序程序很长,而采用条件编译,则根据条件只编译其中的程序段1或程序段2,生成的目标程序较短。如果条件选择的程序段很长,采用条件编译的方法是十分必要的。

#ifndef 和 #endif 要一起使用,如果丢失#endif,可能会报错。

总结一下:

在c语言中,对同一个变量或者函数进行多次声明是不会报错的。所以如果h文件里只是进行了声明工作,即使不使用# ifndef宏定义,一个c文件多次包含同一个h文件也不会报错。 

使用#ifndef可以避免下面这种错误:如果在h文件中定义了全局变量,一个c文件包含同一个h文件多次,如果不加#ifndef宏定义,会出现变量重复定义的错误;如果加了#ifndef,则不会出现这种错.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212423.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午8:05
下一篇 2026年3月18日 下午8:05


相关推荐

  • 分治算法详解_算法的优劣通常用什么来衡量

    分治算法详解_算法的优劣通常用什么来衡量分治算法详解 一、基本概念  在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……   任何一个可以用计算机求解的问

    2025年8月14日
    4
  • 常用css样式大全以及css属性代码大全

    常用css样式大全以及css属性代码大全常用 css 样式大全字体属性 font 大小 font size x large 特大 xx small 极小 一般中文用不到 只要用数值就可以 单位 PX PD 样式 font style oblique 偏斜体 italic 斜体 normal 正常 行高 line height normal 正常 单位 PX PD EM 粗细 font weight bold 粗体 lighter 细体 normal 正常 变体 font va

    2026年3月18日
    3
  • C++常见几种输入方法评测(int && long long)

    C++常见几种输入方法评测(int && long long)

    2021年9月27日
    48
  • ubuntu android studio_android自启动

    ubuntu android studio_android自启动(1)添加头文件:#include(2)在特定驱动结构体中添加early_suspend结构:#ifdefCONFIG_HAS_EARLYSUSPENDstructearly_suspendearly_suspend;#endif(3)在驱动probe函数中注册相关early_suspend结构体:#ifdefCONFIG_HAS_EARLYSUSPEND

    2026年1月17日
    5
  • 代码触发,手动触发touchstart事件,touch事件,click事件,自定义事件

    代码触发,手动触发touchstart事件,touch事件,click事件,自定义事件代码触发,手动触发touchstart事件,touch事件,click事件,自定义事件

    2022年6月19日
    31
  • Quartz定时任务[通俗易懂]

    一、Quartz的核心概念1.任务jobjob就是想要实现的任务类,每一个job必须实现job接口,且实现接口中的excute()方法。2.触发器TriggerTrigger为你执行任务的触发器,可以设置特定时间执行该任务Trigger主要包含SimpleTrigger和CronTrigger两种3.调度器SchedulerScheduler为任务的调度器,它会将任务job及触发器…

    2022年4月18日
    72

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号