Thinking In Redis
阅读redis源码时看到如下代码:
static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
((void)el); ((void)fd); ((void)mask);
redisAeEvents *e = (redisAeEvents*)privdata;
redisAsyncHandleRead(e->context);
}
发现redisAeReadEvent的三个变量 el, fd, mask 的使用上很特别: 函数体中均用void做了强制转换, 但是其他地方没有使用的. 就个人常识而言, 这种强制转换没有任何实现层面的意义, 为何redis的作者要如此为之.
百思不解, 于是决定将((void)el); ((void)fd); ((void)mask);
这段代码删了试试会发生什么:
src git:(dev) ✗ make
CC release.o
CC sentinel.o
sentinel.c:271:43: warning: unused parameter 'el' [-Wunused-parameter]
static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
^
sentinel.c:271:51: warning: unused parameter 'fd' [-Wunused-parameter]
static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
^
sentinel.c:271:75: warning: unused parameter 'mask' [-Wunused-parameter]
static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
编译器给出了警告, 说 el, fd, mask 三个变量没有使用过.
恍然大悟: 原来做'多此一举'的强制转换是为了消除编译器警告, 告诉编译器这些变量我用过了, 你就别给我发警告了.
通常redis中用UNUSED
宏来处理不使用的变量:
/*server.h: Anti-warning macro... */
#define UNUSED(V) ((void) V)
总结:
在c语言编程中类似的处理技巧还是很普遍的, 特别是在一些接口编程中, 函数签名是定义好的, 具体实现中可能有些变量用不上, 可以采用这种人为将无用变量强制转换为void的方式, 消除编译器警告.