【C初阶】预处理

简介: 【C初阶】预处理

前言:在本文中,我将系统的整理一下C语言关于预处理部分的语法,便于整理与回归。

1.预定义符号

在C语言中,C标准提供里一些C预定义符号,在预处理期间完成,可以直接使用。

有如下几个符号:

2.#define

在这个define情况下,该语句是在预处理期间处理完成的。有下面几种不同的分类:

2.1#define 常量定义

注:在使用这个常量定义时候,尽量不要在后面带上“;"这个分号(有需要除外)。

2.2#define 宏定义

#define机制包括了⼀个规定,允许把参数替换到⽂本中,这种实现通常称为宏(macro)或定义宏(definemacro)

注:

1.参数列表的左括号必须与name紧邻,如果两者之间有任何空⽩存在,参数列表就会被解释为stuff的⼀部分。

2.要带上小括号

3.不要使用带有改变参数本身性质的语法

宏在替换过程中,遵循以下规律:

  1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先被替换。
  2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。
  3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

注:1.define可以出现其他define符号 2.在define中不能使用递归

2.3 宏与函数区别

3.4#undef 移除定义

3.5define与函数的命名约定

在通常情况下,宏一般全部大写命名,函数一般不全大写命名。

3.#与##操作符

#作用:将参数字符串化
##作用:参数字符串化并粘合其右边符号作为一个变量名称

3.1#的代码示例:

把字符串中的参数字符串化

#include<stdio.h>
#define my_printf(val,name) printf("the num of " #name " is %d",val);
int main()
{
  int a = 6;
  my_printf(a, a);
  return 0;
}

注意:1.简单的宏替换2.把替换的参数字符串化

3.2##的代码示例

造一个贴切返回类型的函数名

#define my_max(type) \
type type##_max(type x,type y)\
{\
return x>y?x:y;\
}\
my_max(int)
int main()
{
  int max = int_max(1, 2);
  printf("max = %d\n", max);
  return 0;
}

4.命名行定义

许多C的编译器提供了⼀种能⼒,允许在命令⾏中定义符号。⽤于启动编译过程。例如:当我们根据同⼀个源⽂件要编译出⼀个程序的不同版本的时候,这个特性有点⽤处。(假定某个程序中声明了⼀个某个⻓度的数组,如果机器内存有限,我们需要⼀个很⼩的数组,但是另外⼀个机器内存⼤些,我们需要⼀个数组能够⼤些。)

5.条件编译

在编译⼀个程序的时候我们如果要将⼀条语句(⼀组语句)编译或者放弃是很⽅便的。

条件编译用来处理调试性的代码,删除可惜,保留⼜碍事,所以我们可以选择性的编译或者是一些不同版本的代码。

5.1#if

这个跟if基本是一样的,如果if后面结果为真,那么下面这些代码(直到#end)就执行编译,为假就不参与编译。

下面是示例:

int main()
{
#if 1
  printf("hello world\n");
#endif
  return 0;
}

这里有个很坑的写法:

#include<stdio.h>
#include<windows.h>
#define A 1
int main()
{
  int a = 1;
#if A == a
  printf("hello world\n");
#endif
  system("pause");
  return 0;
}

明明相等为啥printf不参与编译啊?因为变量a是在预处理之后形成的。

5.2#ifdef

如果后面的参量名称被定义了,那么ifdef下面(直到#endif)就参与编译。如果没有被定义,ifdef下面(直到#endif)就不参与编译。

注:#ifdef一般逻辑比较简单,只与#else连用,不会和#elif进行连用,连用的话逻辑与我们想的也不太一样。

#include<stdio.h>
#include<windows.h>
#define PAUSE
int main()
{
#ifdef PAUSE
  printf("pause\n");
#endif
  return 0;
}

5.3#ifndef

如果后面的参量名称没有被定义,那么ifndef下面(直到#endif)就参与编译。如果被定义,ifndef下面(直到#endif)就不参与编译。

#include<stdio.h>
#include<windows.h>
#define PAUSE
int main()
{
#ifndef PAUSE
  printf("pause\n");
#endif
  return 0;
}

所以这里有个很重要的常见用法:就是避免头文件重复包含的问题(参见下面方法2)。

//1.方式1:
#pragma once
//2.方式2:
#ifndef ONCE
#define ONCE
//...
#endif

5.4多个分支条件编译#if #elif #else

与if、else if、else同理

#include<stdio.h>
#include<windows.h>
#define A 2
int main()
{
#if A==1
  printf("1\n");
#elif A==2
  printf("2\n");
#elif A==3
  printf("3\n");
#endif
  system("pause");
  return 0;
}

5.5上面所说的可以嵌套使用

#include<stdio.h>
#include<windows.h>
#define A 2
int main()
{
#if A==2
#ifdef A
  printf("ok\n");
#endif
#endif
  return 0;
}

6.头文件包含

#include”“先搜索本地头文件,找不到再去找库头文件。

#include<>直接去找库头文件.


完。

相关文章
|
12月前
|
canal 编解码 运维
飞天洛神云网络再度入选通信顶会 SIGCOMM'24
飞天洛神云网络再度入选通信顶会 SIGCOMM'24
428 12
|
存储 安全 BI
PeopleSoft中的文件上传与下载:实现与优化
PeopleSoft中的文件上传与下载:实现与优化
421 7
|
数据采集 前端开发 JavaScript
捕捉页面的关键元素:用CSS选择器与Puppeteer自动抓取
本文介绍了如何使用 Puppeteer 结合 CSS 选择器抓取动态网页中的关键元素,以亚航网站的特价机票信息为例,通过设置代理 IP、User-Agent 和 Cookie 等技术手段,有效提升爬虫策略,实现高效、稳定的爬取。
399 5
捕捉页面的关键元素:用CSS选择器与Puppeteer自动抓取
|
数据管理 测试技术 持续交付
软件测试中的自动化测试策略与最佳实践
在当今快速迭代的软件开发环境中,自动化测试已成为确保软件质量和加速产品上市的关键手段。本文旨在探讨软件测试中的自动化测试策略,包括选择合适的自动化测试工具、构建有效的自动化测试框架以及实施持续集成和持续部署(CI/CD)。通过分析自动化测试的最佳实践,本文为软件开发团队提供了一系列实用的指南,以优化测试流程、提高测试效率并减少人为错误。
396 4
|
安全 API 数据安全/隐私保护
小红书接口数据查询优化指南
小红书作为热门的社交媒体平台,提供了丰富的API接口供开发者使用。本文档详细介绍如何通过API高效查询小红书数据,包括注册登录、创建应用、接口调用及数据解析等步骤,并附有Python示例代码,助您轻松上手。同时,强调了合规使用、隐私保护和请求频率控制的重要性,确保数据查询的安全与高效。
|
小程序 前端开发 数据安全/隐私保护
微信小程序全栈开发中的身份认证与授权机制
【10月更文挑战第3天】随着移动互联网的发展,微信小程序凭借便捷的用户体验和强大的社交传播能力,成为企业拓展业务的新渠道。本文探讨了小程序全栈开发中的身份认证与授权机制,包括手机号码验证、微信登录、第三方登录及角色权限控制等方法,并强调了安全性、用户体验和合规性的重要性,帮助开发者更好地理解和应用这一关键技术。
469 5
|
存储 安全 测试技术
如何评估 API 的质量
本文详细介绍了评估API质量的关键指标,包括功能性(功能完整性与准确性)、可靠性(稳定性和错误处理)、性能(响应时间和吞吐量)、易用性(文档质量和接口设计)及安全性(身份验证和数据加密),并提供了具体评估方法与测试建议,帮助开发者全面衡量API质量。通过这些评估,可以确保选择到高质量的API,为软件项目奠定坚实基础。
591 5
|
网络协议 Unix 网络架构
网际控制报文协议ICMP
网际控制报文协议(ICMP)是TCP/IP体系结构中网际层的关键组件,用于提高IP数据报的成功传输率。ICMP主要处理两类报文:差错报告报文与询问报文。前者包括终点不可达、源点抑制、时间超过、参数问题及重定向等五类;后者则涵盖回送请求/回答及时间戳请求/回答。ICMP广泛应用于检测网络连通性的PING工具和追踪数据包路径的traceroute工具中。两者分别利用ICMP的回送请求报文及差错报告报文实现功能。
766 10
|
5G 测试技术 语音技术
5G赋能沉浸式体验:VR/AR时代的网络基石
5G赋能沉浸式体验:VR/AR时代的网络基石
672 1