为什么我们从程序中避免使用Magic Numbers或Constants并使用宏?

时间:2011-10-31 12:15:05

标签: c

这里的C编程指南和编码标准说我们必须避免程序中的幻数和使用宏来表示幻数

在宏中,与常量相比,评估需要更多时间,因此在幻数或常数中表现更好。

例如

for(i=0;i<255;i++)
{

} 

我们使用这个

#define MAX 255

for(i=0;i<MAX;i++)
{

}

第二个比第一个花费更多的时间,所以为什么我们更喜欢按照编码标准选择第二个。

7 个答案:

答案 0 :(得分:4)

使用宏常量不需要更多时间。 #define是一个preprocessor指令,所以在二进制代码中,这两段代码将编译为同一个东西!

但是,出于maintainability的原因,我们避免使用“幻数”,假设您有许多相同大小的循环和数组,如果将来这个大小发生变化,您将需要搜索代码并更改它到处都是,[只有它!]如果你使用预处理器命令,你只需要改变它[预处理器命令]。

答案 1 :(得分:2)

这是关于主要因素,而不是表现。每次为同一目的复制两次相同的数字时,它应该是变量,宏或const。阅读DRY;重复的代码或值会大大增加未来错误的可能性。

我相信宏在编译时扩展,而不是运行时,因此根本没有性能。即使使用const,也没有可衡量的差异 - 我相信不到一个周期。

同时查找过早优化。

答案 2 :(得分:1)

第二个是优选的,因为它在读取循环时给出了意义。对于有人进来并维护你在第一个例子中写的代码,显而易见的问题是“为什么255”?这是什么意思,如果我修改它将会发生什么?给这个值起一个名字要清楚得多,并且#define它。如果在整个程序中使用相同的数字,则只需在一个地方进行修改。

至于这样做的成本,它很小。在编译时,MAX的所有实例都将替换为255.在运行时,没有成本。

答案 3 :(得分:0)

两段代码都将被编译为同一件事。当预处理器运行时,MAX的实例被替换为255,因此编译器正在使用完全相同的代码。

使用#define或常量的好处是,如果在多个地方使用该值并且由于某种原因必须进行链接,则更改#define而不是查找所有地点是微不足道的正在使用该值并更改它们。

答案 4 :(得分:0)

  • 它记录了代码(一个有意义的常量名称让读者知道为什么255而不是254,数字是什么意思)
  • 当多次使用号码时,它有助于避免在一个地方更改它而在另一个地方忘记更改的错误
  • 它根本不慢(顺便说一下)

答案 5 :(得分:0)

编译C程序时,程序首先由C预处理程序处理。它处理程序中的所有#foo内容并替换宏。当实际编译器看到代码时,您的宏已被替换为值。

因此,如果您将第二个代码段提供给编译器,实际 C编译器将看到与您的第一个代码段完全相同的内容。这意味着使用宏而不是值不会减慢您的程序。

使用宏(或常量)的想法是为你的数字命名,这对人类来说是有意义的。

考虑你的程序支持三辆自行车(或其他什么,无关紧要)。您需要在很多地方编写3(就像您在for循环中写了255)。但一个月之后,当你看到它时,你可能不再记得3的含义了。如果您改为:

#define MAX_BICYCLES 3

然后在任何地方使用MAX_BICYCLES意图变得更加清晰。更好的是,一旦你的应用程序应该支持,比如5辆自行车,它可能就像改变一个宏一样简单。您无需记住将3更改为5的位置。

答案 6 :(得分:0)

如果有数字变化或数字完全错误你怎么知道? 而不是魔术数字使用真实的名称,这意味着什么  您可以使用#define或常量或枚举作为名称  哪一个是设计选择。
 例如:

 #define   PRESIDENT_WENT_CRAZY  (22)
const int WE_GOOFED= 19;
enum  {
  THEY_DIDNT_PAY= 16
};

if      (PRESIDENT_WENT_CRAZY == foo) { start_thermo_nuclear_war(); }
else if (WE_GOOFED            == foo) { refund_lotso_money(); }
else if (THEY_DIDNT_PAY       == foo) { infinite_loop(); }
else                                  { happy_days_i_know_why_im_here(); }

现在不是更好吗?  const和enum选项是首选,因为调试时调试器有足够的信息来显示值和标签。