C语言之宏详解(超级详细!)

这篇具有很好参考价值的文章主要介绍了C语言之宏详解(超级详细!)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、用宏前须知-#define相关知识

        大致结构:

         对预定义符号的补充:

二、用#define定义宏

        什么是宏?

        #define的替换规则:

三、常用的宏定义

1、宏定义常量

2、定义一个宏语句

3、宏定义函数

        宏与函数的对比:

4、#和## 分别字符串化和将两个符号连接成一个符号 

#字符串化

 ##将两个符号连接成一个符号

四、与宏相关的作用符号

1、换行符 '\'

2、取消宏定义#undef 

五、命名约定


一、用宏前须知-#define相关知识

        大致结构:

#define    name    stuff

         自定义名    内容

        栗子:

#define OP 256
#define YU "youarewelcome"
#define S(r) (r*r)
#define REG register          //为 register这个关键字,创建一个简短的名字
#define PRINT printf("file:%s line:%d\n", __FILE__, __LINE__)//__FILE__,__LINE__这是个啥?别急后面有补充!

#include<stdio.h>
int main()
{
	printf("%d \n", OP);
	printf("%s \n",YU);
	printf("%d \n", S(6));
	PRINT;
	return 0;
}

         c语言宏定义详解,c语言,开发语言


         对预定义符号的补充:

__FILE__      //进行编译的源文件 
__LINE__     //文件当前的行号 
__DATE__    //文件被编译的日期 
__TIME__    //文件被编译的时间 
__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

二、用#define定义宏

        什么是宏?

        宏可以看作为一些命令的集合。它是一种预处理器指令,在预编译阶段将宏名替换为后面的替换体。

        而#define可以用来定义宏:

        #define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。

        宏的声明方式:

  #define name( parament-list ) stuff
//其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中

        栗子:

        实现一个开平方的宏        

#define SQ(x) x*x

printf("%d \n", SQ(7));

        他的实际执行结构为7*7->即为49

        还是用这个我们刚刚定义的宏

        我们执行下面这段代码:       

int a=6;

printf("%d \n", SQ(6+1));

        他的实际执行结构为6+1*6+1->即为13

        这说明了什么?这印证了上面所说的宏是把参数替换到文本中,也就是宏直接吧6+1替换掉了x直接带入了后面的表达式当中了!

        对此,根据我们原来的用意。这时我们可以用括号来解决这个问题:

#define SQ(x) (x)*(x)

        这给了我们一个提醒:我们在用宏时最好多用括号,以此来避免不必要的错误!

再看个栗子:

#define DOUBLE(x) (x) + (x) 
int a = 5; 
printf("%d\n" ,10 * DOUBLE(a));

        在这个例子中我们对这个宏使用了括号,乍一看这个例子输出的值像是100

        但是实际呢?上图!

      c语言宏定义详解,c语言,开发语言

来看看实际它怎么执行的,它执行替换操作实际上为:

printf ("%d\n",10 * (5) + (5));

        因此我们说定义宏要多用括号!

#define DOUBLE( x)   ( ( x ) + ( x ) )

        改成这样就能实现想要的效果啦!


        #define的替换规则:

        在程序中扩展#define 定义符号和宏时,需要涉及几个步骤:
1. 在调用宏时,首先对参数进行检查,看看是否包含任何由 #define 定义的符号。如果是,它们首先被替换。
2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果文件进行扫描,看看它是否包含任何由 #define 定义的符号。如果是,就重复上 述处理过程。
        注意:
1. 宏参数和 #define 定义中可以出现其他 #define 定义的符号。但是对于宏,不能出现递归。
2. 当预处理器搜索 #define 定义的符号的时候,字符串常量的内容并不被搜索。

三、常用的宏定义

1、宏定义常量

         定义诸如:字符串、整形数、浮点型数等等的常量.

        栗子:

#define AO 114514
#define NTR "我可太喜欢了"
#define KK 3.14
#include<stdio.h>
int main()
{
	printf("%d %s %f", AO, NTR, KK);
	return 0;
}

       c语言宏定义详解,c语言,开发语言


2、定义一个宏语句

        栗子:

#include<stdio.h>
#define PFINT printf("hello world!\n");
int main()
{
	PFINT///预处理时会被替换为 printf("hello world!\n");
	return 0;
}

3、宏定义函数

        宏可以接受参数,类似于真正的函数一样。具体的接受参数方法与函数差不多,只不过不用指定函数类型,这也是宏定义函数的一个优势!比如:当我定义了一个函数有时要传整形,有时要传浮点型,函数可能要根据类型来多定义几个,而宏只需要一个就行了!

        栗子1:

#define MAX(a, b) ((a)>(b)?(a):(b))
#include<stdio.h>

int main()
{
	printf("%d", MAX(114, 514));
	return 0;
}

       c语言宏定义详解,c语言,开发语言

        栗子2:

#define MALLOC(num, type)\ 
(type *)malloc(num * sizeof(type)) //这和\是干啥的?详见地四大点\的作用
... 
//使用 
MALLOC(10, int);//类型作为参数 
//预处理器替换之后: 
(int *)malloc(10 * sizeof(int)); 

        这个例子中,函数是做不到跟宏相同的效果的,所以说为啥有了函数我们还要定义宏呢?这个就是一个很明显的例子。


        宏与函数的对比:

c语言宏定义详解,c语言,开发语言


4、#和## 分别字符串化将两个符号连接成一个符号 

#字符串化

        这个很好理解看看例子就会了!

        栗子:

#define STR(exp) printf("%s\n",#exp);
#include<stdio.h>
int main()
{
	STR(for fun)
	return 0;
}

      c语言宏定义详解,c语言,开发语言


 ##将两个符号连接成一个符号

        ##可以把位于它两边的符号合成一个符号。 它允许宏定义从分离的文本片段创建标识符。

        栗子:

#include<stdio.h>
#define ADD_TO(num, value) num##value


int main()
{
	int a = ADD_TO(114, 514);
	printf("%d \n", a);
	return 0;
}

       c语言宏定义详解,c语言,开发语言


四、与宏相关的作用符号

1、换行符 '\'

        在每行末尾(除了最后一行)加上"\",代表换行的意思。这个目的是为了不让代码冗余,如果代码都挤在一段,代码就不美观,可读性不好。

        栗子:

#include<stdio.h>
#define PFINT printf("hello world!\n");\
			  printf("goodbye world!\n");
#define NUM 1,\
			2,\
			3
int main()
{
	PFINT
	int x[] = { NUM };//->int x[] = { 1,2,3 };
	printf("%d %d %d \n", x[0], x[1], x[2]);
	return 0;
}

       c语言宏定义详解,c语言,开发语言


2、取消宏定义#undef 

        这条指令用于移除一个宏定义。        

#define SORT 1000
#undef SORT

        在#undef之后SORT就相当于没有定义,失效了。再使用则会报错!


五、命名约定

        细心的朋友可能发现了!我在定义宏时用的都是大写的字母来作为它自定义的名字!

        这是因为这有一个默认的命名约定:

        一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。

        那我们平时的一个习惯是:

        把宏名全部大写

        函数名不要全部大写                                     


       感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!

c语言宏定义详解,c语言,开发语言文章来源地址https://www.toymoban.com/news/detail-715154.html

到了这里,关于C语言之宏详解(超级详细!)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Go语言】go_session(超级详细)

    国赛初赛有一道题目go session,用go的Gin框架和pongo2模板引擎写的,是关于go的pongo2模板注入和flask的热加载,当时看着一脸懵逼,现在再看突然豁然开朗。 主目录: route文件夹: main.go main.go主要是引入route文件里面的内容,并且设置路由 route.go 这是一个路由文件,使用了Gin框

    2024年02月12日
    浏览(32)
  • C语言中的static的用法(超级详细)

    🌹作者:云小逸 📝个人主页:[云小逸的主页] 📝码云:云小逸 (YunXiaoYi003) 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。希望

    2024年01月16日
    浏览(46)
  • A* 算法详解(超级详细讲解,附有大图)

    目录 引入  一.基本概念 二.算法原理 ①用宽度优先搜索 ②狄克斯特拉算法 ③A*算法 三.需要注意 四.c++伪代码 最后 今天想跟大家聊的,是我们经常用到,但是却让大家觉得十分神秘的那个算法:A* 。 这是一个远古而又非常经典的游戏——红警和 贪玩蓝月 玩的时候,就会发

    2023年04月08日
    浏览(32)
  • 超级详细用C语言判断一个数是否是素数

    先上代码: #include stdio.h int main() {         int n,i;     printf(\\\"请输入一个数: \\\");     scanf(\\\"%d\\\",n);     for(i=2;in;i++){         if(n%i==0){             break;         }     }     if(n==i){         printf(\\\"是素数\\\");     }     else         printf(\\\"不是素数\\\"); } 理解: 素数

    2024年02月08日
    浏览(90)
  • 【Golang】VsCode下开发Go语言的环境配置(超详细图文详解)

    📓推荐网站(不断完善中):个人博客 📌个人主页:个人主页 👉相关专栏:CSDN专栏、个人专栏 🏝立志赚钱,干活想躺,瞎分享的摸鱼工程师一枚 ​ 话说在前,Go语言的编码方式是 UTF-8 ,理论上你直接使用文本进行编辑也是可以的,当然为了提升我们的开发效率我们还是需

    2024年02月07日
    浏览(83)
  • 三子棋游戏----C语言版【超级详细 + 视频演示 + 完整源码】

    ㊙️小明博客主页:➡️ 敲键盘的小明 ㊙️ ✅关注小明了解更多知识☝️ 提示:本篇文章为C语言版的三子棋小游戏的制作,内含超详细讲解和完整源码,以及视频演示,内容如若有误,请联系小明及时更正。 转载请注明原创,谢谢。 提示:以下是本篇文章正文内容:  

    2024年04月14日
    浏览(34)
  • 【数据结构】—超级详细的归并排序(含C语言实现)

    ​                                         食用指南:本文在有C基础的情况下食用更佳                                          🔥 这就不得不推荐此专栏了: C语言                                        ♈️ 今日夜电波:斜陽—ヨルシカ            

    2024年02月08日
    浏览(41)
  • Spring Boot入门(14):使用Mybatis-Plus执行自定义SQL | 超级详细,建议收藏

            在上几期,我们既讲了如何整合Mybatis-Plus进行数据库的增删改查,也讲解了如何使用MP的 Wrapper 构造器,但若是遇到复杂业务逻辑,如多表联查、动态拼接条件等,这些操作往往会让代码变得冗长且难以维护。但是,有了Mybatis-Plus这个优秀的框架,我们可以轻松实现

    2024年02月12日
    浏览(35)
  • Windows API编程01-详解第一个程序(超级详细)

    联系WeChat:i-xiaodi,交流,付费课程学习 简单介绍Windows API: Windows API(Application Programming Interface)是Microsoft Windows平台的应用程序编程接口,其主要目的是让应用程序开发人员可以调用操作系统提供的一组例程功能,而无须考虑其底层的源代码实现及内部工作机制。API函数是

    2024年01月21日
    浏览(39)
  • Spring Boot入门(23):基于AOP实现自定义注解拦截接口日志并保存入库 | 超级详细,建议收藏

            在上两期中,我们着重介绍了如何集成使用 Logback 与 log4j2 日志框架的使用,今天我们讲解的主题依旧跟日志有关,不过不是使用何种开源框架,而是自己动手造。         Spring的核心之一AOP;AOP翻译过来叫面向切面编程, 核心就是这个切面. 切面表示从业务逻辑中

    2024年02月11日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包