广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言超全面define预处理指令的使用说明
  • 565
分享到

C语言超全面define预处理指令的使用说明

2024-04-02 19:04:59 565人浏览 独家记忆
摘要

目录前言#define 定义宏(无参)#define 定义宏函数宏的更多规则特性宏的缺点常见预处理指令前言 C语言中源代码到可执行文件的第一阶段,也就是预处理阶段,会检查源文件中的预

前言

C语言中源代码到可执行文件的第一阶段,也就是预处理阶段,会检查源文件中的预处理指令语句和宏定义,并对源代码进行相应的替换,预处理过程还会删除程序中的注释和多余的空白符号。

预处理指令是以#开头的代码行,#必须是该行除了空白符外的第一个字符,#后是指令关键字,在#和指令关键字之间允许存在若干个空白字符,define是宏定义命令。在C语言程序中允许用一个标识符来表示一个字符串,称为“宏”,“宏”又分为有参和无参,有参又称为“宏函数”,被定义为“宏”的标识符称为“宏名”。

#define 定义宏(无参)

语法规定:

#define name stuff
name:标识符名\宏名
stuff:可以是关键字、常量、关键字、标识符、标点符号、运算符,表达式

在预处理阶段,编译器会在程序中使用#define定义的标识符替换成stuff,可以通过预处理生成的.i文件查看效果。

//stuff是数值常量
#define NUM 10

//stuff是关键字
#define reg reGISter

//stuff是标点符号
#define GREATER_THAN >

//stuff的更多表达方式
#define do_forever for(;;)
//若定义的stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个\(续行符)
#define DBBUG_PRINT printf("file:%s\tline:%d\t \
                    date:%s\ttime:%s\n",\
                    __FILE__,__LINE__,\
                    __DATE__,__TIME__)

总结:#define定义的name(宏名),在预编译阶段会将所有的宏名替换成stuff,stuff内容被替换到源代码中。称为“宏代换”或“宏展开”。

注意:define定义的标识符的时候,后面加上“;”会将“;”认为是stuff中的内容。

#define 定义宏函数

宏函数的申明方式:#define name(parament-list) stuff
parament-list:参数列表

 注意:参数列表的左括号必须与name紧邻,如果两者之间有空白存在,参数列表就会被解释为stuff的部分。

宏函数存在的问题1

#include <stdio.h>
#define SQUARE(x) x*x//定义一个宏函数求平方
int main()
{
    int x = SQUARE(3+1);//替换后x的计算结果是多少?答案是:7
 
}

 为什么呢?

在给宏函数传参时,如果传递的是一个表达式,不会先计算表达式的结果再进行传参,而是直接将表达式整体作为参数传递。

那么如何防止发生这样的情况呢?+()

 宏函数存在的问题2

#include <stdio.h>
#define SUM(x,y) (x)+(y)
int main()
{
    int a = 10;
    int b = 5;
    int c = SUM(a,b)*2;//替换后c的结果为20,why
    return 0;
}

我们看看替换后的结果

 这又该如何解决呢?

 总结:在对数值表达式进行求值的宏定义应该用这两种方式加上括号,避免在使用宏参数的操作符或邻近操作符之间不可预料的相互作用。 

 #define替换规则:

1.在使用宏函数时,首先对参数进行检查,看看参数中是否包含任何#define定义的标识符,如果有,他们首先被替换。

2.替换的内容被插入到源文件原来的位置。对于宏函数,参数名被他们的值替换

宏的更多规则特性

1.宏名一般用大写

2.使用宏可提高程序的通用性和易读性,便于修改。

3.宏定义末尾不加分号

4.宏定义写在函数的大括号外面,作用域为其后的程序,通常放在开头

5.宏函数不可递归

6.宏定义不分配内存,变量定义分配内存

7.字符串" "中永远不包含宏

8.宏定义不存在类型问题,他的参数也没有类型

宏的缺点

1.宏不能调试

2.宏由于与类型无关,不够严谨

3.宏可能带来运算符优先级的问题,导致容易出错

常见预处理指令

#define:宏定义

#undef:撤销已经定义过的宏名

#include:将另一个源文件嵌入到#include源文件中

#if~#endif:如果#if后面的常量表达式为真,则编译#if~#endif之间的代码,如果为假,跳过这些代码不编译。

#if~#elif~#else~#endif:和if~else if~else类似,可以建立更分支。

#ifdef symbol~endif:判断是否被定义,定义了编译他们之间内容

#ifndef symbol~endif:判断是否被定义,没定义编译他们之间的内容

#line:改变当前行数和文件名称,是在编译程序中预先定义的标识符命令的基本形式:#line number["filename"]

#error:编译程序时,只要遇到#error就会生成一个编译错误的提示信息,并停止编译。

#pragma: 可以设定编译程序完成一些特点的动作(可以通过编译程序的菜单中设置),可以向编译程序传送各种指令。

到此这篇关于C语言超全面define预处理指令的使用说明的文章就介绍到这了,更多相关C语言define内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言超全面define预处理指令的使用说明

本文链接: https://www.lsjlt.com/news/146910.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言超全面define预处理指令的使用说明
    目录前言#define 定义宏(无参)#define 定义宏函数宏的更多规则特性宏的缺点常见预处理指令前言 C语言中源代码到可执行文件的第一阶段,也就是预处理阶段,会检查源文件中的预...
    99+
    2022-11-13
  • C语言中的预处理命令怎么使用
    这篇“C语言中的预处理命令怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言中的预处理命令怎么使用”文章吧。一、预...
    99+
    2023-07-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作