我想知道以这种方式使用预处理器的缺点:
#define SOME_FUNCTION someFunction(someArgument)
基本上我觉得这是错误的(或者当然不是最佳做法) - 但我不确定为什么......我的预处理技能充其量只是生锈。
答案 0 :(得分:5)
缺点?通常,宏定义不会在可执行文件的符号表中结束。调试稍微困难一些。
答案 1 :(得分:5)
问题是每次使用时都会重新评估参数:
#define MIN(A,B) ((A) < (B))?(A):(B);
请注意,我必须将所有参数包装在'('')'中,以确保表达式对corectly进行求值。但是,如果我们这样做会发生什么?
int s = MIN(++current,Max);
编码这个我希望在调用函数之前电流增加一次。但是因为它是一个宏,它在测试中增加一次,如果它仍然小于Max
,则第二次增加答案 2 :(得分:2)
您可以想到几个问题:
答案 3 :(得分:1)
如果你必须这样做(并且在某些情况下你可能),那么你至少应该将宏定义为“类似函数”:
#define SOME_FUNCTION() someFunction(defaultArgument)
否则,当它实际上是函数调用时,你会编写看起来像常量赋值的代码;即;
x = SOME_FUNCTION ; // hidden function call
但是使用“类似函数”的宏,您将不得不写:
x = SOME_FUNCTION() ; // shorthand function-call with default argument
哪个更好地匹配预处理器语法和语言语法。
一般来说,最好避免使用类似函数的宏,但有些宏比其他人更隐蔽,这绝不是最坏的情况。但是,您可能很容易在C中编写函数包装器,或者在C ++中使用默认参数,这在大多数情况下更为可取。
答案 4 :(得分:0)
这在一个非常封闭的领域中偶尔会用于以更易读的方式定义流程步骤:
void myfunc() {
DO_STEP_ONE;
THEN_ANOTHER_STEP;
KEEP_GOING;
LAST_STEP;
}
但通常只是让代码更难阅读和理解。
除非值得你的代码读者了解那些#define的详细含义,并且它是某种捷径,你只是让人们在两个地方看一下来理解一行代码(顶部文件和功能)而不是一个。
我很少使用这种方法。
答案 5 :(得分:0)
这取决于语言,编译器等等......
然而,它没有任何问题,一旦顾名思义那些指令就会发生,这是编译的过程。
预处理器通过其实际值删除所有常量引用,使用正确的代码删除所有伪函数,依此类推......
答案 6 :(得分:0)
计算机科学的所有问题都可以 另一个层次的解决方案 间接
这是额外的间接级别之一: - )
假设在某些时候该函数需要另一个参数,或者您根本不需要调用它,您可以更改#define
一次,而不是更改调用该函数的所有位置。
用于开发,但保留生产代码很危险...一旦我有一个成熟的代码并且知道我不需要更改它,我就会运行预处理器来替换该规则。
答案 7 :(得分:0)
为什么要在使用特定的预处理器代码时寻找缺点?对于除条件编译以外的任何事情(包括包含警卫),使用预处理器宏应该被自动视为坏。要问的正确问题是特定用途是否有优势。
预处理器宏不以任何方式尊重范围或用法。它们可能会以意想不到的,难以找到的方式搞砸完美的代码。除非你有充分的理由使用它,否则一定要避免它们。
答案 8 :(得分:0)
缺点是您隐藏了代码。 好处是你隐藏了代码。
下行通常会超过上行空间。
通常这种特殊的方法几乎没用,除非看起来更像是
someModule-&gt; someStorage-&gt; functionList [storage.getFunctionName] .pointer-&gt; SomeFunction(...同样模糊的参数......);
没有必要这样做。如果只有参数是一个模糊的调用,只需简写参数。如果它只是功能,则仅限速度功能。如果两者兼而有之,那么
可能会更好 SOME_FUNCTION(SOME_ARGUMENT);
如果从未使用其他任何东西调用该函数,您可以考虑将其从参数列表中删除并在函数体内获取。如果该对经常重复,在很小的变化中,您可以考虑包装函数。
在宏代码中犯了几个错误后,你会发现调试它们很痛苦,你不会轻率地使用它们。