C语言预处理命令

编译预处理指令:对源程序编译之前做一些处理,生成扩展C源程序

1、种类:

  • 宏定义 #define
  • 文件包含 #include
  • 条件编译 #if–#else–#endif等

2、格式:

  • “#”开头
  • 占单独书写行
  • 语句尾不加分号

3、宏定义

在C语言源程序中允许用一个标识符来表示一个字符串,称为“宏”。被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”
宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的

格式:#define 宏名 宏替换值
作用:在进行编译预处理的时候,编译器会对程序中出现的所有的宏名使用宏字符串去进行替换–宏替换仅为简单字符替换

实例:

#include <stdio.h>
#define PI 3.1415   //宏名PI,替换所用的字符串3.1415int main(int argc, char *argv[])
{int r = 5;float s;s = (float)PI * r * r;printf("s = %7.2f\n", s);r = 4;s = (float)PI * r * r;printf("s = %7.2f\n", s);return 0;
}

该程序预处理以后main函数会变成如下形式:

int main(int argc, char *argv[])
{int r = 5;float s;s = (float)3.1415 * r * r;printf("s = %7.2f\n", s);r = 4;s = (float)3.1415 * r * r;printf("s = %7.2f\n", s);return 0;
}

在C中经常使用宏来定义常量–所以经常把C中的常量叫做符号常量

#include <stdio.h>
#define PI 3.1415   //宏名PI,替换所用的字符串3.1415
#define RC PI * 5.0
#define VAL PI + 5  //在定义复杂的宏的时候一定要注意避免出现副作用,因为宏替换只是简单的字符替换
#define VAL1 ((PI)  + 5)int main(int argc, char *argv[])
{int r = 5;float s;s = (float)PI * r * r;printf("s = %7.2f\n", s);r = 4;s = (float)PI * r * r;printf("s = %7.2f\n", s);s = RC;   //s = 3.1415 * 5.0printf("s = %7.2f\n", s);s = VAL * r * r;   //PI + 5 * r * rprintf("s = %7.2f\n", s);s = VAL1 * r * r;   //PI + 5 * r * rprintf("s = %7.2f\n", s);return 0;
}
[root@localhost 10_bits]# gcc test3.c -o test3
[root@localhost 10_bits]# ./test3
s =   78.54
s =   50.26
s =   15.71
s =   83.14
s =  130.26

带参数宏:

#include <stdio.h>
#define PI 3.1415   //宏名PI,替换所用的字符串3.1415
#define MAX(x, y) x > y ? x : y  //x和y成为带参宏的形参
int main(int argc, char *argv[])
{int num1 = 12;int num2 = 21;int res = MAX(num1, num2);  //在使用带参宏的时候要将对应的实参传递给形参  -- 和函数调用是一样的printf("res = %d\n", res);return 0;
}
上述代码进行宏替换以后称为:
int main(int argc, char *argv[])
{int num1 = 12;int num2 = 21;int res = num1 > num2 ? num1 : num2;  //在替换过程中除了将带参宏定义中的宏值替换宏名以外,还会将实参替换宏定义中的形参printf("res = %d\n", res);return 0;
}

带参宏和函数调用的区别:

  1. 带参数宏的代码在编译过程以后,宏代码会变成程序的本地代码(宏的代码和程序的代码在同一环境下),而函数调用中函数的代码要靠链接进来
  2. 对于一些简单的算法(算法中包含的语句不多的情况下),使用带参宏相比于使用函数调用,程序的运行效率要高
  3. 带参数的宏经常可以适用于不同的参数类型和返回值类型,所以他的通用性更好;但是他的安全性更差。在编译过程中,如果说是函数调用的话,对于实参传递给形参,对于将函数的返回值赋值给其他的对象都会进行类型判定,如果出现类型不兼容,在编译的过程中就会发现;而使用带参宏,由于在编译过程中只进行替换,往往不能发现类型方面的问题,经常都会在程序运行过程中出现意想不到的错误
#include <stdio.h>
#define PI 3.1415   //宏名PI,替换所用的字符串3.1415
#define MAX(x, y) x > y ? x : y/*
int MAX(int x, int y)
{return x > y ? x : y;
}
*/int main(int argc, char *argv[])
{int num1 = 12;int num2 = 21;double dnum1 = 1.23;double dnum2 = 2.32;double dres = MAX(dnum1, dnum2);int res = MAX(num1, num2);//res = MAX(dnum1, dnum2);printf("res = %d\n", res);printf("dres = %7.2f\n", dres);return 0;
}
[root@localhost 10_bits]# gcc test3.c -o test3
[root@localhost 10_bits]# ./test3
res = 2
dres =    2.32

4、文件包含

在编译预处理过程中,会将包含的文件的内容替换到本文件 中
在头文件中定义数据结构,函数原型
在一个c源程序中实现函数
在主程序中调用函数
比如在stu.h中定义学生结构体和函数原型

typedef struct Stu
{int no;char name[12];float score;
}Stu;void show_stu(Stu tmp);

在stu.c中实现stu.h中定义的函数

#include "stu.h"
#include <stdio.h>void show_stu(Stu tmp)
{printf("%d, %s, %7.2f\n", tmp.no, tmp.name, tmp.score);
}

在main.c中调用函数

#include <stdio.h>
#include "stu.h"int main(int argc, char *argv[])
{Stu st = {101, "Jack", 88.5};show_stu(st);return 0;
}
[root@localhost student_manager]# gcc stu.c main.c -o main
[root@localhost student_manager]# ./main
101, Jack,   88.50

5、条件编译

#include <stdio.h>int main(int argc, char *argv[])
{int num1  = 10;int num2 = 20;int res;#ifdef SUMres = num1 + num2;#elseres = num2 - num1;#endifprintf("res = %d\n", res);return 0;
}

该代码编译预处理以后会变成如下:

int main(int argc, char *argv[])
{int num1 = 10;int num2 = 20;int res;res = num2 - num1;printf("res = %d\n", res);return 0;
}

如果程序原型为:

#include <stdio.h>
#define SUMint main(int argc, char *argv[])
{int num1  = 10;int num2 = 20;int res;#ifdef SUMres = num1 + num2;#elseres = num2 - num1;#endifprintf("res = %d\n", res);return 0;
}

则编译预处理以后为:

int main(int argc, char *argv[])
{int num1 = 10;int num2 = 20;int res;res = num1 + num2;printf("res = %d\n", res);return 0;
}

所以条件编译是根据条件十分满足来确定需要编译的语句块
#ifdef … #else … #endif结构是根据指定的标识符是否定义来确定要编译的语句,如果指定标识符在条件编译语句之前已经定义了,选择ifdef部分的语句进行编译(ifdef或者else部分可以是多条件语句,并且不需要使用大括号),如果指定的标识符没有定义则选择else部分的语句进行编译

条件编译还有另外一种结构#ifndef … #else … #endif

所以前面多文件工程应该写成
stu.h

#ifndef __MYHEAD
#define __MYHEAD
typedef struct Stu
{int no;char name[12];float score;
}Stu;
#endif

head1.h

#ifndef __HEAD_1
#define __HEAD_1
#include "stu.h"void show_stu(Stu tmp);#endif

stu.c

#include "stu.h"
#include "head1.h"
#include <stdio.h>void show_stu(Stu tmp)
{printf("%d, %s, %7.2f\n", tmp.no, tmp.name, tmp.score);
}

main.c

include <stdio.h>
#include "stu.h"
#include "head1.h"int main(int argc, char *argv[])
{Stu st = {101, "Jack", 88.5};show_stu(st);return 0;
}

我们也经常使用条件编译语句来进行调试

#include <stdio.h>
#define SUM
//#define DEBUGERint main(int argc, char *argv[])
{int num1  = 10;int num2 = 20;int res;#ifdef DEBUGERprintf("ok1\n");#endif#ifndef SUMres = num1 + num2;#elseres = num2 - num1;#endifprintf("res = %d\n", res);#ifdef DEBUGERprintf("ok2\n");#endifreturn 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/34570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

掌握Python的X篇_32_使用python编辑pdf文件_pdfrw

本篇介绍利用python操作pdf文件&#xff0c;我们平时也会有合并和拆分pdf的需求&#xff0c;此时我们就可以使用本节内容。 文章目录 1. pdfrw的安装2. 切分pdf文件3. pdfrw官网及实现一版四面的实例 1. pdfrw的安装 pip install pdfrw官网地址&#xff1a;https://github.co…

【设计模式】装饰器模式

装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种类型的设计模式属于结构型模式&#xff0c;它是作为现有的类的一个包装。 装饰器模式通过将对象包装在装饰器类中&#xff0c;以便动态地修改其行为…

如何在Linux中查找Nginx安装目录

一、通过which命令查找 $ which nginx /usr/sbin/nginxwhich命令会在系统环境变量PATH中查找nginx可执行文件&#xff0c;并返回路径。因此&#xff0c;通过which命令可以很容易地找到系统中nginx的安装位置。 二、通过whereis命令查找 $ whereis nginx nginx: /usr/sbin/ng…

51单片机(普中HC6800-EM3 V3.0)实验例程软件分析 实验六 静态数码管显示

目录 前言 一、原理图及知识点介绍 1.1、数码管原理图&#xff1a; 二、代码分析 前言 第一个实验&#xff1a; 51单片机&#xff08;普中HC6800-EM3 V3.0&#xff09;实验例程软件分析 实验一 点亮第一个LED_ManGo CHEN的博客-CSDN博客 第二个实验&#xff1a;51单片机&am…

计算机竞赛 LSTM的预测算法 - 股票预测 天气预测 房价预测

0 简介 今天学长向大家介绍LSTM基础 基于LSTM的预测算法 - 股票预测 天气预测 房价预测 这是一个较为新颖的竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/postgraduate 1 基于 Ke…

Java进阶-Oracle(二十)(1)

&#x1f33b;&#x1f33b; 目录 一、Oracle 数据库介绍1、Oracle 的概述2、Oracle 的结构2、Oracle的功能 二、安装与卸载1、卸载2、安装 三、使用&#xff08;需要关注得只有下面这两个&#xff09;四、PLSQL 的简单使用五、DBeaver 的简单使用 一、Oracle 数据库介绍 1、O…

【深度学习】遗传算法[选择、交叉、变异、初始化种群、迭代优化、几何规划排序选择、线性交叉、非均匀变异]

目录 一、遗传算法二、遗传算法概述2.1 选择2.2 交叉2.3 变异 三、遗传算法的基本步骤3.1 编码3.2 初始群体的生成3.3 适应度评估3.4 选择3.5 交叉3.6 变异3.7 总结 四、遗传算法工具箱4.1 initializega4.2 ga4.3 normGeomSelect4.4 arithXover4.5 nonUnifMutation 五、遗传算法…

ASL国产CS5213 转VGA信号输出音频 替代AG6200安格芯片 HDMI to VGA(带音频)方案设计原理图

CS5213功能&#xff1a;HDMI转VGA带音频输出&#xff0c;专注于设计HDMI转VGA带音频输出。可替代AG6200 AG6201。 CS5213芯片是一个HDMI&#xff08;高清多媒体接口&#xff09;到VGA桥接芯片。 它将HDMI信号转换为标准VGA信号它可以在适配器、智能电缆等设备中设计。 Capst…

JAVA 实训报告心得体会

一开始想做计算器那个课题&#xff0c;原因很简单&#xff0c;就是因为我感觉那个课题很简 单&#xff0c;在百度里一搜就搜到了一模一样的源程序。只是感觉没什么意思&#xff0c;那个界面也 不是很好看&#xff0c;又不好玩。所以就做了现在这个猜数游戏。一直想编个游戏程序…

【数据结构与算法】分治算法

分治算法 介绍 分治法是一种很重要的算法&#xff0c;字面意思的解释是“分而治之”&#xff0c;就是把一个复杂的问题分成两个或更多的相同或相似的子问题&#xff0c;再把子问题分成更小的子问题…直到最后子问题可以简单的直接求解&#xff0c;原问题的解即子问题解的合并…

前端接口修改工具 Requestly具体操作

更新于2023年8月12日18:17:56&#xff0c;插件版本可能会变&#xff0c;界面可能会有所变化 插件下载地址&#xff1a;https://chrome.google.com/webstore/detail/requestly-open-source-htt/mdnleldcmiljblolnjhpnblkcekpdkpa 注意&#xff0c;必须用谷歌浏览器&#xff0c;…

Mysql压力测试(sysbench)

目录 配置项目环境&#xff1a; 参考&#xff1a;采用sysbench压测mysql详解_dream21st的博客-CSDN博客 实验步骤&#xff1a; 1、安装sysbench工具 2、在master上创建用户和库&#xff0c;配置用户的权限可以使他可以访问库&#xff08;Mysql的主从复制&#xff09; 3、基…

什么是单页应用程序?如何选择及架构、优势和挑战

什么是单页应用程序&#xff08;Single-Page Application&#xff09;&#xff1f; 单页面应用程序(Web应用程序或网站)仅加载单个页面。然后&#xff0c;当用户与Web服务器交互时&#xff0c;它使用从Web服务器获取的新内容重写页面&#xff0c;而不是为每次交互加载新页面。…

Linux中TCP服务端和客户端

服务端 #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <string.h> #include <netinet/in.h> #include <netinet/ip.h> #include <head.h>#define PORT 6666 …

Linux 文件编辑命令

一、三种模式介绍 命令模式 插入模式(编辑模式) 末行模式 二、模式切换 1.命令模式切换到插入模式 &#xff08;1&#xff09; a //进入到当前光标后开始编辑 &#xff08;2&#xff09; A //进入到当前光标所在行的行末开始编辑 &#xff08;3&#xff09;i //进入当前光…

Python Opencv实践 - 图像缩放

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg_cat cv.imread("../SampleImages/cat.jpg", cv.IMREAD_COLOR) plt.imshow(img_cat[:,:,::-1])#图像绝对尺寸缩放 #cv.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) #指定Size大…

最新智能AI系统+ChatGPT源码搭建部署详细教程+知识库+附程序源码

近期有网友问宝塔如何搭建部署AI创作ChatGPT&#xff0c;小编这里写一个详细图文教程吧。 使用Nestjs和Vue3框架技术&#xff0c;持续集成AI能力到AIGC系统&#xff01; 增加手机端签到功能、优化后台总计绘画数量逻辑&#xff01;新增 MJ 官方图片重新生成指令功能同步官方 …

注意:阿里云服务器随机分配可用区说明

阿里云服务器如有ICP备案需求请勿选择随机可用区&#xff0c;因为当前地域下的可用区可能不支持备案&#xff0c;阿里云百科分享提醒大家&#xff0c;如果你的购买的云服务器搭建网站应用&#xff0c;网站域名需要使用这台云服务器备案的话&#xff0c;不要随机分配可用区&…

ATF(TF-A)安全通告 TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754)

ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754) 二、Variant 1 (CVE-2017-5753) 三、Variant 2 (CVE-2017-5715) 四、Variant 3 (CVE-2017-5754) 一、ATF(TF-A)安全通告 TFV-6 (CVE-2017-5753, CVE-2017-5715, C…

tp5中的事务处理

使用事务首先要数据库支持事务&#xff1b; 如下MySQL数据库user表开启事务支持&#xff0c;即设计表->引擎设置为InnoDB->保存 事务处理 1. 数据库的表引擎需要是 InnoDB 才可以使用&#xff0c;如果不是调整即可&#xff1b; 2. 事务处理&#xff0c;需要执行多个 SQ…