C语言编译和编译预处理
1.编译预处理
在对一个源程序进行编译时,系统将自动调用预处理程序对源程序中的预处理部分作处理,处理完毕后自动编译源程序
2.宏定义
- 宏:C语言源程序中允许用一个标识符来表示一个字符串
- 宏名:被定义为宏的标识符
- 宏展开:在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串替换
- 宏定义由宏定义命令完成
- 宏展开由预处理程序自动完成
- 宏分为:不带参数的宏和带参数的宏
3.不带参数的宏定义
#define 标识符 字符串
#define PI 3.1415926
“标识符”是为所定义的宏名
“字符串”为宏名将要被替换的字符串,可以是常量字符串、表达式字符串、格式字符串等
宏定义
常量宏定义
//【例9. 1】常量的宏定义。
#include <stdio.h>
#define PI 3.1415926
void main()
{ float r,l,s,v;printf("Input radius: ");scanf("%f",&r);l=2.0*PI*r; //宏展开为 l=2.0*3.1415926*r;s=PI*r*r; //宏展开为 s=3.1415926*r*r;v=4.0/3*PI*r*r*r; //宏展开为 v=4.0/3*3.1415926*r*r*r;printf("l=%.4f\ns=%.4f\nv=%.4f\n",l,s,v);
}
表达式的宏定义
//【例9. 2】表达式的宏定义。
#include <stdio.h>
#define M (y*y+3*y)
void main()
{ int s,y;printf("Input a number: ");scanf("%d",&y);s=3*M+4*M+5*M; //宏展开为 s=3*(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y);printf("s=%d\n",s);
}
函数名和格式字符串的宏定义
//【例9. 3】函数名和格式字符串的宏定义。
#include <stdio.h>
#define P printf
#define F "%4d\t%.2f\n"
void main()
{ int a=3, c=5, e=11;float b=4.6, d=7.9, f=22.08;P(F,a,b); //宏展开为 printf("%4d\t%.2f\n",a,b);P(F,c,d); //宏展开为 printf("%4d\t%.2f\n",c,d);P(F,e,f); //宏展开为 printf("%4d\t%.2f\n",e,f);
}
宏
define PI 3.l4l5926
把数字“1”写成了小写字母“l”
#define PI 3.1415926;
……
area=PI*r*r;
……
宏展开后为: area=3.1415926;*r*r;
(6)在源程序中用双引号引起来的字符串内,与宏名相同的字符不进行替换
//【例9. 4】双引号中与宏名相同的字符不作替换。
#include <stdio.h>
#define PI 3.1415926
void main()
{ printf("PI\n"); //不进行宏展开printf("%f\n",PI); //进行宏展开
}
(8)宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用# undef命令。
//【例9. 5】使用# undef结束宏的作用域。
#include <stdio.h>
#define PI 3.1415926
void main()
{ float r=2,area;area=PI*r*r;
//宏展开为area=3.1415926*r*r; printf("area=%f",area);
}
#undef PI
f1()
{ float r=2,area;area=PI*r*r;
//PI不能被宏展开,此处语法报错,PI没有定义printf("area=%f",area);
}
带参数的宏定义

//【例9. 6】带参数的宏定义。
#include <stdio.h>
#define MAX(a,b) (a>b)?a:b
void main()
{ int x,y,max;printf("Input two numbers:");scanf("%d,%d",&x,&y);max=MAX(x,y); //宏展开为 max=(x>y)?x:y;printf("max=%d\n",max);
}
语句: max=MAX(x,y);
宏展开后为:max=(a,b) (a>b)?a:b(x,y); 是错误的。
(2)宏定义中的形参是标识符,语句中的实参可以是表达式
【例9. 7】语句中的实参为表达式。
#include <stdio.h>
#define SQ(y) (y)*(y)
void main()
{ int a,sq;printf("Input a number: ");scanf("%d",&a);sq=SQ(a+1); //宏展开为 sq=(a+1)*(a+1);printf("sq=%d\n",sq);
}
(3)在宏定义中,形参通常要用括号括起来以避免出错。
宏定义:
#define SQ(y) (y)*(y)
中(y)*(y)表达式的y都用括号括起来,因此结果是正确的
如果去掉括号,定义形式如下:
#define SQ(y) y*y
语句: sq=SQ(a+1);
宏展开后为:sq=a+1*a+1;
按以下形式定义:
#define SQ(y) (y)*(y)
语句:sq=1.0/SQ(a+1);
宏展开后为:
sq=1.0/(a+1)*(a+1); //先算除法,再算乘法
要想先算乘法后算除法,应该在宏定义中的整个字符串外加括号,按如下形式定义:
#define SQ(y) ((y)*(y))
带参数的宏和函数的区别
//【例9. 8】通过宏展开得到若干结果。
#include <stdio.h>
#define SSSV(L,W,H,SA,SB,SC,VV) SA=L*W;SB=L*H;SC=W*H;VV=W*L*H;
void main()
{ int l=3,w=4,h=5,sa,sb,sc,vv;SSSV(l,w,h,sa,sb,sc,vv); //宏展开后为sa=l*w;sb=l*h;sc=w*h;vv=w*l*h;printf("sa=%d\nsb=%d\nsc=%d\nvv=%d\n",sa,sb,sc,vv);
}
调用函数只可得到一个返回值,而宏可以设法得到几个结果。
文件包含
文件包含命令的一般形式为:
#include "文件名"
或
#include <文件名>
//【例9. 9】文件包含命令的使用。
(1)文件file1.c内容如下:
#include <stdio.h>
#include "file2.c"
void main()
{ int a,b,c;printf("Input two numbers: ");scanf("%d,%d",&a,&b);c=max(a,b);printf("max=%d\n",c);
}
//(2)文件file2.c内容如下:
int max(int x,int y)
{ int z;if(x>y) z=x;else z=y;return(z);
}

条件编译
条件编译-形式一
#ifdef 标识符
程序段1
#else
程序段2
#endif
#ifdef 标识符
程序段
#endif
功能是:如果所指定标识符在之前已被 #define命令定义过,则在编译时编译程序段1;否则编译程序段2。
【例9. 10】给定半径r,求圆的面积s。要求设置条件编译:若π值已定义,则直接计算面积;若π值未定义,则定义π值后再计算面积。
#include <stdio.h>void main(){ float r,s;printf("Input radius: ");scanf("%f",&r);#ifdef PI //条件编译s=PI*r*r; //程序段1#else#define PI 3.1415926 //程序段2s=PI*r*r; #endifprintf("s=%f\n",s);}
(1)程序中在条件编译前未定义π值(即PI),所以编译程序段2
(2)若程序开头加入宏定义“#define PI 3.1415926”,则编译程序段1
条件编译-形式二
#ifndef 标识符
程序段1
#else
程序段2
#endif
功能是:如果标识符之前未被#define命令定义过,则对程序段1进行编译,否则对程序段2进行编译
【例9. 11】按形式二修改【例9. 10】的程序。
#include <stdio.h>void main(){ float r,s;printf("Input radius: ");scanf("%f",&r);#ifndef PI //条件编译#define PI 3.1415926 //程序段1s=PI*r*r; #elses=PI*r*r; //程序段2#endifprintf("s=%f\n",s);}
(1)程序中在条件编译前未定义π值(即PI),所以编译程序段1
(2)若在程序的开头加入宏定义“#define PI 3.1415926”,则编译程序段2
条件编译-形式三
#if 表达式
程序段1
#else
程序段2
#endif
功能是:若表达式的值为真(非0),则编译程序段1,否则编译程序段2
【例9. 12】设置条件编译。求圆的面积或正方形的面积。
#include <stdio.h>#define PI 3.1415926#define R 1void main(){ float c,s;printf ("Input a number: ");scanf("%f",&c);#if R //条件编译s=PI*c*c; //程序段1printf("Area of circle is : %f\n",s);#elses=c*c; //程序段2printf("Area of square is : %f\n",s);#endif}
程序宏定义中,定义R为1,因此在条件编译时,表达式R的值为真,故编译程序段1,求圆的面积
说明
#ifdef COMPUTER_A
#define INTEGER_SIZE 16
#else
#define INTEGER_SIZE 32
#endif

相关文章:
C语言编译和编译预处理
1.编译预处理 • 编译是指把高级语言编写的源程序翻译成计算机可识别的二进制程序(目标程序)的过程,它由编译程序完成。 • 编译预处理是指在编译之前所作的处理工作,它由编译预处理程序完成 在对一个源程序进行编译时࿰…...
ahb 总线的一些思考
1. 如何处理对不存在地址的访问? 当主设备试图访问内存映射中不存在的地址时,系统需要处理这一情况以避免错误或未定义行为。通常通过使用默认从设备或错误响应机制来管理。具体如下: 默认从设备:默认从设备响应对未定义或不存在…...
spark shuffle写操作——SortShuffleWriter
写入的简单流程: 1.生成ExternalSorter对象 2.将消息都是插入ExternalSorter对象中 3.获取到mapOutputWriter,将中间产生的临时文件合并到一个临时文件 4.生成最后的data文件和index文件 可以看到写入的重点类是ExternalSorter对象 ExternalSorter 基…...
ESP32CAM物联网教学12
ESP32CAM物联网教学12 MicroPython 视频服务 小智希望能在MicroPython中实现摄像头的视频服务,就像官方示例程序CameraWebServer那样。 下载视频服务驱动库 小智通过上网搜索,发现相关的教学材料还不少,并且知道有人已经写出了视频服务的驱…...
【C++精华铺】12.STL list模拟实现
1.序言 STL (Standard Template Library)是C标准库中的一个重要组件,提供了许多通用的数据结构和算法。其中,STL list是一种带头双向链表容器,可以存储任意类型的元素。 list的特点包括: 双向性:list中的元素可以根据需…...
ChatGPT Mac App 发布!
2024 年 6 月,OpenAI 的大语言模型 ChatGPT 的 Mac 客户端与 ChatGPT-4o 一起发布了。ChatGPT Mac 户端可以让用户直接在 Mac 电脑上使用 ChatGPT 进行对话。它提供了一个简单易用的用户界面,用户可以在其中输入文本或语音指令,并接收模型生成…...
ACE之ACE_Time_Value
简介 ACE_Time_Value在ACE中表示时间,集成不同平台的时间 结构 #mermaid-svg-dGoKn1R7GicabUif {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dGoKn1R7GicabUif .error-icon{fill:#552222;}#mermaid-…...
[论文笔记] 自对齐指令反翻译:SELF-ALIGNMENT WITH INSTRUCTION BACKTRANSLATION
https://arxiv.org/pdf/2308.06259 这篇论文介绍了一种名为“指令反向翻译”(instruction backtranslation)的方法,用于通过自动标记人类书写的文本和相应的指令来构建高质量的指令跟随语言模型。这里是一个通俗易懂的解释: 一、背景 通常,训练一个高质量的指令跟随语言…...
算术运算符. 二
# 表达式 # 操作数和运算符组成 比如 11 # 作用:表达式可以求值,也可以给变量赋值。 # Python算术运算符: # - * / % //(整除:向下取整) ** print(10 4) # 14 print(10 - 4) # 6 print(10 * 4) # 40 …...
代码优化方法记录
每次代码 review 之后,对 review 的情况进行总结记录,产出实际经验,方便组内学习、分享。 1、提取公共内容 公共内容要提取,避免重复编写; 2、css 色值使用变量 css 中的色值、字体,都换成组件库中的变…...
qt 图形、图像、3D相关知识
1.qt 支持3d吗 Qt确实支持3D图形渲染。Qt 3D模块是Qt的一个组成部分,它允许开发者在Qt应用程序中集成3D内容。Qt 3D模块提供了一组类和函数,用于创建和渲染3D场景、处理3D对象、应用光照和纹理等。 Qt 3D模块包括以下几个主要组件: Qt 3D …...
【逆向基础】十、工具分享之DIE(Detect It Easy)
一、简介 DIE(Detect It Easy)是一款可以轻松检测PE文件的程序;其主要作用是查壳,并将pe文件的内容解析出来,包括PE文件中包含的导入函数、导出函数的名称及地址,入口函数地址等,是技术人员分析…...
Netcat:——网络瑞士军刀
Netcat: 网络瑞士军刀 概述 Netcat(通常称为 nc)是一个功能强大的网络工具,广泛用于网络测试和调试。它能够读取和写入网络数据,支持TCP、UDP协议,可以用于端口扫描、端口监听、文件传输等多种用途。 主要用途 获取…...
C++ //练习 14.50 在初始化ex1和ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。
C Primer(第5版) 练习 14.50 练习 14.50 在初始化ex1和ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。 struct LongDouble{LongDouble(double 0.0);operator double();operator float(); }; Long…...
【开源 Mac 工具推荐之 1】gibMacOS:方便快捷的 macOS 完整包下载 Shell 工具
简介 gibMacOS 是由 GitHub 开发者 corpnewt 编写的一款 Shell 工具。它采用 Python 编程语言,可以让用户打开后在纯文本页面中轻松选择并下载来源于 Apple 官方的 macOS 完整安装包。 Repo 地址:https://github.com/corpnewt/gibMacOS (其…...
pdf文件如何快速英文转中文?
要将 PDF 文件中的英文内容转换为中文,你可以使用以下几种方法: 1、在线翻译工具: 使用网上的免费在线翻译工具,如Google翻译、百度翻译或有道翻译,将整个 PDF 文档粘贴到工具中进行翻译。 2、专业翻译软件…...
程序的控制结构——if-else语句(双分支结构)【互三互三】
目录 🍁 引言 🍁if-else语句(双分支结构) 👉格式1: 👉功能: 👉程序设计风格提示: 👉例题 👉格式2: 👉…...
[C++]初识C++(命名空间,命名空间使用,函数重载,缺省参数等)
💖💖💖欢迎来到我的博客,我是anmory💖💖💖 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…...
每天一个数据分析题(四百十六)- 线性回归模型
根据模型假设,线性回归模型中误差项的方差为 A. 常数 B. 函数 C. 随机变量 D. 以上都不是 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容涵盖Python,SQL,统计学&#…...
JupyterNotebook中导出当前环境,并存储为requirements.txt
使用Anaconda管理Python环境时,可以轻松地导出环境配置,以便在其他机器或环境中重新创建相同的环境。可以通过生成一个environment.yml文件实现的,该文件包含了环境中安装的所有包及其版本。但是,常常在一些课程中JupyterNotebo…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
