7

I'm a fairly new programmer, and I apologize if this information is easily available out there, I just haven't been able to find it yet.

Here's my question:

Is is considered magic numbers when you use a literal number to access a specific element of an array?

For example:

arrayOfNumbers[6] // Is six a magic number in this case?

I ask this question because one of my professors is adamant that all literal numbers in a program are magic numbers. It would be nice for me just to access an element of an array using a real number, instead of using a named constant for each element.

Thanks!

4

11 回答 11

22

这真的取决于上下文。如果你有这样的代码:

arr[0] = "Long";
arr[1] = "sentence";
arr[2] = "as";
arr[3] = "array.";

...然后 0..3 不被视为幻数。但是,如果您有:

int doStuff() 
{
   return my_global_array[6];
}

...那么 6 绝对是一个神奇的数字。

于 2010-01-18T21:48:21.710 回答
6

这很神奇。

我的意思是,你为什么要访问第 6 个元素?应该应用于该数字的语义是什么?就目前而言,我们所知道的是“第 6 个(从零开始的)数字”。如果我们知道 的声明,arrayOfNumbers我们将进一步知道它的类型(例如 anint或 a double)。

但如果你说:

arrayOfNumbers[kDistanceToSaturn]; 

...现在它对阅读代码的人具有更多意义。

一般来说,一个数组遍历一个数组,对每个元素执行一些操作,因为不知道数组有多长,你不能只以硬编码的方式访问它。

但是,有时数组元素具有特定含义,例如在图形编程中。有时数组总是相同的大小,因为数据需要它(例如某些变换矩阵)。在这些情况下,通过数字访问特定元素可能会也可能不会:领域专家会知道您在做什么,但通才可能不会。给神奇的索引号起个名字会让那些必须维护你的代码的人更清楚,并帮助你防止意外输入错误的数字。

在上面的示例中,我假设您的阵列保持从太阳到行星的距离。太阳将是第零个元素,因此 arrayOfNumbers[kDistanceToSun] = 0。然后随着您的增加,每个元素都包含到下一个最远行星的距离:水星、金星等。这比仅仅输入数字更具可读性你想要的星球。在这种情况下,数组的大小是固定的,因为有固定数量的行星(嗯,除了整个冥王星的崩溃)。

另一个问题是“arrayOfNumbers”没有告诉我们数组的内容。我们已经知道它是一个数字数组,因为我们在您所说的地方int arrayOfNumers[12345];或您声明它的地方看到了声明。相反,类似:

int distanceToPlanetsFromSol[kNumberOfPlanets];

...让我们更好地了解数据实际上是什么以及它的语义是什么。作为程序员,您的目标之一应该是以这种方式编写自记录的代码。

然后我们可以在其他地方争论kNumberOfPlanets应该是 8 还是 9。:)

于 2010-01-18T21:47:09.183 回答
5

您应该问自己为什么要访问该特定职位。在这种情况下,我假设如果你在做arrayOfNumbers[6]第六个位置有一些特殊的意义。如果您认为这是什么意思,您可能会意识到这是一个隐藏它的神奇数字。

于 2010-01-18T21:46:26.953 回答
2

another way to look at it:

What if after some chance the program needs to access 7th element instead of 6th? HOw would you or a maintainer know that? If for example if the 6th entry is the count of trees in CA it would be a good thing to put

 #define CA_STATE_ENTRY 6

Then if now the table is reordered somebody can see that they need to change this to 9 (say). BTW I am not saying this is the best way to maintain an array for tree counts by state - it probably isnt.

Likewise, if later people want to change the program to deal with trees in oregon, then they know to replace

 trees[CA_STATE_ENTRY]

with

 trees[OR_STATE_ENTRY]

The point is

 trees[6]

is not self-documenting

Of course for c++ it should be an enum not a #define

于 2010-01-18T22:02:15.610 回答
1

您必须为有意义的答案提供更多上下文。并不是所有的字面数字都是神奇的,但很多都是。在这种情况下,根本无法确定,尽管大多数情况下我可以想到带有显式数组索引 >>1 的副手可能符合魔术。

于 2010-01-18T21:47:25.827 回答
1

并非程序中的所有文字都真正符合“幻数”的要求——但这似乎确实如此。这6让我们不知道为什么要访问数组的特定元素。

要不是一个神奇的数字,即使在第一次检查(或至少最小检查)时,您需要非常清楚它的含义,为什么要使用该值。举个例子,很多代码会做这样的事情:&x[0]. 在这种情况下,通常很清楚“0”实际上只是表示“数组的开头”。

于 2010-01-18T21:50:24.603 回答
0

如果您需要访问数组的特定元素,那么您可能做错了。

您应该几乎总是遍历整个数组。

于 2010-01-18T21:47:01.230 回答
0

如果您的程序正在做一些特别涉及数字 6 的非常特殊的事情,那么它就不是一个神奇的数字。你能提供一些背景吗?

于 2010-01-18T21:47:15.007 回答
0

这就是教授的问题,他们往往过于学术。理论上他是对的,像往常一样,但通常在更严格的上下文中使用幻数,当数字嵌入数据流中时,允许您检测流的某些属性(例如文件类型的签名标头) . 另请参阅此 Wikipedia 条目

于 2010-01-18T21:47:55.077 回答
0

通常,并非软件中的所有常量值都称为幻数。java 类文件总是以十六进制值 0xcafebabe 开头,一个带有 MZ 0x4d, 0x5a 的 windows .exe 文件,这使您可以快速(但不确定)识别二进制文件的内容。

于 2010-01-18T21:56:01.677 回答
0

在符合 MISRA 的系统中,除 0 和 1 之外的所有值都被视为幻数。我的观点一直是,如果常数值很明显或可能不会改变,那么将其保留为数字。如果有疑问,请创建一个独特的常量,因为长期维护会更容易。

于 2010-01-18T22:49:52.413 回答