作者:孟岩 来源:CSDN博客   酷勤网收集 2007-12-09

摘要
  C语言宏定义中的一个奇技淫巧

CII Chap 04中,对于RETURN的宏定义是:

#define RETURN switch(Exception_stack = Exception_stack->prev, 0) default: return

放在如下的代码中:

TRY

    /* do something */

    if (failed)

      RETURN 1;

EXCETPT(Allocation_Failed)

    /* Handle allocation fail */

END_TRY

展开之后就是:(暂不考虑TRY的宏定义)

TRY

    /* ... */

    if (failed)

        switch(Exception_stack = Exception_stack->prev, 0)

        default:

            return 1;

EXCEPT(Allocation_Failed)

     ...

END_TRY

可以看到,这个宏的唯一目的,就是在return 1之前,执行Exception_stack = Exception_stack->prev语句。

仔细考虑之后可以发现,C语言中其他的结构都不能满足这一条件。如果使用
#define RETURN if(Exception_stack = Exception_stack->prev, 1) return

则在
if (...)
  RETURN 1;
else
  ...
语句中,会导致else的误匹配。

我想到的唯一一个功能相同的语言结构是:
#define RETURN (Exception_stack = Exception_stack->prev, 0) ((void)0) : return

评论

#   ai-fans 发表于2004-05-01 01:04:00  IP: 61.49.198.*
en, 真的很巧妙

#   XianChou 发表于2004-05-19 00:23:00  IP: 210.82.77.*
#define RETURN(_X) do{if(Exception_stack = Exception_stack->prev, 1) return _X}while(0)

#   傻强 发表于2004-05-31 09:54:00  IP: 61.178.108.*
为什么起这么个文章名

#   周星星 发表于2004-06-02 08:44:00  IP: 218.2.111.*
#define RETURN do( Exception_stack = Exception_stack->prev; return ) while(0)
行不行?

#   hanshuifang 发表于2004-06-15 17:44:00  IP: 218.108.42.*
i want to ask :

1. why define RETURN macro instead use code directly?

2. Where else should this macro define helpful?

and since i couldn't find out the answer to these two question, so i don't think this skill valuable!

#   无名 发表于2004-06-07 13:27:00  IP: 202.105.42.*
#define ACE_RETURN(Y) \
do { \
int __ace_error = ACE_Log_Msg::last_error_adapter (); \
ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
ace___->set (__FILE__, __LINE__, Y, __ace_error, ace___->restart (), \
ace___->msg_ostream (), ace___->msg_callback ()); \
return Y; \
} while (0)
回复:C语言宏定义中的一个奇技淫巧

#   myan 发表于2004-06-08 15:09:00  IP: 218.247.132.*
几位朋友的解决方案都不对。因为RETURN是要这样用的

func() {
TRY
//...
// ...
RETURN 10;
EXCEPT
// ...
END_TRY
}

#   周星星 发表于2004-06-09 12:13:00  IP: 218.2.111.*
佩服!

#   xjf 发表于2004-06-22 23:45:00  IP: 218.19.121.*
可以解析一下,最后一句是什么意思?
#define RETURN (Exception_stack = Exception_stack->prev, 0) ((void)0) : return

没看明白

#   ypapa 发表于2004-07-10 11:04:00  IP: 61.51.215.*
CII 是什么?机械工业出的《C语言接口与实现》?

#   刘未鹏 发表于2004-08-25 00:34:00  IP: 222.94.3.*
不知道这样可不可以呢:
#define RETURN return Exception_stack = Exception_stack->prev,

例如:
#define RETURN return i=0,

double f()
{
int i=0;
RETURN 0.99;
^^^^^^^^^
}
int main()
{
double i= f();
std::cout<<i; //outputs 0.99
system("pause");
}

#   perl-emacser 发表于2004-09-13 13:53:00  IP: 210.22.158.*
一种利用macro定义函数的常用方法是:
#define foo(_arg) \
{\
statement1;\
statement2;\
...
}while(0)

这个方法已被验证是可行的,可以添加任意多个语句,并且不会带来任何二义性。由于大家都这样用,这个定义也很容易理解,这已经是一种约定俗成的标准,而且linux内核里也是采用这个宏定义标准。它也并不是什么奇技淫巧!!!!!

#   赵老师 发表于2004-09-24 17:25:00  IP: 165.170.128.*
奇技淫巧=奇巧淫技
可是糍粑没有收录,我生怕自己写错了

#   lodge 发表于2004-10-14 05:00:00  IP: 61.183.79.*
#define RETURN switch(Exception_stack = Exception_stack->prev, 0) default: return

#define RETURN return Exception_stack = Exception_stack->prev,

#define RETURN(_X) do{if(Exception_stack = Exception_stack->prev, 1) return _X}while(0)

这三种都可以,不过前两种好一点,不带参数的,更方便。而第二种在只用RETURN ;这是有语法错误,总的来说第一种最好。

#   peanut 发表于2004-10-14 16:48:00  IP: 218.81.161.*
其实,尚有一种用for的方法(在我自己的实现里就是用for的,不知道那个编译出的代码更好一些),

#define RETURN \
for(Exception_stack = Exception_stack->prev; ;) return

当然,for的妙用还不至于此:)

#   agui 发表于2004-11-05 17:00:00  IP: 211.151.91.*
>#define RETURN switch(Exception_stack = Exception_stack->prev, 0) default: return
>#define RETURN return Exception_stack = Exception_stack->prev,
>#define RETURN(_X) do{if(Exception_stack = Exception_stack->prev, 1) return _X}while(0)
>这三种都可以,不过前两种好一点,不带参数的,更方便。而第二种在只用RETURN ;这是有语法错误,总的来说第一种最好。

第二种如果不带返回值,语法会错误。
第三种逼着人用括弧,跟 return 不象。

开始想不明白为什么要用 switch 语句,后来想他可能是要用在只有一个语句的地方。如:
if (xxxxx) RETURN y;

>#define RETURN (Exception_stack = Exception_stack->prev, 0) ((void)0) : return
冒号起什么作用啊?在C里好象冒号在标号(label)、case语句及:?中才有用,这里起什么作用呢?能编译通过吗?
这一句的前面部分看起来象是函数调用。编了一个程序试试发现通不过编译:
$ cat t.c
struct s { struct s* prev; } *Exception_stack;

#define RETURN (Exception_stack = Exception_stack->prev, 0) ((void)0) : return


void f()
{
RETURN;
}

int g()
{
RETURN 0;
}

编译信息:
$ gcc -c t.c
t.c: In function `f':
t.c:8: called object is not a function
t.c:8: parse error before `:'
t.c: In function `g':
t.c:13: called object is not a function
t.c:13: parse error before `:'

PS: 以前以为switch语句必须要有大括号,从这里看来,也可以不要(因为只有return一句?),受教。

#   nydgg 发表于2005-01-12 23:14:00  IP: 218.29.25.*
又想了几个:),不知能不能用

#define RETURN for (lhs=rhs; ; ) return

#define RETURN while (lhs=rhs, 1) return

文章里的好像没写对,修改一下
#define RETURN lhs=rhs, 0? ((void)0) : return

还有 ? : 的 if 式

#define RETURN if (lhs=rhs, 0) ((void)0); else return

#   nydgg 发表于2005-01-12 23:24:00  IP: 218.29.25.*
不好意思, ? : 式不能用。更正一下。

来自:http://blog.csdn.net/myan/archive/2004/04/27/542.aspx

分类: 编程语言 C/C++编程语言 修炼之道

上一篇:关于C++复杂性的零碎思考   下一篇:C++杂思录——风格的选择