C语言中的宏定义

2023-11-07

1. 简单宏定义

简单的宏定义有如下格式:

[#define指令(简单的宏)]  #define  标识符替换列表

替换列表是一系列的C语言记号,包括标识符、关键字、数、字符常量、字符串字面量、运算符和标点符号。当预处理器遇到一个宏定义时,会做一个 “标识符”代表“替换列表”的记录。在文件后面的内容中,不管标识符在任何位置出现,预处理器都会用替换列表代替它。

不要在宏定义中放置任何额外的符号,否则它们会被作为替换列表的一部分。一种常见的错误是在宏定义中使用 = :

#define N = 100       /*** WRONG ***/
int a[N];            /* 会成为 int a[= 100]; */

在上面的例子中,我们(错误地)把N定义成一对记号(= 和100)。

在宏定义的末尾使用分号结尾是另一个常见错误:

#define N 100;       /*** WRONG ***/
int a[N];            /*    become int a[100;]; */

这里N被定义为100和;两个记号。

在一个宏定义中,编译器可以检测到绝大多数由多余符号所导致的错误。但不幸的是,编译器会将每一处使用这个宏的地方标为错误,而不会直接找到错误的根源——宏定义本身,因为宏定义已经被预处理器删除了。

简单的宏主要用来定义那些被Kernighan和Ritchie称为“明示常量”(manifest constant)的东西。使用宏,我们可以给数值、字符和字符串命名。

#define STE_LEN 80

#defineTRUE     1

#defineFALSE    0

#definePI        3.14159

#defineCR        '\r'

#defineEOS       '\0'

使用#define来为常量命名有许多显著的优点:

1) 、 程序会更易读。一个认真选择的名字可以帮助读者理解常量的意义。否则,程序将包含大量的“魔法数”,使读者难以理解。

2) 、 程序会更易于修改。我们仅需要改变一个宏定义,就可以改变整个程序中出现的所有该常量的值。“硬编码的”常量会更难于修改,特别是有时候当他们以稍微不同的形式出现时。(例如,如果一个程序包含一个长度为100的数组,它可能会包含一个从0到99的循环。如果我们只是试图找到所有程序中出现的100,那么就会漏掉99。)

3) 、可以帮助避免前后不一致或键盘输入错误。假如数值常量3.14159在程序中大量出现,它可能会被意外地写成3.1416或3.14195。

虽然简单的宏常用于定义常量名,但是它们还有其他应用。

4) 、可以对C语法做小的修改。实际上,我们可以通过定义宏的方式给C语言符号添加别名,从而改变C语言的语法。例如,对于习惯使用Pascal的begin和end(而不是C语言的{和})的程序员,可以定义下面的宏:

#define BEGIN  {

#define END    }

我们甚至可以发明自己的语言。例如,我们可以创建一个LOOP“语句”,来实现一个无限循环:

#define LOOP   for (;;)

当然,改变C语言的语法通常不是个好主意,因为它会使程序很难被其他程序员所理解。

5) 、对类型重命名。在5.2节中,我们通过重命名int创建了一个Boolean类型:

#define BOOL int

虽然有些程序员会使用宏定义的方式来实现此目的,但类型定义(7.6节)仍然是定义新类型的最佳方法。

6) 、控制条件编译。如将在14.4节中看到的那样,宏在控制条件编译中起重要的作用。例如,在程序中出现的宏定义可能表明需要将程序在“调试模式”下进行编译,来使用额外的语句输出调试信息:

#define DEBUG

这里顺便提一下,如上面的例子所示,宏定义中的替换列表为空是合法的。

当宏作为常量使用时,C程序员习惯在名字中只使用大写字母。但是并没有如何将用于其他目的的宏大写的统一做法。由于宏(特别是带参数的宏)可能是程序中错误的来源,所以一些程序员更喜欢使用大写字母来引起注意。其他人则倾向于小写,即按照Kernighan和Ritchie编写的The C Programming Language一书中的样式。

2. 带参数的宏

带参数的宏定义有如下格式:

[#define指令—带参数的宏]  #define 标识符(x1, x2,…,xn)替换列表

其中x1, x2,…,xn是标识符(宏的参数)。这些参数可以在替换列表中根据需要出现任意次。

在宏的名字和左括号之间必须没有空格。如果有空格,预处理器会认为是在定义一个简单的宏,其中(x1,x2,…,xn)是替换列表的一部分。

当预处理器遇到一个带参数的宏,会将定义存储起来以便后面使用。在后面的程序中,如果任何地方出现了标识符(y1,y2,…,yn)格式的宏调用(其中y1,y2,…,yn是一系列标记),预处理器会使用替换列表替代,并使用y1替换x1y2替换x2,依此类推。

例如,假定我们定义了如下的宏:

#define MAX(x,y)    ((x)>(y) ? (x) :(y))

#define IS_EVEN(n)   ((n)%2==0)

现在如果后面的程序中有如下语句:

i = MAX(j+k, m-n);

if (IS_EVEN(i)) i++;

预处理器会将这些行替换为

i = ((j+k)>(m-n)?(j+k):(m-n));
if (((i)%2==0)) i++;

如这个例子所显示的,带参数的宏经常用来作为一些简单的函数使用。MAX类似一个从两个值中选取较大的值的函数。IS_EVEN则类似于另一种函数,该函数当参数为偶数时返回1,否则返回0。

下面的例子是一个更复杂的宏:

#define TOUPPER(c)('a'<=(c)&&(c)<='z'?(c)-'a'+'A':(c))

这个宏检测一个字符c是否在'a'与'z'之间。如果在的话,这个宏会用'c'减去'a'再加上

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言中的宏定义 的相关文章

  • 未捕获的异常“Google_IO_Exception”,消息为“HTTP 错误:无法连接”

    我有一个任务 查询 运行一些从 gmail 邮箱检索数据的 php 代码 直到上周五 2015 年 4 月 10 日 它一直工作正常 现在我收到以下错误日志 E 11 58 26 094 2015 04 15 200 3 38 KB 14
  • 使用PHP套接字发送和接收数据

    我正在尝试通过 PHP 套接字发送和接收数据 一切正常 但是当我尝试发送数据时 PHP 不发送任何内容 Wireshark 告诉我发送的数据长度为 0 我正在使用这段代码
  • 将 MySQL 结果作为 PHP 数组

    mysql 表 config name config value allow autologin 1 allow md5 0 当前的 php 代码 sth mysql query SELECT rows array while r mysq
  • 如何在html中制作多行类型的文本框?

  • PHP文件上传

    如果我想在文件名转到服务器的永久位置 而不是临时位置 之前更改文件名 我该如何执行此操作 代码如下
  • 为什么 PHP 中不允许“传统”类型提示?

    刚刚发现类型提示 http php net manual en language oop5 typehinting phpPHP 中允许 但不适用于整数 字符串 布尔值或浮点数 为什么 PHP 不允许对整数 字符串等类型进行类型提示 从 P
  • PHP cURL 在本地工作,在 AWS 服务器上出现错误 77

    最新更新 脚本作为管理员用户通过 SSH shell 作为 php script php 成功运行 当由 nginx 用户运行时 curl 命令无法执行 https 请求 所以我猜测这是nginx用户无法正确使用curl的问题 我已经检查了
  • 在 PHP 中模拟 jQuery.ajax 请求

    我必须在 PHP 中模拟 AJAX 请求 就像在 jQuery 中一样 我当前的代码在这里 原始 AJAX 调用 不得修改 ajax type POST url someFile php data data success function
  • 如何确定当前使用哪个网格选项

    我将 Bootstrap 3 用于使用 PHP 和 HTML 创建的网页 随着响应式网格和类的开启引导程序3您可以将多个类分配给一个 div 以根据当前屏幕尺寸定义不同的宽度 例如 div class col lg 3 col md 3 c
  • 如何将行变成列?

    我有一个数据库 其中存储分组到项目中的关键字以及与每个关键字相关的数据 然后我显示每个项目的数据网格 每个关键字一行和几列 全部从同一个表 数据 中检索 我有 4 个表 关键字 项目 group keywords 和数据 keywords
  • 尝试获取 Google accessToken

    看起来 无论我做什么 谷歌都在竭尽全力阻止我完成这个研究项目 我的项目让我使用 Google 电子表格作为数据库 并使用所述电子表格中的数据执行程序化的 Google 图片搜索 并向最终用户显示一些结果 设置说明 我开始按照此处的说明进行操
  • PHP使用auto_increment生成短唯一ID?

    我想生成一个简短的 唯一的 ID 而不必检查冲突 我目前正在做类似的事情 但是我当前生成的 ID 是随机的 并且在循环中检查冲突很烦人 并且如果记录数量显着增加 将会变得昂贵 通常担心冲突不是问题 但我想要生成的唯一 ID 是一个由 5 8
  • Doctrine 1 和 Symfony 1 的多个主键?

    我已经知道在 Symfony 1 和 Doctrine 1 中不可能使用多个主键 但是你们知道有什么好的解决方法吗 除了多对多关系之外 原则 1 不适用于多列上的主键 但如果你想使用多对多关系 请像这样使用 BlogPost columns
  • 模拟/存根在 PHPUnit 中实现 arrayaccess 的类的对象

    这是我正在为其编写测试套件的类的构造函数 它扩展了 mysqli function construct Config c store config file this gt config c do mysqli constructor pa
  • 删除 woocommerce 店面主页标题 php

    我正在使用 woocommerce 的店面主题 我需要用 php 删除主页标题 h1 我知道 css 解决方案 但我不想使用它 因为我想将 h1 添加到该页面的其他位置 并且在一个页面中包含 2 个 h1 对 seo 不利页 我也知道删除页
  • 如何解决 Laravel 8 UI 分页问题?

    我在尝试最近发布的 laravel 8 时遇到了问题 我试图找出变化是什么以及它是如何工作的 当我这样做时 我遇到了分页 laravel 8 UI 变得混乱的问题 不知何故它发生了 有人可以帮助我吗 或者经历过同样的事情 像这样我在 lar
  • 简单的dom php解析获取自定义数据属性值

    HTML div class something ddsf PHP foreach dom gt find something data rel as this var dump this gt attr 我尝试了这个但错误 在其文档中找不
  • 如何确保在 PHP 的“foreach”循环中重置该值?

    我正在写一个简单的 PHP 页面和一些foreach使用了循环 以下是脚本 arrs array a b c foreach arrs as arr if substr arr 0 1 b echo This is b End of fir
  • 接口中的构造方法

    接口中的构造方法不好吗 为什么人们认为有人想要实例化接口 我们想要做的是强制实现者实现构造函数 就像其他接口方法一样 接口就像一个合同 假设我有一个接口 Queue 并且我想确保实现者创建一个带有一个参数的构造函数 该构造函数创建一个单例队
  • 谷歌日历手表过期时间超过1个月怎么办?

    我将我的 CRM 系统与 Google 日历同步 为此 我要求push notifications从我的用户 Google 日历到我的系统 我已经成功创建了手表 并将过期时间设置为2030年 但是当我收到手表事件的响应时 它显示手表的过期时

随机推荐

  • 电脑阅卷系统

    本软件利用电脑外接摄像头 和用普通纸张打印 或复印 的答题卡进行选择题的阅卷 能实时播报成绩产生作答分析 软件名称是 精易摄像头阅卷软件 功能特色 1 精易软件的设计精度和速度已达到实际使用需要 填涂到位的情况下读卡速度是每张答题卡用时1
  • 决策树应用实例③——银行借贷模型

    决策树系列目录 文末有惊喜彩蛋 决策树 信息熵 信息增益 基尼系数 决策树 决策树算法原理 ID3 C4 5 CART 决策树 决策树参数介绍 分类和回归 决策树 决策树Sklearn调参 GridSearchCV调参及过程做图 决策树 P
  • NoSQL数据库简介

    NoSQL代表 不仅是SQL 指的是一种数据库管理系统 旨在处理大量非结构化和半结构化数据 与使用具有预定义架构的表格格式的传统SQL数据库不同 NoSQL数据库是无模式的 并且允许灵活和动态的数据结构 NoSQL数据库是必需的 因为它们可
  • 解决:Not creating XLA devices, tf_xla_enable_xla_devices not set

    解决 Not creating XLA devices tf xla enable xla devices not set 实验环境 提示如下 分析原因 解决方法 实验环境 Windows 10 NVIDIA GeForce GTX 105
  • 易经中的一些见解

    曾仕强教授 易经不只是用来趋吉避凶 低端讲法 高端讲法 持正向善 云端讲法 心安理得 求得好死 好死指的是死得其时 死得其所 死得心安理得 趋吉避凶是手段 不是目的 顺自然 重人伦 自作自受 缺角 修治 完人 慎始 反省提升 善终 人生的乐
  • InvokeHelper调用引发异常

    代码原来的实现是 try InvokeHelper catch GetLastError 好吧 引发了异常 但是GetLastError 永远为零 状况了 网上又找不到相关资料 知道自己一步一步地从InvokeHelper跟踪进去 发现里面
  • Spring Cloud OpenFeign 超时设置与开启重试

    超时设置 数据中台HRestful API请求 feign okhttp enabled true client config default 日志打印级别 loggerLevel basic 跨服务接口请求超时 readTimeout 2
  • Windows操作系统截屏快捷键

    1 Print Screen截屏 不只是win10系统独有的 只要在键盘上按下 Print Screen 键 就会截取当前屏幕并储存在剪切板中 进入文档编辑器 文本文档除外 图片处理工具 QQ等聊天窗口进行粘贴 Ctrl V 操作 就可以获
  • os.path函数简要分析

    os模块简介 os模块实现了在路径上的一些有用的功能 os path abspath path 返回一个绝对路径名 import os path abspath os path abspath User home Work print ab
  • 静态代码扫描环境搭建(mac)

    一 安装要求 1 1 软件要求 在进行sonarqube环境安装和搭建前务必确定当前机器和平台配置满足如下要求 机器上需要安装java Oracle JRE 11 或 OpenJDK 11 SonarQube服务器需要的java版本为11
  • 数据分析-数据清洗与整理

    1 数据清洗 第一步 对异常值进行处理 首先 查看原数据库是否一样 然后 查询是否信息录入时出现错误 最后 看看是不是顾客随意填写的信息 第二步 对离群值进行处理 首先 查询是否与原数据库一致 然后 查询是否信息录入错误 最后 判断是否符合
  • Selenium成长之路-18多窗口切换

    在实际测试过程中 打开多窗口是进行测试是很正常的事情 那么在自动化测试中 也需要开启多窗口来进行测试 我们来分析一下 打开多窗口测试的思路 1 打开一个目标网页 2 再次打开新的网页 3 获得所有窗口的 4 循环判断窗口是否为当前窗口 5
  • 2024最强秋招八股文(精简、纯手打)

    7 28日已更新 错误已修改 有错误的地方 欢迎大家留言 目录 一 Java基础篇 1 接口和抽象类的区别 2 重载和重写的区别 3 和equals的区别 4 异常处理机制 5 HashMap原理 6 想要线程安全的HashMap怎么办 7
  • 让idea自动生成类关系图

    学习了解一些开源的工具源码 有时需要了解到程序入口及项目类之间的关系 Idea工具提供了这个功能 以Jmeter5 1 1源码为例 看下RemoteJMeterEngineImpl类的关系图 操作方法 1 定位到RemoteJMeterEn
  • 窗体的扩展样式GWL_EXSTYLE: 用于SetWindowLong

    SetWindowLong Handle GWL EXSTYLE GetWindowLong Handle GWL EXSTYLE or WS EX TRANSPARENT or WS EX LAYERED WS EX ACCEPTFILE
  • 若依框架主子表数据导出问题

    一 使用若依框架导出主子表数据因为返回的数据中含有子表的集合信息 导致excel表格中多出一行标题 二 在Controller层写入导出的方法 三 这边返回的数据是主表的数据 主表数据的实体类中含有子表的集合信息 四 如果不想要子表信息就把
  • 车载无线控制服务器,车载无线视频监控系统应用整体解决方案

    车载视频监控系统整体描述 前言 现如今社会存在一些不良分子扰乱社会治安 盗窃 抢劫 斗殴 民事纠纷 面对这些突发现象 在公安执法 治安巡逻的过程中 很多时候都要随时把过程记录下来 作为记录 取证 证明等各种用途 这时候车载无线视频监控系统起
  • Passing the Message HDU - 3410(单调栈模板题,简单应用)

    题意 现在有n个人站成一行 告诉你每个人的身高 现在每个人都要找到在他左边 比他矮的人中最高的人的位置 同时也要找到 在他右边比他矮的人中最高的人的位置 注意由于他们是站成一行的 所以他们不能越过比他们高的人去看后面的人 也就是说 他只能看
  • IDEA设置忽略idea文件和iml文件

    1 File gt Settings 2 Editor gt File Types 3 红框那里填上 iml idea
  • C语言中的宏定义

    1 简单宏定义 简单的宏定义有如下格式 define指令 简单的宏 define 标识符替换列表 替换列表是一系列的C语言记号 包括标识符 关键字 数 字符常量 字符串字面量 运算符和标点符号 当预处理器遇到一个宏定义时 会做一个 标识符