libev源代码由于有各种宏定义,十分让人费解,作者这么写确实使得代码很简练,但也给读者的阅读带来了巨大的麻烦,下面将分析下ev_loop这个结构体的定义,加深对作者代码简化的理解,先上代码:

struct ev_loop
{
ev_tstamp ev_rt_now;
#define ev_rt_now ((loop)->ev_rt_now)
#define VAR(name,decl) decl;
#include "ev_vars.h"
#undef VAR
};
​

ev_loop是表示libev事件循环的结构体,我们看前两行就极其费解,首先定义了变量ev_tstamp ev_rt_now;其中,ev_tstamp为float的转义,这句没什么问题,即定义了一个float型变量ev_rt_now。然而作者紧接着就给来了一个相同的宏定义#define ev_rt_now ((loop)->ev_rt_now),what a fuck!初读感觉写这代码的人真的脑抽了,定义的宏和上一行定义的变量名一模一样!这不会有问题?然而代码跑起来依然是好好的。那么这么定义会带来什么样的结果呢?作者又为什么要这么玩?首先,我们要理解一下宏定义的作用域,先看一个非常简单的例子:

#include<iostream>
using namespace std;
int main()
{
int x=11;
cout<<x<<endl;
#define x 13
cout<<x<<endl;
return 0;
}
//输出结果:
//11
//13

这是一个非常简单的例子,两个输出结果分别是11和13,现在就比较容易理解了,C语言标准中宏定义的作用域是,从定义位置开始,到其当前所在作用域结束,也就是说在宏定义#define x 13之前我们定义了变量x,并初始化为11,在第一次cout的时候宏定义未出现,所以预编译阶段x并不会被替换成13,而仍然是变量x,随后由于加入宏定义#define x 13,后面所有的x都会被替换为常量13。理解了这些,那么就比较容易理解了ev_loop的结构了,ev_loop的定义在ev.c文件中,首先定义了float成员变量ev_rt_now,由于此时宏定义#define ev_rt_now ((loop)->ev_rt_now)在其后面,故预编译并不会替换变量ev_rt_now,也就是对于结构体定义本身来说其和代码

struct ev_loop
{
ev_tstamp ev_rt_now;
#define VAR(name,decl) decl;
#include "ev_vars.h"
#undef VAR
};
​

的效果是一样的,宏定义并不会成为结构体成员,也不会替换其前面的结构体变量ev_rt_now。而在此之后,ev_rt_now都会被替换为((loop)->ev_rt_now),那作者为什么要做这种替换呢,我们沿着ev.c的代码往下找,3097行可以找到如下代码:

ev_loop_new (unsigned int flags) EV_THROW
{EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));memset (EV_A, 0, sizeof (struct ev_loop));loop_init (EV_A_ flags);if (ev_backend (EV_A))return EV_A;ev_free (EV_A);return 0;
}

可以找到EV_P这个宏定义实际为 struct ev_loop *loop,而loop_init定义也在ev.c,其中部分代码如下:

loop_init (EV_P_ unsigned int flags) EV_THROW
{if (!backend){origflags = flags;#if EV_USE_REALTIMEif (!have_realtime){struct timespec ts;if (!clock_gettime (CLOCK_REALTIME, &ts))have_realtime = 1;}
#endif#if EV_USE_MONOTONICif (!have_monotonic){struct timespec ts;if (!clock_gettime (CLOCK_MONOTONIC, &ts))have_monotonic = 1;}
#endif/* pid check not overridable via env */
#ifndef _WIN32if (flags & EVFLAG_FORKCHECK)curpid = getpid ();
#endifif (!(flags & EVFLAG_NOENV)&& !enable_secure ()&& getenv ("LIBEV_FLAGS"))flags = atoi (getenv ("LIBEV_FLAGS"));ev_rt_now          = ev_time ();mn_now             = get_clock ();now_floor          = mn_now;rtmn_diff          = ev_rt_now - mn_now;

其中倒数第四行可以看到代码ev_rt_now = ev_time (),看到这里,差不多明白了。也就是对于新建一个事务结构体struct ev_loop的实例(ev_loop_new函数来实现),需要分配内存、初始化其成员变量并返回指向该内存的指针,代码中这个指针变量名为loop( struct ev_loop *loop),先分配内存(EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));),后续初始化其成员变量的话需要通过指针调用的方式来进行,若不加此宏定义,那么ev_rt_now = ev_time ()必须改为loop->ev_rt_now=ev_time (),显然就不如之前的代码看起来简洁(不过我还是要说,简洁是简洁了,读起来是真累啊,%>_<%)。ev_loop结构体其他变量的调用也是这么实现的,变量定义在#ev_vars.h中,#include "ev_vars.h"在结构体中,故这里定义了结构体的其他成员变量,定义完ev_loop结构体后,紧跟着的一行代码是

#include "ev_wrap.h"

er_wrap.h的内容如下:

#ifndef EV_WRAP_H
#define EV_WRAP_H
#define acquire_cb ((loop)->acquire_cb)
#define activecnt ((loop)->activecnt)
#define anfdmax ((loop)->anfdmax)
#define anfds ((loop)->anfds)
#define async_pending ((loop)->async_pending)
#define asynccnt ((loop)->asynccnt)
#define asyncmax ((loop)->asyncmax)
#define asyncs ((loop)->asyncs)
#define backend ((loop)->backend)
#define backend_fd ((loop)->backend_fd)
#define backend_mintime ((loop)->backend_mintime)
#define backend_modify ((loop)->backend_modify)
#define backend_poll ((loop)->backend_poll)
#define checkcnt ((loop)->checkcnt)
#define checkmax ((loop)->checkmax)
#define checks ((loop)->checks)
#define cleanupcnt ((loop)->cleanupcnt)
#define cleanupmax ((loop)->cleanupmax)
#define cleanups ((loop)->cleanups)
#define curpid ((loop)->curpid)
#define epoll_epermcnt ((loop)->epoll_epermcnt)
#define epoll_epermmax ((loop)->epoll_epermmax)
#define epoll_eperms ((loop)->epoll_eperms)
#define epoll_eventmax ((loop)->epoll_eventmax)
#define epoll_events ((loop)->epoll_events)
#define evpipe ((loop)->evpipe)
#define fdchangecnt ((loop)->fdchangecnt)
#define fdchangemax ((loop)->fdchangemax)
#define fdchanges ((loop)->fdchanges)
#define forkcnt ((loop)->forkcnt)
#define forkmax ((loop)->forkmax)
#define forks ((loop)->forks)
#define fs_2625 ((loop)->fs_2625)
#define fs_fd ((loop)->fs_fd)
#define fs_hash ((loop)->fs_hash)
#define fs_w ((loop)->fs_w)
#define idleall ((loop)->idleall)
#define idlecnt ((loop)->idlecnt)
#define idlemax ((loop)->idlemax)
#define idles ((loop)->idles)
#define invoke_cb ((loop)->invoke_cb)
#define io_blocktime ((loop)->io_blocktime)
#define iocp ((loop)->iocp)
#define kqueue_changecnt ((loop)->kqueue_changecnt)
#define kqueue_changemax ((loop)->kqueue_changemax)
#define kqueue_changes ((loop)->kqueue_changes)
#define kqueue_eventmax ((loop)->kqueue_eventmax)
#define kqueue_events ((loop)->kqueue_events)
#define kqueue_fd_pid ((loop)->kqueue_fd_pid)
#define loop_count ((loop)->loop_count)
#define loop_depth ((loop)->loop_depth)
#define loop_done ((loop)->loop_done)
#define mn_now ((loop)->mn_now)
#define now_floor ((loop)->now_floor)
#define origflags ((loop)->origflags)
#define pending_w ((loop)->pending_w)
#define pendingcnt ((loop)->pendingcnt)
#define pendingmax ((loop)->pendingmax)
#define pendingpri ((loop)->pendingpri)
#define pendings ((loop)->pendings)
#define periodiccnt ((loop)->periodiccnt)
#define periodicmax ((loop)->periodicmax)
#define periodics ((loop)->periodics)
#define pipe_w ((loop)->pipe_w)
#define pipe_write_skipped ((loop)->pipe_write_skipped)
#define pipe_write_wanted ((loop)->pipe_write_wanted)
#define pollcnt ((loop)->pollcnt)
#define pollidxmax ((loop)->pollidxmax)
#define pollidxs ((loop)->pollidxs)
#define pollmax ((loop)->pollmax)
#define polls ((loop)->polls)
#define port_eventmax ((loop)->port_eventmax)
#define port_events ((loop)->port_events)
#define postfork ((loop)->postfork)
#define preparecnt ((loop)->preparecnt)
#define preparemax ((loop)->preparemax)
#define prepares ((loop)->prepares)
#define release_cb ((loop)->release_cb)
#define rfeedcnt ((loop)->rfeedcnt)
#define rfeedmax ((loop)->rfeedmax)
#define rfeeds ((loop)->rfeeds)
#define rtmn_diff ((loop)->rtmn_diff)
#define sig_pending ((loop)->sig_pending)
#define sigfd ((loop)->sigfd)
#define sigfd_set ((loop)->sigfd_set)
#define sigfd_w ((loop)->sigfd_w)
#define timeout_blocktime ((loop)->timeout_blocktime)
#define timercnt ((loop)->timercnt)
#define timermax ((loop)->timermax)
#define timers ((loop)->timers)
#define userdata ((loop)->userdata)
#define vec_eo ((loop)->vec_eo)
#define vec_max ((loop)->vec_max)
#define vec_ri ((loop)->vec_ri)
#define vec_ro ((loop)->vec_ro)
#define vec_wi ((loop)->vec_wi)
#define vec_wo ((loop)->vec_wo)
#else
#undef EV_WRAP_H
#undef acquire_cb
#undef activecnt
#undef anfdmax
#undef anfds
#undef async_pending
#undef asynccnt
#undef asyncmax
#undef asyncs
#undef backend
#undef backend_fd
#undef backend_mintime
#undef backend_modify
#undef backend_poll
#undef checkcnt
#undef checkmax
#undef checks
#undef cleanupcnt
#undef cleanupmax
#undef cleanups
#undef curpid
#undef epoll_epermcnt
#undef epoll_epermmax
#undef epoll_eperms
#undef epoll_eventmax
#undef epoll_events
#undef evpipe
#undef fdchangecnt
#undef fdchangemax
#undef fdchanges
#undef forkcnt
#undef forkmax
#undef forks
#undef fs_2625
#undef fs_fd
#undef fs_hash
#undef fs_w
#undef idleall
#undef idlecnt
#undef idlemax
#undef idles
#undef invoke_cb
#undef io_blocktime
#undef iocp
#undef kqueue_changecnt
#undef kqueue_changemax
#undef kqueue_changes
#undef kqueue_eventmax
#undef kqueue_events
#undef kqueue_fd_pid
#undef loop_count
#undef loop_depth
#undef loop_done
#undef mn_now
#undef now_floor
#undef origflags
#undef pending_w
#undef pendingcnt
#undef pendingmax
#undef pendingpri
#undef pendings
#undef periodiccnt
#undef periodicmax
#undef periodics
#undef pipe_w
#undef pipe_write_skipped
#undef pipe_write_wanted
#undef pollcnt
#undef pollidxmax
#undef pollidxs
#undef pollmax
#undef polls
#undef port_eventmax
#undef port_events
#undef postfork
#undef preparecnt
#undef preparemax
#undef prepares
#undef release_cb
#undef rfeedcnt
#undef rfeedmax
#undef rfeeds
#undef rtmn_diff
#undef sig_pending
#undef sigfd
#undef sigfd_set
#undef sigfd_w
#undef timeout_blocktime
#undef timercnt
#undef timermax
#undef timers
#undef userdata
#undef vec_eo
#undef vec_max
#undef vec_ri
#undef vec_ro
#undef vec_wi
#undef vec_wo
#endif

显然套路都是一样的,先定义结构体中的变量,保证结构体内的变量不会被宏定义替换,后加宏定义保证后面代码的简洁性。

好啦,至此我们明白了整个ev_loop的结构,瞻仰下大神的精妙设计!但还是想奉劝一句,平时写代码最好不要这么玩,很容易出错的!!!很容易挨揍!!!

,

libev中ev_loop结构体中宏定义的理解相关推荐

  1. c语言中 定义结构体变量初始化,c++中的结构体:声明 定义 初始化

    什么是结构体? 之前的学习中我们知道了数组是一个容器,而且是存放固定大小数据的容器,而且存放的元素的数据类型必须要一致. 比如数据库中有这样的一条记录学号 性别 年龄 成绩 地址应该怎样存放 结构体: ...

  2. Source Insight4.0结构体使用宏定义之后,成员没关联?

    今天使用SI发现有BUG?还是就是没办法显示关联 例如: 此时没办法识别结构体指针GPIOB的成员 但如果直接把GPIOB定义为全局变量,类型为结构体指针就可以关联,如图: 但是我发现KEIL5中这种 ...

  3. c++结构体总结(结构体定义,结构体数组,结构体指针,结构体嵌套结构体,结构体做函数参数,结构体中 const使用场景)

    看完b站黑马程序员之后的借鉴和笔记 1.什么是结构体,有什么作用? 在C/C++中,结构体是用户定义的数据类型.它可以把几种不同类型的数据项集合成结构体这样一个单一类型. 2. 结构体定义和使用 #i ...

  4. Linux结构体变量报错,C语言中的结构体

    用户自己建立自己的结构体类型 1.  定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...

  5. C++中的结构体与类

    C++中继承了C语言中的结构体,但同时也在C语言的基础上新增了一个类(class)的概念,类可以说是C语言中结构体的升级版,这里主要细讲C++中的类 1.C++结构体 2.C++类 1.c语言结构体: ...

  6. Linux中的两个经典宏定义:获取结构体成员地址,根据成员地址获得结构体地址;Linux中双向链表的经典实现。...

    倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生.这两个宏最初是极客写出的,后来在Linux内核中被推广使用. 1. offse ...

  7. linux结构体数组的定义数组,task_struct结构体中的run_list和array域

    他们的定义分别是: struct list_head run_list; prio_array_t *array; 其中,想必struct list_head这个结构体大家很熟悉了 struct li ...

  8. 结构体中定义函数指针

    结构体指针变量的定义,定义结构体变量的一般形式如下: 形式1:先定义结构体类型,再定义变量 struct结构体标识符 { 成员变量列表;- }; struct 结构体标识符 *指针变量名; 变量初始化 ...

  9. 【C语言】宏offsetof的模拟实现 (计算结构体中某变量相对于首地址的偏移)

    首先我们应该特别留意 : offsetof 是一个宏,并非是一个函数 ! 宏offsetof的介绍 : 参数:第一个是结构体类型名称,第二个是结构体成员名 返回类型:size_t无符号整形 引用的头文 ...

最新文章

  1. 下载Google Play中的APK
  2. 高淇python讲义百度文库_python 面向对象01
  3. java菜单如何点解_【Java】详解菜单组件
  4. 创建使用模块与datetime模块使用
  5. 【报告分享】中国都市圈发展报告:城镇化白皮书5.0.pdf(附下载链接)
  6. Ajax用POST方式传中文到SERVLET中,接收时乱码
  7. 算法学习--链表/Hash--LRU cache
  8. NVIDIA Nsight Compute,Nsight Systems, Nsight Graphics,Nsight Deep Learning Designer简介-草稿
  9. 计算机中丢失无法开机密码,手把手教你“电脑开机密码忘记了,无法登录”的解决方法...
  10. 【Autoware自动驾驶-开源项目实践】大家快来入门体验啦
  11. MATLAB中拟合线性方程(最小二乘法)
  12. 把鸡蛋放到一个篮子里,然后看好你的篮子
  13. [译] 超快速的分析器(一):优化扫描器
  14. 数据分析真题日刷 | 网易2018校园招聘数据分析工程师笔试卷
  15. 页面5秒钟刷新一次(html,php)均可用
  16. 2018第二十二届软博会将于6月在京拉开帷幕
  17. Gradle学习之Android-DSL AppExtension篇
  18. pycharm(python)的注释
  19. SQL-常用SQL语句
  20. 坐标系转换-大地坐标转笛卡尔坐标系,笛卡尔坐标系转东北天坐标系

热门文章

  1. 中国人工智能学会公布首批会士名单,共计53名产业领军人物当选
  2. RHCE环境准备 | 介绍
  3. 立法保障交通权 日本交通政策基本法是如何制定的?
  4. 从游戏中学习产品设计2:消费篇
  5. 【Android】请求打开蓝牙和定位功能
  6. iOS的键盘种类(不同的键盘布局)
  7. ASCII码中不同字符分类、含义及相关技巧
  8. SecurityException: Uid 0312 does not have permission content://com.android.providers...
  9. MySQL之IN的优化
  10. springboot切面AOP拦截父类或接口中标记注解的方法