宏定义

[复制链接]
3010|18
 楼主| 醉心369 发表于 2012-12-18 22:10 | 显示全部楼层 |阅读模式
图中的宏定义不十分太懂,请大侠们给说明一下。斜杆号是什么意思,for循环是宏定义里面的吗

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
john_lee 发表于 2012-12-18 23:09 | 显示全部楼层
那个所谓“正确的用法”也是不对(有缺陷)的。
ayb_ice 发表于 2012-12-19 07:58 | 显示全部楼层
本帖最后由 ayb_ice 于 2012-12-19 16:01 编辑

一行不够写,下一行接着写
ver军 发表于 2012-12-19 14:39 | 显示全部楼层
文本编辑时留下的,和代码本身没联系
coody 发表于 2012-12-19 15:04 | 显示全部楼层
分行写宏就是这样。宏最后一般不要加分号。
 楼主| 醉心369 发表于 2012-12-19 15:45 | 显示全部楼层
john_lee 发表于 2012-12-18 23:09
那个所谓“正确的用法”也是不对(有缺陷)的。

哪里有缺陷啊,正确的是什么啊
 楼主| 醉心369 发表于 2012-12-19 15:46 | 显示全部楼层
ayb_ice 发表于 2012-12-19 07:58
一行够写,下一行接着写

是一行不够写吧
ayb_ice 发表于 2012-12-19 16:01 | 显示全部楼层
醉心369 发表于 2012-12-19 15:46
是一行不够写吧

不好意思,笔误
lu50211 发表于 2012-12-19 16:14 | 显示全部楼层
什么情况!
lzqxs89 发表于 2012-12-19 16:34 | 显示全部楼层
john_lee 发表于 2012-12-18 23:09
那个所谓“正确的用法”也是不对(有缺陷)的。

希望版主能够解析下什么地方有缺陷。
lzqxs89 发表于 2012-12-19 16:35 | 显示全部楼层
john_lee 发表于 2012-12-18 23:09
那个所谓“正确的用法”也是不对(有缺陷)的。

是不是a、b的类型问题啊?
john_lee 发表于 2012-12-19 16:49 | 显示全部楼层
本帖最后由 john_lee 于 2012-12-19 16:51 编辑
醉心369 发表于 2012-12-19 15:45
哪里有缺陷啊,正确的是什么啊


先来看一个例子:
  1. if (condition)
  2.     INTI_RECT_VALUE(ret[index].a, rect[index].b);
  3. else
  4.     ...
其中的 INTI_RECT_VALUE 宏是抄你的,else 后面的语句具体是什么无关紧要,重要的是有个 else。
这段程序编译会产生一个错误:error: 'else' without a previous 'if',这是 gcc 编译器的报错,其它编译器的报错可能稍有不同,但意思一样。

问题的根本,在于单条语句复合语句的区别,单条语句要求以分号“;”结束,而复合语句则是由大括号“{}”包围,如果我们在复合语句结束的大括号之后加一个分号:
  1. { a = 0; b = 0; }; // 注意最后的分号,它绝非无关紧要
我稍微把上面的语句变形一下,拆成两行:
  1. { a = 0; b = 0; }
  2. ;
第1行是一个复合语句,而第2行的那个单独的分号,按C语法来说,是一个空语句,注意,它确实是一条语句。就是说在复合语句后加一个分号,实际上是两条语句
在一般顺序执行的语句逻辑中,多一个几个空语句是无害的,但在条件分支语句(if)中,不允许有多条语句:
  1. if (condition)
  2.     statement1
  3. else
  4.     statement2
如果在 if (condition) 后出现了两条语句,按语法来说,第2条语句就自动结束了 if 语句,如果其后再出现 else,编译器只能报错了。

解决这个问题的方法,有两个:
1、始终在 if 语句中加入大括号,这样可以保证只有一个复合语句在其中,这个方法要求编程者主动配合,而不是从语法层面堵死漏洞,显然不能让人满意。
2、把宏定义的复合语句变形为单条语句,使之完全符合语法要求,具体做法是,在原来定义的复合语句的前面(“{”之前),加一个“do”,在后面(“}”之后)加一个“while (0)”:
  1. #define INTI_RECT_VALUE(a, b)     \
  2.     do {                          \
  3.         a = 0;                    \
  4.         b = 0;                    \
  5.     } while (0)
注意“while (0)”后面没有分号,在宏调用展开时,原来宏后面的那个空语句分号,将把“while (0)”后面的分号补上,使之成为一个单条语句,展开后的结果:
  1. if (condition)
  2.     do {
  3.         ret[index].a = 0;
  4.         ret[index].b = 0;
  5.     } while (0);
  6. else
  7.     ...
bruceding 发表于 2012-12-19 17:07 | 显示全部楼层
续行符  楼上正解    其实用,运算符也不错 如下
#define INTI_RECT_VALUE(a, b)    a = 0, b = 0
  
jack821119 发表于 2012-12-19 17:10 | 显示全部楼层
其实也不用那么复杂,简单点就可以了.如下:
if (condition)

INTI_RECT_VALUE(ret[index].a, rect[index].b)

else
......


refee 发表于 2012-12-19 17:20 | 显示全部楼层
12楼解释得很好 很详细 :handshake
 楼主| 醉心369 发表于 2012-12-19 18:15 | 显示全部楼层
john_lee 发表于 2012-12-19 16:49
先来看一个例子:其中的 INTI_RECT_VALUE 宏是抄你的,else 后面的语句具体是什么无关紧要,重要的是有个 ...

版主,你讲的非常详细。13的宏定义是否可行?
john_lee 发表于 2012-12-19 18:55 | 显示全部楼层
13楼的宏定义方法,使用了逗号运算符,而逗号运算符的两边都要求是表达式,所以这种方法有个局限:只适合可以构成表达式的语句,例如 a = 0 和 b = 0 均是表达式,而其它非表达式的语句就无能为力了,比如 if for while 等语句。
john_lee 发表于 2012-12-19 19:04 | 显示全部楼层
14楼的方法不可取,因为这个宏看起来就像是一个单条语句,一般写程序都习惯地认为单条语句后就应该加分号结束,这种方法与习惯相左,你自己写自己用倒无所谓,怕的就是让别人来使用你的宏,还要让别人记住你这个宏的特殊性,显然会被吐槽的。

记住,规则定义要尽量统一且符合习惯用法。
 楼主| 醉心369 发表于 2012-12-19 22:00 | 显示全部楼层
学习了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

60

主题

283

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部