打印
[STM32F1]

求#define定义函数

[复制链接]
2222|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
d865841995|  楼主 | 2016-6-28 13:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看到别人的代码里这样写的。
#define DATA_OUT(data)        if(data&0x8000){LCD_D15_SET;}        else{LCD_D15_CLR;}\
                                                if(data&0x4000){LCD_D14_SET;}        else{LCD_D14_CLR;}

我想问下这样define之后调用和不define 写成一个函数再调用。会有什么区别。
有人说是节省时间,这个data是不确定的也能预编译?如何节省的时间。
大家说说这两种调用方式各自的特点!谢谢大家
沙发
fswyt| | 2016-6-28 13:28 | 只看该作者
减少时间是因为减少了函数跳转的次数,define定义的函数就相当于在调用处写了一个一模一样的函数,你应该理解下define的含义

使用特权

评论回复
板凳
d865841995|  楼主 | 2016-6-28 14:23 | 只看该作者
fswyt 发表于 2016-6-28 13:28
减少时间是因为减少了函数跳转的次数,define定义的函数就相当于在调用处写了一个一模一样的函数,你应该理 ...

可是代码中是define也用了,函数方式也写了。而且还说只用define会很占空内存。

使用特权

评论回复
地板
d865841995|  楼主 | 2016-6-28 14:24 | 只看该作者
fswyt 发表于 2016-6-28 13:28
减少时间是因为减少了函数跳转的次数,define定义的函数就相当于在调用处写了一个一模一样的函数,你应该理 ...

占内存..

使用特权

评论回复
5
d865841995|  楼主 | 2016-6-29 08:23 | 只看该作者
大家都来说说啊

使用特权

评论回复
6
ianhom| | 2016-6-29 09:58 | 只看该作者
本帖最后由 ianhom 于 2016-6-29 10:01 编辑

准确地说,用define 不是占内存,而是增加额外的rom,
宏定义会在预处理阶段,将宏定义部分全部替换为宏定义之后的内容,在你的例子里就全部替换成 if(data&0x8000){LCD_D15_SET;}        else{LCD_D15_CLR;}  if(data&0x4000){LCD_D14_SET;}        else{LCD_D14_CLR;},比如程序中有10个这样的DATA_OUT(data)宏,就会有10个if else if else嵌入到你的代码中,这样就增大了代码的在rom中的size

如果用函数的话,if else if else的代码只有一份,每次调用函数的时候,会跳转到这个唯一的一份代码中,所以这样总体的代码size 会小。

再回到你最初的问题
DATA_OUT(data)这里的data并不是不确定,宏定义仅仅做替换,所以int a; DATA_OUT(a);就会被替换为 if(a&0x8000).... else... if(a&0x4000)....else..... 预编译过程是合法的,在程序运行期间,a的值会直接被带入if..else...if....else中。

函数调用有一个固有的开销,就是函数调用的时候要进行压栈出栈的操作,索然不会体现在c的代码中,但是汇编的结果会增加少许代码,同时函数调用语句本身也需要一条汇编指令。如果函数体类只有一条语句,而且这个函数会被频繁调用,那不仅执行效率低(压栈出栈的操作),而且rom占用多(压栈出栈的代码)。所以对一些简短而频繁调用的函数块,一般采用的是宏定义(宏函数)的方式来实现,以优化运行效率和代码size

对宏函数也有几点注意:
1、宏函数中的参数不会进行类型检查,使用时需要自己注意;
2、在模块化编程中,各模块要求相互独立,内部的变量也不宜公开,比如某模块中的记录系统ms时钟的变量g_SystemTm,如果其他模块想获取这个时钟,有如下两种方法
     1)宏函数 #define GET_SYSTEM_TM()    g_SystemTm
     2 )标准函数封装   int Get_System_Tm() {return g_SystemTm;}
上面例子可以看出,函数体只有一个语句,按道理使用宏函数比较好。但如果使用了宏函数,g_SystemTm就必须是全局变量,这样一来关键变量就公开出来,比如意外写成了GET_SYSTEM_TM() = 0;那整个系统的时钟就被清0了,也不能防止其他模块意外操作同名变量;而使用函数封装的方式, g_SystemTm就可以用static来修饰,变量仅本模块可见。用函数的方式返回也使该变量变成了只读模式,不会被意外篡改。

使用特权

评论回复
评分
参与人数 1威望 +8 收起 理由
ocon + 8 赞一个!
7
xujinjiang| | 2016-6-29 10:11 | 只看该作者
只是方便查看,性能无任何变化!

使用特权

评论回复
8
datouyuan| | 2016-6-29 17:00 | 只看该作者
xujinjiang 发表于 2016-6-29 10:11
只是方便查看,性能无任何变化!

不对.
使用函数的过程:先保护现场->执行函数->恢复现场

使用定义不需要保护现场和恢复现场,当然快些.

这叫以空间换速度.

对一些很简单的,而使用又非常频繁的,采用定义的方法能大大提高速度.

使用特权

评论回复
9
Ryze| | 2016-6-29 22:06 | 只看该作者
宏定义会在预处理阶段,将宏定义部分全部替换为宏定义之后的内容

使用特权

评论回复
10
Thorald| | 2016-6-30 21:44 | 只看该作者
.define的“函数定义”

define可以像函数那样接受一些参数,如下

#define max(x,y) (x)>(y)?(x):(y);

这个定义就将返回两个数中较大的那个,看到了吗?因为这个“函数”没有类型检查,就好像一个函数模板似的,当然,它绝对没有模板那么安全就是了。可以作为一个简单的模板来使用而已。

但是这样做的话存在隐患,例子如下:
#define Add(a,b) a+b;
在一般使用的时候是没有问题的,但是如果遇到如:c * Add(a,b) * d的时候就会出现问题,代数式的本意是a+b然后去和c,d相乘,但是因为使用了define(它只是一个简单的替换),所以式子实际上变成了
c*a + b*d

另外举一个例子:
#define pin (int*);
pin a,b;
本意是a和b都是int型指针,但是实际上变成int* a,b;
a是int型指针,而b是int型变量。
这是应该使用typedef来代替define,这样a和b就都是int型指针了。

所以我们在定义的时候,养成一个良好的习惯,建议所有的层次都要加括号。

使用特权

评论回复
11
d865841995|  楼主 | 2016-7-1 10:52 | 只看该作者
ianhom 发表于 2016-6-29 09:58
准确地说,用define 不是占内存,而是增加额外的rom,
宏定义会在预处理阶段,将宏定义部分全部替换为宏定 ...

谢谢,这就是我想要的。这个函数调用的固有开销应该不大,我实际测试下看看需不需要这么做。

使用特权

评论回复
12
d865841995|  楼主 | 2016-7-1 10:53 | 只看该作者
datouyuan 发表于 2016-6-29 17:00
不对.
使用函数的过程:先保护现场->执行函数->恢复现场

空间换速度,这个说的好。

使用特权

评论回复
13
d865841995|  楼主 | 2016-7-1 10:58 | 只看该作者
Thorald 发表于 2016-6-30 21:44
.define的“函数定义”

define可以像函数那样接受一些参数,如下

谢谢,使用的时候我会注意的,例子很实用。

使用特权

评论回复
14
xzw118| | 2016-7-1 15:55 | 只看该作者
用宏可以优化代码,减少运行开销

使用特权

评论回复
15
lovecat2015| | 2016-7-1 20:38 | 只看该作者
用宏定义的话是预处理,不参与编译吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

293

帖子

6

粉丝