主页:114514的代码大冒
qq:2188956112(欢迎小伙伴呀hi✿(。◕ᴗ◕。)✿ )
Gitee:庄嘉豪 (zhuang-jiahaoxxx) - Gitee.com
文章目录
目录
文章目录
前言
2.5带副作用的宏参数
2.6宏和函数的对比
3#undef
编辑
4 命令行定义
5 条件编译
6 文件包含
总结
前言
咱们书接上回
2.5带副作用的宏参数
先来看一段代码
#define MAX(x,y) ((x)>(y)?(x):(y))
int main()
{
int a = 4;
int b = 6;
int m = MAX(a++, b++);
printf("%d\n", m);
printf("a=%d b=%d\n", a, b);
return 0;
}
这个结果是什么呢?
为什么?
我们一样要考上文中的“宏是一种替换”的概念,先做一下替换然后我们来解析一下
x+1;//不带副作用
x++;//带有副作用
但是在这里这种情况,函数就不会发生类似问题
这里我提供了测试代码,读者可自取
#define MAX(x,y) ((x)>(y)?(x):(y))
int Max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
//int m = MAX(2, 3);
//printf("%d\n", m);
int a = 4;
int b = 6;
int m = MAX(a++, b++);
//int m = Max(a++, b++);
printf("%d\n", m);
// m = 7
printf("a=%d b=%d\n", a, b);
return 0;
}
2.6宏和函数的对比
函数的反汇编
宏的反汇编
宏明显要快不少嘛
1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜一筹 。2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用于> 来比较的类型。宏是类型无关的 。
宏的缺点
当然和函数相比宏也有劣势的地方:1. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度。2. 宏是没法调试的。3. 宏由于类型无关,也就不够严谨。4. 宏可能会带来运算符优先级的问题,导致程容易出现错。
宏没有类型,如上图所示,函数只能进行固定类型数据的操作,而宏却可以忽视这一细节
但是对应的,宏是一种替换,也就是说,他会把定义的内容替换到正文代码中,造成代码超度变长
另外就是像上文所说的那种“副作用”,足以看出宏在调试时的问题是比较大的,
因为“你看到的并非你看到的(宏替换的关系)”
所以总的说来,宏有着优点也有着缺点
具体使用函数还是宏,要根据实际情况
属
性
|
#define
定义宏
|
函数
|
代
码
长
度
|
每次使用时,宏代码都会被插入到程序中。除了非常
小的宏之外,程序的长度会大幅度增长
|
函数代码只出现于一个地方;每
次使用这个函数时,都调用那个
地方的同一份代码
|
执
行
速
度
|
更快
|
存在函数的调用和返回的额外开 销,所以相对慢一些
|
操
作
符
优
先
级
|
宏参数的求值是在所有周围表达式的上下文环境里,
除非加上括号,否则邻近操作符的优先级可能会产生
不可预料的后果,所以建议宏在书写的时候多些括
号。
|
函数参数只在函数调用的时候求
值一次,它的结果值传递给函
数。表达式的求值结果更容易预测
|
带
有
副
作
用
的
参
数
|
参数可能被替换到宏体中的多个位置,所以带有副作 用的参数求值可能会产生不可预料
的结果
|
函数参数只在传参的时候求值一次,结果更容易控制。
|
参
数
类
型
|
宏的参数与类型无关,只要对参数的操作是合法的, 它就可以使用于任何参数类型。
|
函数的参数是与类型有关的,如果参数的类型不同,就需要不同的函数,即使他们执行的任务是相同的。
|
调
试
|
宏是不方便调试的
|
函数是可以逐语句调试的
|
递
归
|
宏是不能递归的
|
函数是可以递归的
|
把宏名全部大写函数名不要全部大写
3#undef
#undef NAME// 如果现存的一个名字需要被重新定义,那么它的旧名字首先要被移除。
4 命令行定义
#include <stdio.h>
int main()
{
int array [ARRAY_SIZE];
int i = 0;
for(i = 0; i< ARRAY_SIZE; i ++)
{
array[i] = i;
}
for(i = 0; i< ARRAY_SIZE; i ++)
{
printf("%d " ,array[i]);
}
printf("\n" );
return 0;
}
//linux 环境演示
gcc -D ARRAY_SIZE=10 programe.c
5 条件编译
比如说:
------------------------------条件编译的“条件”不可以是变量------------------------------------------------
因为条件编译中的条件在预处理阶段就已经处理了,而预处理阶段不处理变量
使用方法再举例
关系可以向C语言中的“if.....else”语句考虑
更多例子
6 文件包含
这个多次包含编译器是不会进行报错的,但是这个东西意味着程序将多次调用同一段代码
这显然是多余的,ok,看起来似乎这个多次包含同一文件的错误对于个人来讲很容易规避
但是如果是
下图这般
如何避免呢?
答:条件编译
下面这个放在第一行也具有相同作用
#pragma once//这个也是OK的
#include <filename.h> 和 #include "filename.h"有什么区别?
答:如果使用尖括号,那么程序将直接在系统头文件库寻找该文件
如果使用引号,那么程序将现在本地找一找,找不到才回去系统头文件库查找
从提升效率的角度讲,系统头文件调用时应该使用<>
而个人创建的头文件,应该使用“”
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。