本帖最后由 john_lee 于 2012-12-19 16:51 编辑
醉心369 发表于 2012-12-19 15:45
哪里有缺陷啊,正确的是什么啊
先来看一个例子:if (condition)
INTI_RECT_VALUE(ret[index].a, rect[index].b);
else
...
其中的 INTI_RECT_VALUE 宏是抄你的,else 后面的语句具体是什么无关紧要,重要的是有个 else。
这段程序编译会产生一个错误:error: 'else' without a previous 'if',这是 gcc 编译器的报错,其它编译器的报错可能稍有不同,但意思一样。
问题的根本,在于单条语句与复合语句的区别,单条语句要求以分号“;”结束,而复合语句则是由大括号“{}”包围,如果我们在复合语句结束的大括号之后加一个分号:{ a = 0; b = 0; }; // 注意最后的分号,它绝非无关紧要
我稍微把上面的语句变形一下,拆成两行:第1行是一个复合语句,而第2行的那个单独的分号,按C语法来说,是一个空语句,注意,它确实是一条语句。就是说在复合语句后加一个分号,实际上是两条语句。
在一般顺序执行的语句逻辑中,多一个几个空语句是无害的,但在条件分支语句(if)中,不允许有多条语句:if (condition)
statement1
else
statement2
如果在 if (condition) 后出现了两条语句,按语法来说,第2条语句就自动结束了 if 语句,如果其后再出现 else,编译器只能报错了。
解决这个问题的方法,有两个:
1、始终在 if 语句中加入大括号,这样可以保证只有一个复合语句在其中,这个方法要求编程者主动配合,而不是从语法层面堵死漏洞,显然不能让人满意。
2、把宏定义的复合语句变形为单条语句,使之完全符合语法要求,具体做法是,在原来定义的复合语句的前面(“{”之前),加一个“do”,在后面(“}”之后)加一个“while (0)”:#define INTI_RECT_VALUE(a, b) \
do { \
a = 0; \
b = 0; \
} while (0)
注意“while (0)”后面没有分号,在宏调用展开时,原来宏后面的那个空语句分号,将把“while (0)”后面的分号补上,使之成为一个单条语句,展开后的结果:if (condition)
do {
ret[index].a = 0;
ret[index].b = 0;
} while (0);
else
...
|