C do{}while(0)-宏安全
我们知道,多行宏必须包含在do while(0)循环中,才能安全地包含在代码中的任何位置 例如,这是100%安全的:C do{}while(0)-宏安全,c,macros,scope,do-while,C,Macros,Scope,Do While,我们知道,多行宏必须包含在do while(0)循环中,才能安全地包含在代码中的任何位置 例如,这是100%安全的: #define swap( a , b ) \ do \ { \ int t = a ; \ a = b ; \ b = t ; \ }
#define swap( a , b ) \
do \
{ \
int t = a ; \
a = b ; \
b = t ; \
} \
while(0)
我想知道一个宏的一部分代码在循环之外是否也是安全的,如果不是,在什么情况下会出现问题
#define swap( a , b ) \
int t ; \ //should be in the same scope where the macro was called and before the loop
do \
{ \
t = a ; \
a = b ; \
b = t ; \
} \
while(0)
是否有一种安全的方法来实现这一点,如果它不安全,那么必须更改什么,或者我应该遵循什么规则。如果名为
t
的变量在该范围内的任何其他地方,那么编译就不安全。我可以想到两种情况。首先,如果当前作用域中已经有一个变量t
,那么在同一个作用域错误中将得到多个定义或冲突的定义。第二,考虑:
if (some_condition) swap(a,b);
将扩展到:
if (some_condition) int t;
do
{
t = a;
a = b;
b = t;
} while (0);
它在很多方面都不安全。首先,如果任何名为t的变量已经存在,它将不会编译 除此之外,您还必须注意以下事项:
if (...)
swap(a,b);
因为它将扩展到:
if (...)
int t;
do { ... } while(0);
请注意,if体将只是一个声明,因为if块没有大括号
为什么不在do块内声明t?因为您的实际目标是定义从makro外部访问的
t
,所以您应该在makro外部声明它。如果您的makro可以在一个代码块中多次使用(如您作为示例使用的交换
——您希望能够交换多个值),那么您将遇到多个t
声明的问题
相反,您可以像MFC一样使用并定义另一个makro使用为您的makro准备所有“全局”数据的\u SWAP
,并且在每个代码块中只能调用一次,在SWAP
的任何和所有出现之前(理想情况下在代码块的开头)。现在,您可以随时交换内容,并且仍然可以在一个makro中处理所需变量的声明
当然,问题仍然是,在
USES\u SWAP
中声明的t
将与其他t
冲突,但如果找不到其他方法,这可能是必要的。你应该试着去做;)为了减少这成为一个问题的可能性,您应该考虑一个更具体的名称,例如<代码> SavaPyt < /Cube >,甚至<代码> SavaPialAlpababLyt 。在普通代码中使用该名称声明变量的危险性很低。除了作用域之外,宏中还有第二个问题。您忘了在宏变量中加括号,这可能会产生一些意想不到的效果
#define swap( a , b ) \
do \
{ \
int t = a ; \
a = b ; \
b = t ; \
} \
while(0)
在C++中,如果用三进制:<代码>交换(x?x:y,z)< /> >调用宏,它会有一个惊喜效果。
do
{
int t = x?x:y;
x?x:y = z ;
z = t;
}
while(0)
由于三元的优先级低于矫揉造作,第二行将被解释为:
x?x:(y=z)代码>
因此,通常会有其他惊喜:
始终在宏参数周围加括号,始终强>
编辑:这是正确的定义
#define swap( a , b ) \
do \
{ \
int t = (a) ; \
(a) = (b) ; \
(b) = t ; \
} \
while(0)
我需要它在块外,然后将它包装在另一个do while块内,如下所示:do{int t;do{/*swap…*/}while(0);}while(0);我需要它在宏块之外:)啊好的。。。嗯,我想你必须接受这个,并坚持你原来的代码。是的,它会的。通常,您必须小心使用任何可以放置支架的说明(如果、虽然、for等)。但是如果你总是包含它们,应该不会有问题。if语句是唯一可能发生这种情况的地方吗?如果我在任何地方都使用If{}else{},那么我就不明白了?不,如果If
被替换为for
或while
,你也会遇到同样的问题。switch语句可能有问题。如果您试图将它与短路逻辑运算符|
或&&
一起使用,您会遇到问题。为什么要这样做?我的编译器不允许我以任何方式将三元运算符放入交换
宏中(需要左值)。我必须说我读过所有关于在宏变量周围加括号的内容,但从来没有读过关于宏参数的内容。你能提供一些信息(链接)吗?谢谢。可能会有误解,在#define
中,每次出现宏参数都应该放在括号中,不是在调用点。我没有找到一个例子来说明C中的问题,这就是为什么我在C++
中说,因为三元组与C中的优先级不同,并且允许它们作为lvalue
。这并不意味着不会有其他问题。