服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言宏定义#define的使用

C语言宏定义#define的使用

2022-08-14 10:49南城Flipped C/C++

本文主要介绍了C语言宏定义#define的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

        宏定义是高级语言编译器提供的常用语法,其目的是利用某一标识符标识某个文本字符串。在编写程序时,如果程序中反复地使用某个数据或某段程序片段,就可以考虑将这个数据或程序片段定义为宏,然后每个出现该数据或程序片段的地方用宏名替代,选择宏定义来做的好处是程序简洁,可读性好,而且当需要修改这些相同的程序片段时,只要修改宏定义中的字符串即可,不需要修改多处。

        宏定义命令:define

       优点:方便程序的修改,同时也能提高程序的运行效率。

        宏定义一般有两种形式:无参宏定义和带参宏定义。

 

无参宏定义

 

 

定义形式

#define 标识符 字符串

注意:
        1.宏定义是用宏名来表示一个字符串,在宏展开时以该字符串取代宏名,只是简单的替换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理不作任何检查。只在编译时检查。
        2.宏定义行末不必加分号(除非你的宏内容中需要有分号)。
        3.宏定义必须写在函数之外,作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令 

例1:输入圆的半径输出圆的周长和面积

#include <stdio.h>
#define PI 3.14 
int main(){
    int r;
    printf("输入半径:");
    scanf("%d",&r);
	printf("圆的周长为:%.2f,面积为:%.2f",2*PI*r,PI*r*r); 
    return 0;
}

预处理阶段进行宏替换↓:

#include <stdio.h>
int main(){
    int r;
    printf("输入半径:");
    scanf("%d",&r);
	printf("圆的周长为:%.2f,面积为:%.2f",2*3.14*r,3.14*r*r); 
    return 0;
}

代码输出: 

C语言宏定义#define的使用

 例2:通过宏定义输出字符串

#include <stdio.h>
#define HELLO "Hello,"
#define WORLD "World!"
int main(){
    printf(HELLO WORLD);
    return 0;
}

预处理阶段进行宏替换↓:

#include <stdio.h>
int main(){
    printf("Hello," "World!");
    return 0;
}

代码输出:

 

C语言宏定义#define的使用

例3:请问如下代码S1和S2的输出是否相等

 
#include <stdio.h>
#define S1 3+4
#define S2 (3+4)
int main(){
    printf("S1:%d
",S1*5);
    printf("S2:%d
",S2*5);
    return 0;
}

预处理进行宏替换↓(这里就体现出了直接替换并不会因为你的宏先定义就先计算,而是替换后再做后续处理):

#include <stdio.h>
#define S1 3+4
#define S2 (3+4)
int main(){
    printf("S1:%d
",3+4*5);
    printf("S2:%d
",(3+4)*5);
    return 0;
}

 代码输出:

C语言宏定义#define的使用

 

 带参宏定义

定义形式

#define 宏名(形参表) 字符串

例1:M(3)==N(3)?  M(3+2)==N(3+2)?

#include<stdio.h>
#define  M(y)  ((y)*(y)+3*(y))
#define  N(y)  (y*y+3*y)
int main(){
	printf("M(3):%d
",M(3));
	printf("N(3):%d
",N(3));
	
	printf("M(3+2):%d
",M(3+2));
	printf("N(3+2):%d
",N(3+2));
}

预处理阶段进行宏替换↓(这个例题主要是为了提醒大家如果要用宏定义进行一些计算,最好将参与计算的所有变量都加上括号以防本题中的情况出现):

#include<stdio.h>
#define  M(y)  ((y)*(y)+3*(y))
#define  N(y)  (y*y+3*y)
int main(){
	printf("M(3):%d
",((3)*(3)+3*(3)));
	printf("N(3):%d
",(3*3+3*3));
	
	printf("M(3+2):%d
",((3+2)*(3+2)+3*(3+2)));
	printf("N(3+2):%d
",(3+2*3+2+3*3+2));
}

 代码输出:

C语言宏定义#define的使用

 例2:通过宏来计算数组中元素个数

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define Size_Array(b) sizeof(b)/sizeof(b[0])
int main(){
	int i;
	srand((unsigned)time(NULL));
	int b[i=rand()%100];
	printf("随机数为:%d 数组元素个数为:%d",i,Size_Array(b));
}

 预处理阶段进行宏替换↓(很经典的面试小题):

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
	int i;
    srand((unsigned)time(NULL));
	int b[i=rand()%100];
	printf("随机数为:%d 数组元素个数为:%d",i,sizeof(b)/sizeof(b[0]));
}

 代码输出:

C语言宏定义#define的使用

 

#和##运算 

 

#运算 用法:

        # 运算符的用处就是把符号转化为字符串。例如,如果 a 是一个宏的形参,则替换文本中的 #a 则被系统转化为 “a”。        

#include <stdio.h>
#define TO_STR(s) #s
int main(){
    printf(TO_STR(HelloWorld!));
    return 0;
}

 代码输出: 

C语言宏定义#define的使用

 

##运算 用法:

        ## 运算符可以用在替换文本中,而它的作用是起到粘合的作用,即将两个符号组合成一个符号。

#include <stdio.h>
#define CONCAT(x,y) x##y
int main(){
    printf("%d", CONCAT(1,000));
    return 0;
}

  代码输出:

C语言宏定义#define的使用

 

变参宏

用法:

        当要调用printf类似不确定参数格式时可以使用__VA_ARGS__,在宏定义中,形参列表的最后一个参数为省略号“…”,“__VA_ARGS__”就可以被用在替换文本中,来表示“…”代表了什么。     

#define PR(...) printf(__VA_ARGS__)     //宏定义
PR("hello
");                          //宏调用

例:

#include <stdio.h>
#define P(X, ...) printf("get:"#X":"__VA_ARGS__)
int main(){
    int j=20,i=10;
    P(10, "j = %d
", j); 
	P(10, "j = %d i=%d
", j,i);      
    return 0;
}

   代码输出:

 C语言宏定义#define的使用

 

#ifndef 条件编译

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

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

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

        使用#ifndef可以避免这种错误:

#ifndef x    //先测试x是否被宏定义过
#define x
   code1     //如果x没有被宏定义过,定义x,并编译code1
#endif   
  code2     //如果x已经定义过了则编译code2,跳过code1

        适当的使用条件编译和宏定义可以让代码的运行效率更高,特别是在进行大项目的时候当某个数值使用次数较多且修改比较频繁的情况下,宏定义也是比较高效的(当然函数也可以,等有时间写完函数再来比较一下函数和宏的优缺点吧) 

到此这篇关于C语言宏定义#define的使用的文章就介绍到这了,更多相关C语言宏定义#define内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/m0_57882370/article/details/122379858

延伸 · 阅读

精彩推荐
  • C/C++C++实现涂色游戏(博弈)

    C++实现涂色游戏(博弈)

    这篇文章主要为大家详细介绍了C++实现涂色游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    LSC_3339992021-08-13
  • C/C++C语言实现简单计算器功能(2)

    C语言实现简单计算器功能(2)

    这篇文章主要为大家详细介绍了C语言实现简单计算器功能的第二部分,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一...

    xiaocaidayong9052021-08-20
  • C/C++c++隐式类型转换示例分享

    c++隐式类型转换示例分享

    这篇文章主要介绍了c++隐式类型转换的二个示例,需要的朋友可以参考下...

    C++教程网10662021-01-17
  • C/C++一篇文章带你了解C语言内存对齐公式

    一篇文章带你了解C语言内存对齐公式

    这篇文章主要介绍了C语言内存对齐,包括内存对其的基本概念及用法,以及注意事项,并以实例形式加以说明,需要的朋友可以参考下,希望能给你带来帮助...

    Wallace Zhang6942021-12-15
  • C/C++VS2019中CMake项目如何指定c++语言标准

    VS2019中CMake项目如何指定c++语言标准

    这篇文章主要介绍了VS2019中CMake项目如何指定c++语言标准,需要的朋友可以参考下...

    江小举5972021-08-17
  • C/C++C++设计模式之抽象工厂模式

    C++设计模式之抽象工厂模式

    这篇文章主要介绍了C++设计模式之抽象工厂模式,本文要讲的抽象工厂模式,就是工厂方法模式的扩展和延伸,需要的朋友可以参考下...

    果冻想7022021-02-03
  • C/C++GCC 编译使用动态链接库和静态链接库的方法

    GCC 编译使用动态链接库和静态链接库的方法

    根据链接时期的不同,库又有静态库和动态库之分,有别于静态库,动态库的链接是在程序执行的时候被链接的...

    C语言之家2712020-11-18
  • C/C++vscode搭建STM32开发环境的详细过程

    vscode搭建STM32开发环境的详细过程

    这篇文章主要介绍了vscode搭建STM32开发环境的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    顶点元8772021-11-03