我想知道有什么缺点都以这样的方式使用预处理的:使用预处理器定义函数调用的缺点是什么?
#define SOME_FUNCTION someFunction(someArgument)
基本上,我觉得这是不对的(否则肯定不是最佳做法) - 但我不知道为什么...我的预处理器技能最好是生锈的。
我想知道有什么缺点都以这样的方式使用预处理的:使用预处理器定义函数调用的缺点是什么?
#define SOME_FUNCTION someFunction(someArgument)
基本上,我觉得这是不对的(否则肯定不是最佳做法) - 但我不知道为什么...我的预处理器技能最好是生锈的。
这是一个非常封闭域定义在一个更可读的方式处理步骤偶尔有用:
void myfunc() {
DO_STEP_ONE;
THEN_ANOTHER_STEP;
KEEP_GOING;
LAST_STEP;
}
但通常它只是使代码难以阅读和理解。
除非它的值得你的代码读者详细了解这些#define的含义,而且它是某种捷径,你只是让人们在两个地方查看以了解一行代码(顶部文件和功能)而不是一个。
我很少使用这种方法。
这将取决于语言,编译器,等,等,等...
然而,没有什么不对的地方,一旦顾名思义这些指令之前发生编译过程。
预处理器删除其真正的价值都经常提到,所有的伪功能与适当的代码,等等...
所有的问题在计算机科学可以 另一个待解决 间接的水平
这是这些额外的间接水平:-)
的人说,在某些时候是功能需要另一种说法,或者你不需要要完全调用它,您可以更改#define
一次,而不是更改函数被调用的所有位置。
用于开发,但危险保留在生产代码...我运行预处理器来取代规则,一旦我有一个成熟的代码,并知道我不需要改变它。
如何设置太多的间接级别? ;) – daotoad 2010-01-18 20:30:55
缺点?通常,宏定义不会在可执行文件的符号表中结束。稍微难以调试。
的问题是,所述参数被重新=它们被用来每次计算:
#define MIN(A,B) ((A) < (B))?(A):(B);
注意,我必须包装所有参数在“(”“)”,以确保表达corectly评估。但是如果我们这样做会发生什么?
int s = MIN(++current,Max);
对此进行编码我期望在函数被调用之前将当前值增加一次。但由于它是在测试增加了一次宏观和第二时间,如果它仍然比最大
小虽然这确实是宏的缺点,但'gcc'提供了*编译器特定的*扩展来解决这个问题:'#define MIN(a,b)({typeof(a)_a =(a); typeof(b )_b =(b); _a <_b?_a:_b;})'。 – kennytm 2010-01-18 17:40:55
@Kenny:你的Macro Foo比我的好。我试了一下,它的工作原理。虽然看起来不像,但我不认为一个声明(Block)可以作为一个右值。 – 2010-01-18 19:08:13
@Kenny:不幸的是,如果在被命名为'_a'和'_b'的变量上调用了MIN,那么即使gcc的扩展也不能工作。 – jamesdlin 2010-01-18 19:49:59
有你能想到的几个问题:
为什么你会在使用特定的预处理代码查找缺点是什么?自动将预处理器宏用于条件编译以外的任何其他应用程序(包括包含防护)。要问的正确问题是特定用途是否有优势。
预处理程序不尊重以任何方式范围或使用量。他们可以用意想不到的难以找到的方式搞砸完美的代码。除非你有充分的理由去使用它,否则一定要避免它们。
那么,如果你必须这样做(有时可能某些情况下),那么你至少应该定义宏的“功能类”这样的:
#define SOME_FUNCTION() someFunction(defaultArgument)
否则你会写代码,当它实际上是一个函数调用时,它看起来像是一个常量赋值;即;
x = SOME_FUNCTION ; // hidden function call
但你将不得不写一个“功能类”宏:
x = SOME_FUNCTION() ; // shorthand function-call with default argument
哪个更好匹配的语言语法的预处理器语法。
一般函数宏,最好避免,但也有一些更阴险的是别人,这绝不是最坏的情况。然而,你可能很容易在C中编写函数包装,或者在C++中使用默认参数,在大多数情况下这将是更可取的。
缺点是你隐藏了代码。 好处是你隐藏了代码。
缺点通常outweights上行。
通常这个特定的方法是几乎无用的,除非通话看起来更像
someModule-> someStorage-> functionList [storage.getFunctionName] .pointer-> SomeFunction(...同样模糊的说法... );
这样做没有意义。如果只有参数是一个模糊的调用,则只能简写参数。如果它只是功能,则只是简写功能。如果这两个,你可能与
SOME_FUNCTION(SOME_ARGUMENT);
更好,如果该功能不会与其他任何调用,您可以考虑从参数列表中删除,并在函数体中获得。如果这一对重复次数很多,可以考虑包装功能。
当你在一个宏的代码中犯了几个错误之后,你会发现它很难调试它们,并且你不会轻易地使用它们。
使用宏并不比使用具有相同名称的函数更具可读性 – user463035818 2017-07-21 16:40:53