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

目录
  • 前言
  • #define 定义宏(无参)
  • #define 定义宏函数
  • 宏的更多规则特性
  • 宏的缺点
  • 常见预处理指令

前言

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

(0)

相关推荐

  • 浅谈关于C语言中#define的副作用

    MFC虽然没有未来,但是我觉得MFC的思想还是有必要研究研究的,在MFC中或者一些底层代码的编写中,宏是相当好用的,为什么呢?因为宏只是简单的替换,不进行类型转换,替换就意味着灵活,而C语言编程的灵魂就是灵活啊. 但是在高级语言中,甚至C++中,是提倡用const的,不提倡用#define,因为#define有一定的副作用,玩不好就没命了. 这里我们讨论下#define的副作用. # include <stdio.h> # include <stdlib.h> # define C

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

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

  • C语言中#define定义的标识符和宏实例代码

    目录 1.#define定义标识符 语法 举个栗子 2.#define定义宏 #define替换的规则 #与###的用法: 宏的缺点 宏和函数的优缺点 总结 1.#define定义标识符 在C语言程序中,有时候会包含#define #define可以定义标识符 也就是说可以对字符重新定义,实现代替的作用 语法 #define  name  stuff 就比如说: #define MAX 1000(用MAX代替1000) #define reg   register (用reg代替register

  • C语言中#define预处理语法总结

    目录 一.使用#define定义标识符常量 语法1: 语法2: 二.#define来定义带有参数的宏 三.C语言给我们定义好的一些标识符常量 一.使用#define定义标识符常量 语法1: #define MAX 100 注意使用#define末尾不需要带; MAX是一个常量,是使用#define定义的一个标识符常量 !!! 我为什么要在这里强调这是一个常量呢?因为它和普通常量一样不可被修改 大家可能会疑惑使用const修饰的变量不也是不可被修改的吗,这两者有什么不同呢? 这里要强调一下,使用c

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

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

  • C语言入门篇--定义宏#define的概述

    目录 1.什么是宏 2.为什么要有宏? 3.宏的用法 3.1定义宏 3.2宏常量 3.3"宏函数" 1.什么是宏 宏只做简单的文本替换,但一般在作为变量名出现或者在字符串中出现中是不会被替换的. 2.为什么要有宏? (1)便于代码的可维护性,对宏的内容进行修改,即可修改代码中所有用到此宏地方的内容. (2)方便阅读,见名知意. 3.宏的用法 3.1定义宏 格式: #define 标识符 内容 3.2宏常量 #include <stdio.h> #define M 1 int

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

    目录 前言 #define 定义宏(无参) #define 定义宏函数 宏的更多规则特性 宏的缺点 常见预处理指令 前言 C语言中源代码到可执行文件的第一阶段,也就是预处理阶段,会检查源文件中的预处理指令语句和宏定义,并对源代码进行相应的替换,预处理过程还会删除程序中的注释和多余的空白符号. 预处理指令是以#开头的代码行,#必须是该行除了空白符外的第一个字符,#后是指令关键字,在#和指令关键字之间允许存在若干个空白字符,define是宏定义命令.在C语言程序中允许用一个标识符来表示一个字符串,称

  • C语言预编译#define(预处理)

    目录 一.预定义符号 二.#define 定义标识符 三.#define 定义宏 四.#define 替换规则: 五.#和## 两个符号(少见) 六.宏和函数的对比 七.#undef 一.预定义符号 预定义符号是系统本身定义的: FILE 进行编译的源文件的位置 LINE 文件当前的行号 DATE 文件被编译的日期 TIME 文件被编译的时间 STDC 如果编译器遵循 ASNSI C,其值为1,否者未定义 二.#define 定义标识符 语法:#define name stuff (用stuff

  • C语言超详细讲解宏与指针的使用

    目录 1.关于define 2.初识指针 (1)内存 (2)示例 (3)指针的使用示例 (4)指针变量的大小 1.关于define define是一个预处理指令,有两种用法,一种是用define定义常量:另外一种是define定义宏. 下面的例子为利用define定义常量 #define _CRT_SECURE_NO_WARNINGS #define MAX 1000 #include <stdio.h> int main() { printf("%d\n",MAX); r

  • 常用C/C++预处理指令详解

    预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查.预处理命令以符号"#"开头. 常用的预处理指令包括: 宏定义:#define 文件包含:#include 条件编译:#if.#elif.#ifndef.#ifdef.#endif.#undef 错误信息指令:#error #line指令 布局控制:#pragma 宏定义 宏定义又称为宏代换.宏替换,简称"宏".宏替换只作替换,不做计算,不做表达式求解.宏定义分带参数的宏定义和不带参数的宏

  • 关于C语言 const 和 define 区别

    目录 一.const 使用 1.const 修饰变量 2.const 修饰指针 3.const 修饰在函数名前面当 4.const 修饰在函数名后面 5.const 修饰函数参数 二.define 使用 1.define 定义常量 2.define 定义函数 3.define 定义多行函数 4.define 防止头文件重复包含 三.const 和 define 区别 四.const 优点 一.const 使用 const 是 constant 的缩写,"恒定不变"的意思.被 const

  • C语言程序环境和预处理详解分析

    目录 一.程序的翻译环境和运行环境 程序的翻译环境 链接阶段 执行环境(运行环境) 二.预处理详解 预定义符号 #define定义标识符 #define定义宏 #define 替换规则 #和##两个预处理的工具 带副作用的宏参数 宏和函数对比 #undef移除宏 命令行定义 条件编译 头文件包含 嵌套文件包含 总结 一.程序的翻译环境和运行环境 重点:任何ANSI C(标准C的程序)的一种实现,存在两个不同的环境 第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令. 第2种是执行环境,

  • C语言超详细解析函数栈帧

    目录 一.前面 二.预备知识 三.栈帧创建与销毁 四.总结 一.前面 本章将以汇编视角看函数栈帧的内存是如何使用与回收的,为了降低汇编语言的理解成本,以图示的方式讲解每一步汇编指令所带来的效果,来逐步展示函数栈帧的形成与销毁的整个过程. 展示环境:win10 && vs2019 二.预备知识 这些预备知识理解与否对本篇文章并无很大关系,之所以预备这些知识是为了让读者能够更加相信函数栈帧的形成与销毁过程就是如此. 栈区:内存四区之一,内存为了使用和管理,被划分为四部分,其中栈区就是内存被划分

  • c#预处理指令分析

    预处理指令 这些指令/命令不会转换为可执行代码,但会影响编译过程的各个方面:列如,可以让编译器不编译某一部分代码等. C#中主要的预处理指令 #define和#undef #define指令定义: #define DEBUG 它告诉编译器存在DEBUG这个符号:这个符号不是实际代码的一部分,而只是在编译器编译代码时候可能会根据这个符号做条件编译. #undef定义: #undef DEBUG 用来移除定义的符号DEBUG.如果不存在这样的标记,#undef指令则不会生效.同样,用#define再

  • .net 预处理指令符的使用详解

    什么是预处理指令符? 当C#编译器找到一条预处理指令#if,最后找到一条指令时,#endif仅在定义了指定符号的情况下,编译器才会在这些指令之间编译代码.与C和C ++不同,您不能将数字值分配给符号.#if C#中的语句为布尔型,仅测试符号是否已定义. 预处理指令符的使用 #if:打开条件编译,仅在定义了指定符号的情况下才编译代码. #elif:根据是否定义了指定的符号,关闭前面的条件编译并打开新的条件编译. #else:如果未定义先前指定的符号,则关闭之前的条件编译并打开新的条件编译. #en

随机推荐