2010-01-18 81 views

回答

0

这是一个非常封闭域定义在一个更可读的方式处理步骤偶尔有用:

void myfunc() { 
    DO_STEP_ONE; 
    THEN_ANOTHER_STEP; 
    KEEP_GOING; 
    LAST_STEP; 
} 

但通常它只是使代码难以阅读和理解。

除非它的值得你的代码读者详细了解这些#define的含义,而且它是某种捷径,你只是让人们在两个地方查看以了解一行代码(顶部文件和功能)而不是一个。

我很少使用这种方法。

+0

使用宏并不比使用具有相同名称的函数更具可读性 – user463035818 2017-07-21 16:40:53

0

这将取决于语言,编译器,等,等,等...

然而,没有什么不对的地方,一旦顾名思义这些指令之前发生编译过程。

预处理器删除其真正的价值都经常提到,所有的伪功能与适当的代码,等等...

0

所有的问题在计算机科学可以 另一个待解决 间接的水平

这是这些额外的间接水平:-)

的人说,在某些时候是功能需要另一种说法,或者你不需要要完全调用它,您可以更改#define一次,而不是更改函数被调用的所有位置。

用于开发,但危险保留在生产代码...我运行预处理器来取代规则,一旦我有一个成熟的代码,并知道我不需要改变它。

+0

如何设置太多的间接级别? ;) – daotoad 2010-01-18 20:30:55

5

缺点?通常,宏定义不会在可执行文件的符号表中结束。稍微难以调试。

5

的问题是,所述参数被重新=它们被用来每次计算:

#define MIN(A,B) ((A) < (B))?(A):(B); 

注意,我必须包装所有参数在“(”“)”,以确保表达corectly评估。但是如果我们这样做会发生什么?

int s = MIN(++current,Max); 

对此进行编码我期望在函数被调用之前将当前值增加一次。但由于它是在测试增加了一次宏观和第二时间,如果它仍然比最大

+0

虽然这确实是宏的缺点,但'gcc'提供了*编译器特定的*扩展来解决这个问题:'#define MIN(a,b)({typeof(a)_a =(a); typeof(b )_b =(b); _a <_b?_a:_b;})'。 – kennytm 2010-01-18 17:40:55

+0

@Kenny:你的Macro Foo比我的好。我试了一下,它的工作原理。虽然看起来不像,但我不认为一个声明(Block)可以作为一个右值。 – 2010-01-18 19:08:13

+0

@Kenny:不幸的是,如果在被命名为'_a'和'_b'的变量上调用了MIN,那么即使gcc的扩展也不能工作。 – jamesdlin 2010-01-18 19:49:59

2

有你能想到的几个问题:

  • 在C++中的宏没有命名空间和班级范围,所以到处都是一样的。一个例子就是不幸的min和max在windows.h中定义的地方。 如果你正在为windows编程并且包含windows.h并且想要编写std :: numeric_limits :: max(),那么max将被一些代码替换......这会在预处理器运行后留下不可编译的代码。 (好吧有办法关闭最小/最大宏在WINDOWS.H,但它仍然是设计不合理!)
  • 宏不能很好地调试。调试器将停止对宏用于未在宏内部的代码行...
  • 宏观参数的可能重新评估(你可以阻止这种由具有宏内部与局部变量的模块,但这样会使调试更糟!)
0

为什么你会在使用特定的预处理代码查找缺点是什么?自动将预处理器宏用于条件编译以外的任何其他应用程序(包括包含防护)。要问的正确问题是特定用途是否有优势。

预处理程序不尊重以任何方式范围或使用量。他们可以用意想不到的难以找到的方式搞砸完美的代码。除非你有充分的理由去使用它,否则一定要避免它们。

1

那么,如果你必须这样做(有时可能某些情况下),那么你至少应该定义宏的“功能类”这样的:

#define SOME_FUNCTION() someFunction(defaultArgument) 

否则你会写代码,当它实际上是一个函数调用时,它看起来像是一个常量赋值;即;

x = SOME_FUNCTION ; // hidden function call 

但你将不得不写一个“功能类”宏:

x = SOME_FUNCTION() ; // shorthand function-call with default argument 

哪个更好匹配的语言语法的预处理器语法。

一般函数宏,最好避免,但也有一些更阴险的是别人,这绝不是最坏的情况。然而,你可能很容易在C中编写函数包装,或者在C++中使用默认参数,在大多数情况下这将是更可取的。

0

缺点是你隐藏了代码。 好处是你隐藏了代码。

缺点通常outweights上行。

通常这个特定的方法是几乎无用的,除非通话看起来更像

someModule-> someStorage-> functionList [storage.getFunctionName] .pointer-> SomeFunction(...同样模糊的说法... );

这样做没有意义。如果只有参数是一个模糊的调用,则只能简写参数。如果它只是功能,则只是简写功能。如果这两个,你可能与

SOME_FUNCTION(SOME_ARGUMENT); 

更好,如果该功能不会与其他任何调用,您可以考虑从参数列表中删除,并在函数体中获得。如果这一对重复次数很多,可以考虑包装功能。

当你在一个宏的代码中犯了几个错误之后,你会发现它很难调试它们,并且你不会轻易地使用它们。

相关问题