C语言_宏定义

C语言_宏定义一 预处理 编译一个 C 语言程序的第一步骤就是预处理阶段 这一阶段就是宏发挥作用的阶段 C 预处理器在源代码编译之前对其进行一些文本性质的操作 主要任务包括删除注释 插入被 include 进来的文件内容 定义和替换由 define 定义的符号以及确定代码部分内容是否根据条件编译 if 来进行编译 文本性质 的操作 就是指一段文本替换成另外一段文本 而不考虑其中任何的语义内容 宏仅仅是在 C 预


一.预处理

二.宏定义用法

①宏常量

#include"stdio.h" #define PI 3.14 #define STR "圆周率约等于" int main() { 
     printf("%s %f",STR,PI); //预处理时会被替换为 printf("%s %f","圆周率约等于",3.14); return 0; } 

②宏语句

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

③宏函数

#include"stdio.h" #define Print(str) printf("%s",str) int main() { 
      Print("这是一个只有一条语句的宏函数!"); //预处理时会被替换为 printf("%s","这是一个只有一条语句的宏函数!") return 0; } 

在这里插入图片描述

④其它

1.#undef 是用来撤销宏定义的,用法如下:

#define PI 3.// code #undef PI //下面开始 PI 就失效了 

2.使用ifndef防止头文件被重复包含和编译

  这是宏定义的一种,它可以根据是否已经定义了一个变量来进行分支选择,一般用于调试等等.实际上确切的说这应该是预处理功能中三种(宏定义,文件包含和条件编译)中的一种—-条件编译。 C语言在对程序进行编译时,会先根据预处理命令进行“预处理”。C语言编译系统包括预处理,编译和链接等部分。

#ifndef x //先测试x是否被宏定义过 #define x //如果没有宏定义下面就宏定义x并编译下面的语句 ... ... ... #endif //如果已经定义了则编译#endif后面的语句 

所以还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

  #ifndef <标识>   #define <标识>   ......   #endif 

<标识>
在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

   #ifndef _STDIO_H_   #define _STDIO_H_   ...... #endif 

三.宏定义相关作用符

①换行符 “\”

#include"stdio.h" #define Print printf("这是第1条语句\n");\ printf("这是第2条语句\n");\ printf("这是第3条语句\n") #define Show(str1,str2,str3)\ { 
        \ printf("%s\n",str1);\ printf("%s\n",str2);\ printf("%s\n",str3);\  } int main() { 
       Print; //无参数宏函数 Show("first","second","third"); //带参数宏函数 return 0; } 

②字符串化符 “#”

#include"stdio.h" #define Print(str)\ { 
        \ printf(#str"的值是%d",str);\  } int main() { 
       int x=3,y=4; Print(x+y); //此处等价于printf("x+y""的值是%d",x+y); //#str等价于"x+y",所以#str不需要再用双引号引起来  return 0; } 

③片段连接符””

#include"stdio.h" #define Add(n,value)\ { 
         \ numn+=value;\ }  int main() { 
        int num1=1; int num2=10; Add(2,10); //等价于num2+=10; 这里把num和2连接成了num2  printf(" num1=%d\n num2=%d",num1,num2); return 0; } 

四.宏函数的巧用

①类型传递

#define Malloc(type,size) (type*)malloc(sizeof(type)*size) 

这个时候,我们只有把类型,容量作为参数传递进行,就可以开辟各种类型的内存了

int *p=Malloc(int,100); //开辟int类型的内存 char *q=Malloc(char,100); //开辟字符类型的内存 

②传递数组

#include"stdio.h" #define InsertSort(list)\ { 
          \ int s=sizeof(list)/4;\ int i,j;\ for(i=2;i<=s;i++)\ { 
          \ list[0]=list[i];\ for(j=i-1;list[j]>list[0];j--)\ list[j+1]=list[j];\  list[j+1]=list[0];\ }\ } int main() { 
         int num[]={ 
        0,2,5,7,3,1,8,0,8,22,57,56,74,18,99,34,31,55,41,12,9,4}; InsertSort(num); for(int i=1;i<sizeof(num)/4;i++) printf("%d ",num[i]); return 0; } 

五.注意事项

① 运算符优先级问题

#define MULTIPLY(x, y) x * y 

  这是一个很简单的乘法函数,当计算MULTIPLY(10, 10),结果是100,这个大家都知道,但是当你计算MULTIPLY(5+5, 10)时,你以为结果还是100吗?当然不是,MULTIPLY(5+5, 10)=5+5*10=55,所以结果是55,所以我们写宏函数时要特别注意运算符的优先级,这里稳妥一点的写法应该这样写

#define MULTIPLY(x, y) ((x)*(y)) 

②宏参数重复调用

#define MAX(a,b) ((a)>(b)?(a):(b)) int a=0; int b =1; int c =MAX(++a,++b); 

这里很多人都以为是c=MAX(1,2)=2;而实际上上面代码等价于

int c =((++a)>(++b)?(++a):(++b)); 

可以看到实际上a b都各自加了两次,所以c=1>2?2:3=3,所以结果是3

③分号吞噬问题

#include"stdio.h" #define FUN(n)\ { 
          \ while(n>0)\ { 
          \ if(n==3)\ break;\  }\ } int main() { 
         int num=10; if(num>0) FUN(num); else num=-num; return 0; } 
#define FUN(n)\  do\ { 
        \ while(n>0)\ { 
        \ if(n==3)\ break;\ }\ }while(0) 

④递归调用问题

#define NUM (4 + NUM) 

  按前面的理解,(4 + NUM)会展开成(4 + (4 + NUM)),然后一直展开下去,直至内存耗尽。但是,预处理器采取的策略是只展开一次。也就是说,NUM只会展开成(4 + NUM),而展开之后NUM的含义就要根据上下文来确定了。

⑤宏参数预处理

  宏参数中若包含另外的宏,那么宏参数在被代入到宏体之前会做一次完全的展开,除非宏体中含有#或。

有如下宏定义:

#define A(y) X_y #define B(y) A(y) #define SIZE 1024 #define S SIZE 










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

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

(0)
上一篇 2026年3月20日 上午10:32
下一篇 2026年3月20日 上午10:32


相关推荐

  • Nginx简单防御CC攻击的两种方法

    Nginx简单防御CC攻击的两种方法CC 攻击可以归为 DDoS 攻击的一种 他们之间都原理都是一样的 即发送大量的请求数据来导致服务器拒绝服务 是一种连接攻击 CC 攻击又可分为代理 CC 攻击 和肉鸡 CC 攻击 代理 CC 攻击是黑客借助代理服务器生成指向受害主机的合法网页请求 实现 DOS 和伪装就叫 cc ChallengeCol 而肉鸡 CC 攻击是黑客使用 CC 攻击软件 控制大量肉鸡 发动攻击 相比来后者比前者更难防御 因为肉鸡可以

    2026年1月22日
    6
  • PyCharm闪退及解决办法

    PyCharm闪退及解决办法很久没用 pycharm 了 昨天本来想用一下来着 发现用一会儿居然闪退 最开始没有在意 用着用着发现是周期性的闪退 今天再打开软件 仔细看了报错信息 YourPyCharme Yoursessionw 原来是注册码过期了 于是在网上找了一个新的注册码 这个注册码能撑到 2020 年 06 月 如

    2026年3月27日
    1
  • 手机怎样用百度网盘下载网上的资源_百度网盘资源如何下载

    手机怎样用百度网盘下载网上的资源_百度网盘资源如何下载2019独角兽企业重金招聘Python工程师标准>>>…

    2022年8月10日
    10
  • 在ubuntu20.04中安装clang和make_uos怎么安装软件

    在ubuntu20.04中安装clang和make_uos怎么安装软件申明:由于项目需要用到ros环境,所以在此记录一下ubuntu20.04下的ROSNoetic安装过程,全程顺序执行一次性安装成功,当然执行下一步的时候上一步必须执行成功,在网络不好的时候可以多尝试几次,以下是我亲自实践的过程,现在分享出来与大家一起交流学习,这个过程全部参考官方安装步骤,此处给出官方链接http://wiki.ros.org/noetic/Installation/Ubuntu。系统要求:Ubuntu20.04ROS安装版本:Noetic安装步骤:1、添加source

    2025年10月18日
    3
  • Hadoop排序工具用法小结

    Hadoop排序工具用法小结

    2021年6月16日
    122
  • win10 pycharm无法打开 双击无反应

    win10 pycharm无法打开 双击无反应pycharm 打不开 重装无效 netshwinsock 重置一下网络状态一个命令解决 怀疑是前两天做美赛安装 latex 导致系统环境出现问题 查这个问题的人还挺多的 更新一下 还有可能是电脑配置比较低 pycharm 在初始化中 如果进程中能看到的话

    2026年3月27日
    3

发表回复

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

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