数组中的魔数?- C++

7
我是一名相对较新的程序员,如果这些信息很容易获取,我向大家道歉,我只是还没有找到它们。

这是我的问题:

当您使用字面数字访问数组的特定元素时,是否被认为是魔数?

例如:

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

我提出这个问题是因为我的一位教授坚信程序中所有的文字数字都是魔法数字。如果我可以直接使用实数访问数组元素,而不是为每个元素使用命名常量,那就太好了。
谢谢!

2
为了避免这种情况,上帝给我们 i++ :P - Leo
5
@Mef: #define TWO 2 ... if (i % TWO) printf("i is odd\n");. 教授们应该学会不要过于笼统地概括。像“所有的字面数字都是神奇数字”这样的说法对于一位教授来说是荒谬的。 - Mehrdad Afshari
12
请勿在C++中使用#define来定义常量,而应该使用const关键字。 - Fred Larson
3
当然,我们都知道42是唯一的“真正”的魔数。 - Wim
1
@Mehrdad:确实。我只是想指出这一点,以便新手不会错过这个笑话并认为#define实际上是一个好主意。 - Fred Larson
显示剩余10条评论
11个回答

22

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

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

...那么0到3就不被视为魔数。但是,如果您有:

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

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


6

这真是神奇。

我的意思是,为什么您要访问第6个元素?应该应用于该数字的语义是什么?现在我们所知道的只有“第六个(从零开始计数的)数字”。如果我们知道 arrayOfNumbers 的声明,我们将进一步了解其类型(例如 int double )。

但如果您说:

arrayOfNumbers[kDistanceToSaturn]; 

现在,对于阅读代码的人来说,它有了更多的含义。

通常情况下,我们会遍历一个数组,在每个元素上执行某些操作,因为我们不知道这个数组的长度,也不能以硬编码的方式访问它。

然而,有时候数组元素具有特定的含义,例如在图形编程中。有时候数组的大小总是相同的,因为数据需要(例如某些变换矩阵)。在这些情况下,按编号访问特定元素可能是可以接受的,也可能不可以:领域专家会知道你在做什么,但一般人可能不会。给神奇的索引号取个名字,可以让那些需要维护你的代码的人更容易理解,也可以帮助你防止意外输入错误的编号。

在我上面的例子中,我假设你的数组保存了从太阳到行星的距离。太阳将是第零个元素,因此arrayOfNumbers[kDistanceToSun] = 0。然后,随着增量的增加,每个元素都包含到下一个最远行星的距离:水星、金星等等。这比只键入您想要的行星的数字要容易阅读得多。在这种情况下,数组的大小是固定的,因为行星的数量是固定的(当然,除了整个冥王星事件)。

另一个问题是,"arrayOfNumbers"并没有告诉我们数组的内容。我们已经知道它是一个数字数组,因为我们在某个地方看到了声明,其中你写道int arrayOfNumers[12345];或者你以其他方式声明了它。相反,可以使用类似于:

int distanceToPlanetsFromSol[kNumberOfPlanets];

这样做可以更好地了解数据的实际含义和语义。作为程序员,你的目标之一应该是编写具有自我记录功能的代码。

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


这取决于您是否计算了两次火星。 - Thomas Eding

5

你应该问自己为什么要访问那个特定的位置。在这种情况下,我假设如果你正在执行arrayOfNumbers[6],第六个位置具有某种特殊含义。如果你想知道这个含义,你可能会意识到它是隐藏的一个魔术数字。


2

从另一个角度来看:

如果程序需要访问第七个元素而不是第六个元素,你或维护者如何知道呢?例如,如果第六个条目是加利福尼亚州的树木数量,那么将其放置在正确的位置将是一件好事。

 #define CA_STATE_ENTRY 6

如果现在表格被重新排序,有人会发现他们需要将这个改为9(比如说)。顺便说一下,我并不是说这是维护按州计算树木数量数组的最佳方法 - 这可能不是最好的方法。

同样地,如果以后有人想要更改程序以处理俄勒冈州的树木,那么他们就知道要替换掉

 trees[CA_STATE_ENTRY]

使用

 trees[OR_STATE_ENTRY]

重点是:
 trees[6]

不是自我记录的

当然,对于C++而言,应该使用枚举而不是#define。


1
你需要提供更多的上下文才能得到有意义的答案。并不是所有的字面数字都是神奇的,但很多确实是。在这种情况下,无法确定是否神奇,虽然我能想到的大多数情况下,显式数组索引 >>1 可能都算是神奇的。

1

并非程序中的所有文字都被认为是“魔数”——但这个确实看起来像是。 6 并没有给我们任何线索,说明为什么要访问数组的特定元素。

如果不想成为魔数,你需要在第一次检查(或至少最小检查)时就清楚地知道其含义,以便了解为什么使用该值。例如,很多代码会执行以下操作:&x[0]。在这种情况下,通常很清楚 '0' 实际上只是表示“数组的开头”。


0

如果你需要访问数组中的特定元素,很可能你的方法是错误的。

你几乎总是应该迭代整个数组。


0

如果你的程序涉及到特定的数字六,那么它就不是一个神奇数字了。你能提供一些上下文吗?


0

这就是教授的问题,他们通常过于学术化。从理论上讲,他通常是正确的,但通常情况下,魔数是在更严格的上下文中使用的,当数字嵌入到数据流中时,允许您检测流的某些属性(例如文件类型的签名头)。 另请参见此维基百科条目


你写的正是我要写的。加一。 - the_drow

0
通常软件中并不是所有的常量值都被称为魔数。 Java类文件始终以十六进制值0xcafebabe开头,Windows .exe文件则以MZ 0x4d、0x5a开头,这样可以快速(但不一定准确)地识别二进制文件的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接