C语言宏定义#define的使用

目录
  • 无参宏定义
    • 定义形式
  • 带参宏定义
    • 定义形式
  • #和##运算
    • #运算 用法:
    • ##运算 用法:
  • 变参宏
  • #ifndef 条件编译

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

宏定义命令: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;
}

代码输出:

例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;
}

代码输出:

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

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

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

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

代码输出:

带参宏定义

定义形式

#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\n",M(3));
	printf("N(3):%d\n",N(3));

	printf("M(3+2):%d\n",M(3+2));
	printf("N(3+2):%d\n",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\n",((3)*(3)+3*(3)));
	printf("N(3):%d\n",(3*3+3*3));

	printf("M(3+2):%d\n",((3+2)*(3+2)+3*(3+2)));
	printf("N(3+2):%d\n",(3+2*3+2+3*3+2));
}

代码输出:

例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]));
}

代码输出:

#和##运算

#运算 用法:

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

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

代码输出:

##运算 用法:

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

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

代码输出:

变参宏

用法:

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

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

例:

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

代码输出:

#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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言#define拼接宏定义实现方式

    使用场合:拼接两个宏,一个是传入的宏.但是传入的宏不会被替换,反而原封不动的接了上去,这就尴尬了.经过各种尝试,居然成了,特此记录分享一下,方便大家学习. char A_param=0; char B_pramm=0; //添加宏定义 #define OBJECT A #define DEFINE_(X) X##_param //一次定义 #define DEFINE(X) DEFINE_(X) //再次定义 #define PARAM DEFINE(OBJECT) void fun() { /

  • C语言中的内联函数(inline)与宏定义(#define)详细解析

    先简明扼要,说下关键:1.内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,这样在运行时速度更快. 2.内联函数可以调试,而宏定义是不可以调试的.内联函数与宏本质上是两个不同的概念如果程序编写者对于既要求快速,又要求可读的情况下,则应该将函数冠以inline.下面详细介绍一下探讨一下内联函数与宏定义. 一.内联函数是什么?内联函数是代码被插入到调用者代码处的函数.如同 #define 宏(但并不等同,原因见下文),内联函数通过避免被调用的开销来提

  • 详解C语言#define预处理宏定义

    目录 #define介绍: #define宏定义无参的一般形式为:#define  标识符 常量 #define宏定义有参的一般形式为:#define  标识符(参数表) 表达式 #运算符: ##运算符: 可变宏...和__VA_ARGS__: 开发项目中常用的宏定义: #define介绍: C语言里可以用#define定义一个标识符来表示一个常量.特点是:定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了,也不做类型定义.预编译又叫预处理.预编译就是编译前的处理.这个操作是在

  • 详解C语言中的#define宏定义命令用法

    #define 命令#define定义了一个标识符及一个串.在源程序中每次遇到该标识符时,均以定义的串代换它.ANSI标准将标识符定义为宏名,将替换过程称为宏替换.命令的一般形式为: #define identifier string 注意: 1.该语句没有分号.在标识符和串之间可以有任意个空格,串一旦开始,仅由一新行结束. 2.宏名定义后,即可成为其它宏名定义中的一部分. 3.宏替换仅仅是以文本串代替宏标识符,前提是宏标识符必须独立的识别出来,否则不进行替换.例如: #define XYZ t

  • C语言宏定义#define的使用

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

  • C/C++语言宏定义使用实例详解

     C/C++语言宏定义使用实例详解 1. #ifndef 防止头文件重定义 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成 一个可执行文件时,就会出现大量"重定义"的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定义. 方法:例如要编写头文件test.h 在头文件开头写上两行: #ifndef TEST_H #define TEST_H //一般是文件名的大写 头文件结尾写上一行: #endif 这样一个工程文件里同时

  • C语言宏定义的扩展定义讲解

    目录 1. 常量宏定义 2. 定义宏函数 3. 宏定义和#号结合 4. 宏定义和两个#结合 5. 宏定义和do…while()的结合 6. #ifdef…#else…#endif 7. #ifndef…#else…#endif 8. #if defined() … #else … #endif 1. 常量宏定义 使用c中的#define 来定义一个常量来表示一年有多少秒 #define SECONDS_PER_YEAR (606024*365)UL 求圆的周长: #define D® (r +

  • C语言宏定义容易认不清的盲区梳理

    目录 1.概念 3.宏不是函数 4.宏定义不是说明或语句 5.宏不是类型定义 6.与之相关的宏定义 7.总结 1.概念 #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本. 命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义. (1)简单的宏定义: #define<宏名> <字符串> #defineVALUE((sizeof(a))/sizeof(a[0])) (2) 带参数的宏定义 #defin

  • C/C++中宏定义(#define)

    #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,使得程序的运行与预期的目的不一致,或者在读别人写的程序时,把运行结果理解错误,这对 C语言的学习很不利. 宏的定义在程序中是非常有用的,但是使用不当,就会给自身造成很大的困扰.通常这种困扰为:宏使用在计算方面. 本例子主要是在宏的计算方面,很多时候,大家都知道定义一个计算的宏,对于编译和编程

  • C语言宏定义使用分析

    1.如何区分宏定义中的"宏名称"和"宏字符串"?对于带参数的宏又该注意什么? 在宏定义中,"宏名称"和"宏字符串"是通过"空格"来区分的.编译器在处理时宏定义时,首先从"#define"后第一个空格开始读取字符串,直到遇见下一个空格为止,两个空格之间的字符串为"宏名称",确定好"宏名称"之后,本行的所有其他字符串都为"宏字符串"

  • C语言宏定义结合全局变量的方法实现单片机串口透传模式

    何谓透传? 根据百度百科给出的定义如下: 透传,即透明传输(pass-through),指的是在通讯中不管传输的业务内容如何,只负责将传输的内容由源地址传输到目的地址,而不对业务数据内容做任何改变. 在现实单片机产品开发过程中,如果存在多个串口,在调试打印某个模块信息的时候,大多数人的做法是将所有模块的TX.RX.GND引出来,分别接到不同的调试口去,通过PC终端去将这些信息分别打印出来.这样子做难免会弄错,甚至非常繁琐,万一不小心还会接错导致模块烧坏. 于是,透传模式的出现就是为了解决这样的问

  • C语言详细分析宏定义的使用

    目录 一.C语言中函数的“缺陷” 二.再次理解函数 三.C语言中的宏 四.宏与函数的不同 五.编译器组成简介 六.宏使用示例 七.再论宏常量 八.小结 一.C语言中函数的“缺陷” 实参和形参之间仅仅是值传递,因此,函数中无法直接改变实参. 二.再次理解函数 函数是一种代码复用的手段 把实现某个功能的代码片段进行封装(当作一个整体) 给这个代码片段一个合适的名字(通过名字使用代码) 定义参数(定义代码片段需要处理的问题) 三.C语言中的宏 宏是C语言中代码复用的补充方式 宏定义语法:#define

随机推荐