程序环境和预处理(二)

简介: 程序环境和预处理(二)

程序环境和预处理(一)+https://developer.aliyun.com/article/1385004

3.2.2 #define 定义宏

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

宏的申明方式:

       #define name( parament-list ) stuff

其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。

注意:

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

例如:

 

#define SQUARE(x) x*x
int main()
{
  int a = 3;
  int n = SQUARE(a + 2);
  printf("%d\n", n);
  return 0;
}

我们想得到的结果是25,这里得到的为什么是11呢?

注意:在写宏时,我们要把每个参数用括号扩起来,同时宏整体也要扩起来 。

所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中 的操作符或邻近操作符之间不可预料的相互作用。

2.2.3 #define 替换规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤:

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

注意:

  • 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
  • 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
3.2.4  # 和 ##

使用 # ,把一个宏参数变成对应的字符串

#define PRINT(n,format) printf("the value of "#n" is "format"\n",n);
int main()
{
  int a = 3;
  PRINT(a, "%d");
  int b = 5;
  PRINT(b, "%d");
  float c = 10.0;
  PRINT(c, "%f");
}

使用 ##,把位于它两边的符号合成一个符号

#define CAT(x,y) (x##y)
int main()
{
  int a110 = 2023;
  printf("%d\n", CAT(a, 110));
}
3.2.5 带副作用的宏参数

这段代码的结果是什么呢?

#define MAX(x, y) ( (x) > (y) ? (x) : (y) )
int main()
{
  int a = 5;
  int b = 6;
  int c = MAX(a++, b++);
  printf("a=%d\n", a);
  printf("b=%d\n", b);
  printf("c=%d\n", c);
  return 0;
}

宏参数代替后:

int c = MAX(a++, b++);
int c =(a++)>(b++)?(a++):(b++);

a和b都是后置++,所以都是先使用,后++。

注意:当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能 出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。

3.2.6 宏和函数对比

宏通常被应用于执行简单的运算。

比如在两个数中找出较大的一个。

       #define MAX(a, b) ((a)>(b)?(a):(b))

不用函数来完成这个任务的原因:

  1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。 所以宏比函数在程序的规模和速度方面更胜一筹。
  2. 更为重要的是函数的参数必须声明为特定的类型。 所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以 用于>来比较的类型。 宏是类型无关的。

使用宏来计算最大值的汇编代码和用函数计算最大值的汇编代码的对比:

宏的缺点:当然和函数相比宏也有劣势的地方:

  1. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序 的长度。
  2. 宏是没法调试的。
  3. 宏由于类型无关,也就不够严谨。
  4. 宏可能会带来运算符优先级的问题,导致程容易出现错。

程序环境和预处理(三)+https://developer.aliyun.com/article/1385006

相关文章
|
运维 负载均衡 安全
以太通道详解:网络连接的桥梁
【4月更文挑战第22天】
534 0
|
域名解析 网络协议 Linux
【Shell 命令集合 网络通讯 】Linux 设置和管理网络接口配置信息 netconfig命令 使用指南
【Shell 命令集合 网络通讯 】Linux 设置和管理网络接口配置信息 netconfig命令 使用指南
450 1
|
机器学习/深度学习 传感器 运维
综述:弱监督下的异常检测算法
# 一、前言 文章标题是: Weakly Supervised Anomaly Detection: A Survey 这是一篇针对“弱监督”异常检测的综述。 其中弱监督异常检测 简称为 WSAD - 论文链接:https://arxiv.org/abs/2302.04549 - 代码链接:https://github.com/yzhao062/wsad # 二、问题 针对异常检测问题,其
724 1
综述:弱监督下的异常检测算法
|
4月前
|
Arthas 存储 Java
JVM深入原理(三+四):JVM组成和JVM字节码文件
目录3. JVM组成3.1. 组成-运行时数据区3.2. 组成-类加载器3.3. 组成-执行引擎3.4. 组成-本地接口4. JVM字节码文件4.1. 字节码文件-组成4.1.1. 组成-基础信息4.1.1.1. 基础信息-魔数4.1.1.2. 基础信息-主副版本号4.1.2. 组成-常量池4.1.3. 组成-方法4.1.3.1. 方法-工作流程4.1.4. 组成-字段4.1.5. 组成-属性4.2. 字节码文件-查看工具4.2.1. javap4.2.2. jclasslib4.2.3. 阿里Arthas
89 0
|
6月前
|
机器学习/深度学习 数据采集 算法
基于yolov2和googlenet网络的疲劳驾驶检测算法matlab仿真
本内容展示了基于深度学习的疲劳驾驶检测算法,包括算法运行效果预览(无水印)、Matlab 2022a 软件版本说明、部分核心程序(完整版含中文注释与操作视频)。理论部分详细阐述了疲劳检测原理,通过对比疲劳与正常状态下的特征差异,结合深度学习模型提取驾驶员面部特征变化。具体流程包括数据收集、预处理、模型训练与评估,使用数学公式描述损失函数和推理过程。课题基于 YOLOv2 和 GoogleNet,先用 YOLOv2 定位驾驶员面部区域,再由 GoogleNet 分析特征判断疲劳状态,提供高准确率与鲁棒性的检测方法。
|
11月前
|
JSON 前端开发 测试技术
API接口 |产品经理一定要懂的10%技术知识
作为产品经理,掌握约10%的技术知识对处理API相关工作至关重要。这包括理解API的基本概念及其作为数据交换的桥梁作用;熟悉JSON和XML两种主要数据格式及其特点;了解常见HTTP请求方法(GET、POST、PUT、DELETE)及响应状态码;关注API安全性,如认证授权和数据加密;掌握API版本管理和错误处理技巧;重视性能优化,以提升用户体验;参与API联调测试,确保稳定可靠;并与前后端团队紧密协作,选择合适的第三方API服务,推动产品高效开发。
|
10月前
|
存储 数据可视化 API
重磅干货,免费三方网络验证[用户系统+CDK]全套API接口分享教程。
本套网络验证系统提供全面的API接口,支持用户注册、登录、数据查询与修改、留言板管理等功能,适用于不想自建用户系统的APP开发者。系统还包含CDK管理功能,如生成、使用、查询和删除CDK等。支持高自定义性,包括20个自定义字段,满足不同需求。详细接口参数及示例请参考官方文档。
|
监控 安全 网络安全
使用 Scapy 库编写 ICMP 洪水脚本
使用 Scapy 库编写 ICMP 洪水脚本
使用 Scapy 库编写 ICMP 洪水脚本
|
存储 NoSQL Java
Jedis
Jedis
153 0
|
安全 网络安全
IP的纯净度:评判标准与重要性
**IP纯净度关乎网络行为的安全与可靠性。高纯净度IP指独立、真实、无不良记录的地址。评估标准包括:** - **IP来源**:正规ISP的IP更纯净。 - **历史记录**:检查是否涉及违规行为或在黑名单中。 - **技术特征**:支持SSL,匿名性高,连接稳定快速的IP更佳。 - **用户反馈**:用户评价反映IP的实际表现和信誉。 综合考量这些因素,能确保选择到安全可靠的IP地址。

热门文章

最新文章