首页 > 其他分享 >C语言宏

C语言宏

时间:2023-09-17 11:23:19浏览次数:29  
标签:函数 定义 C语言 参数 文本 替换 define

C语言的宏可以分为宏定义和宏函数,宏定义又可以叫做对象式宏,在编译时直接把定义的内容替换到源码处,只是一个文本替换功能,不会进行计算。宏函数又叫做类函数宏,跟函数的使用类似,但是他的本质也是文本的替换,这就有产生很多注意事项。

#define N 10 //宏定义
#define max(a,b) (a>b? a:b) //宏函数

不管是宏定义还是宏函数,本质都是文本替换,把宏名称后面的文本参数替换到源码处,因此我们可以分为没有参数的宏和有参数的宏。

没有参数的宏

对于没有参数的宏,处理很简单,直接替换到源码就好了。

#define N 10 
#define six 2+4
#define print printf("打印的值为:");
print       //这里我不加分号,在宏定义里加,目的是让宏定义的文本替换更形象
printf("%d",N*six);

所以上述打印的值是多少呢?编译器把宏名称替换进去后,是这样的

printf("打印的值为:");
printf("%d",10*2+4);

可以看到,打印出来的值是24,而不是60,因为它是单纯文本替换,不计算,所以使用宏时要加上括号

#define N 10 
#define six (2+4)
printf("%d",N*six);

这样才能打印出60。

printf("%d",10*(2+4));

带参数的宏

前面最大值宏函数#define max(a,b) (a>b? a:b)就是带了参数的宏。这里的替换文本也加了括号,是不是随意使用都没有问题呢?不是!

#define max(a,b) (a>b? a:b)
max(3,4==4);

在替换时,ab是形参,34==4(1)是实参,参数之间用逗号隔开宏名称和括号之间不能有空格,否则就成为不带参数的宏,把(a,b) (a>b? a:b)替换进去了。

上面代码我们期望返回的是3,因为b=(4==4)的值是1,3大于1,但其实返回的是1。我们来替换一下,形参替换为实参,宏名替换为其他部分。

 (3>4==4? 3:4==4)

因为>==优先级相同,所以运算从左往右,因此逻辑表达式值为0,返回1即4==4

所以平时使用宏代码时,一定要注意,因为很容易出错。上述代码应该改为:

#define max(a,b) ((a)>(b)? (a):(b))
max(3,4==4);

每个形参都加括号,这样才能到达我们的目的。

对于宏还有几点注意:

  1. 宏定义中反斜杠的作用:对于比较长的替换文本,需要换行时应加入反斜杠,然后续写后面的内容。其中函数内代码换行也是加入反斜杠的,但是由于不用加也可以,为了代码美观,所以函数内单条一般不加反斜杠,直接换行。但是函数外则必须加入反斜杠换行才能进行续写。



2. 函数和宏函数的区别:我们说了宏只是文本替换,不做计算,虽然函数和带参数的宏用法类似,但是函数的操作不一样,它涉及到参数传递(将实参值赋值给形参)、函数调用和函数返回操作(入栈出栈)、返回值的传递,所以宏函数必然是要比函数的效率高的。
3. 宏的作用域:
你无法再次使用 #define 命令重新定义一个已经被定义为宏的标识符,除非重新定义所使用的替换文本与已经被定义的替换文本完全相同。如果该宏具有形参,重新定义的形参名称也必须与已定义形参名称的一样。
如果想改变一个宏的内容,必须首先使用下面的命令取消现在的定义:
#undef 宏名称
执行上面的命令之后,标识符“宏名称”可以再次在新的宏定义中使用。如果上面指定的标识符并非一个已定义的宏名称,那么预处理器会忽略这个 #undef 命令。
标准库中的多个函数名称也被定义成了宏。如果想直接调用这些函数,而不是调用同名称的宏,可以使用#undef 命令取消对这些宏的定义。即使准备取消定义的宏是带有参数的,也不需要在 #undef 命令中指定参数列表。如下例所示:

	#include <ctype.h>
	#undef isdigit          // 移除任何使用该名称的宏定义
	 /* ... */
	if ( isdigit(c) )               // 调用函数isdigit()
	 /* ... */

当某个宏首次遇到它的 #undef 命令时,它的作用域就会结束。如果没有关于该宏的 #undef 命令,那么它的作用域在该翻译单元结束时终止。

其他关于带参数的宏的用法,如可选参数、字符串化运算符(带#号)、 记号粘贴运算符等,参考文献1

参考文献:

  1. C语言宏的定义和宏的使用方法(#define)
  2. C语言基础--宏函数

标签:函数,定义,C语言,参数,文本,替换,define
From: https://www.cnblogs.com/gofan-SiTu/p/17707964.html

相关文章

  • C语言实例_实现malloc与free函数完成内存管理
    一、malloc和free函数介绍在C语言中,malloc和free是用于动态内存管理的函数。(1)malloc函数malloc函数用于在堆(heap)中分配指定大小的内存空间,并返回一个指向该内存块的指针。原型如下:void*malloc(size_tsize);size参数表示要分配的内存块的大小,以字节为单位。函数返回一个指向分配内......
  • C语言如何输入一个字符串?
    (C语言如何输入一个字符串?)用scanf输入字符串(有限制)整个字符串处理在scanf()和printf()函数中,%s指的就是字符串所以我们就可以使用scanf("%s",str)和printf("%s",str)从键盘处读取字符串并将字符串打印出来代码如下:intmain(){ charstr[10]={0}; scanf("%s",str......
  • C语言学习记录----函数
    1.函数是什么?数学中我们常见到函数的概念。但是你了解C语言中的函数吗?维基百科中对函数的定义:子程序在计算机科学中,子程序(英语:Subroutine,procedure,function,routine,method,subprogram,callableunit),是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完......
  • 初学者一定要了解的c语言数据类型详解来了
    @TOC前言`一、当我们要描述或者记录一些事物时,通常需要用一些数据来反映它的特征,例如:小明"男""19"岁,身高"1.88"米,在从语言中,要表示这些数据就需要设置合适的数据类型,那么c中数据有哪些类型提供给我使用呢?一、数据类型基本类型整形short//短整型int//整形l......
  • C语言实例_解析GPS源数据
    一、GPS数据格式介绍GPS(全球定位系统)数据格式常见的是NMEA0183格式,NMEA0183格式是一种用于导航设备间传输数据的标准格式,定义了一套规范,使得不同厂商的设备可以通过串行通信接口(常见的是RS-232)进行数据交换。这个标准最初由美国航海电子协会(NationalMarineElectronicsAssociat......
  • C语言学习——三大语法结构
    1.顺序结构C语言中的顺序结构是指程序中的语句按照从上到下的顺序依次执行,每一条语句都在前一条语句执行完毕后才执行,形成了线性的执行路径。这是C语言的基本执行方式,也是大多数编程语言的通用执行方式之一。以下是C语言顺序结构的特点:1.1从上到下执行:在C语言中,程序从main函数......
  • Ubuntu16.04下C语言编译及makefile应用
    一、不同环境下C语言的编译在Ubuntu16.04下:step1:编写main1.c主程序用nano编好,下面为主程序展示注意:1、主程序中函数的声明step2:编写子程序 step3:用gcc命令编译采用多个文件一起编译,输出放在main1中 gcc的常见用法:-c只生成目标文件不进行连接,用于对目标文件的分别......
  • 9月15日忆——学习C语言碎片
    EOF指的是endofflie,即文件结束符号,值为-1运用函数比较两个数的大小#include<stdio.h>intMax(intx,inty){if(x<y)returny;elsereturnx;}intmain(){inta=1;intb=2;intmax=Max(a,b);printf("%d\n",max);return0;}sizeof的相关知识inta=1;intarr[]={1,2,3,4,5,6}......
  • 七天学会C语言-第一天(C语言基本语句)
    一、固定格式这个是C程序的基本框架,需要记住!!!#include<stdio.h>intmain(){return0;}二、printf语句简单输出一句C程序:#include<stdio.h>intmain(){printf("大家好,");printf("我是");printf("沐尘而生!");return0;}运行结果:例2:#include......
  • C语言学习记录
    声明:#include<stdio.h>#include<string.h>#include<windows.h>#include<stdlib.h>#include<time.h>#include<math.h>1000到2000年之间的闰年intmain(){intyear=0;intcount=0;for(year=1000;year<=2000;year++)......