我是一个相当新的程序员,如果无法轻松获得此信息,我感到抱歉,我只是无法找到它。
这是我的问题:
当您使用文字数字访问数组的特定元素时,是否被视为幻数?
例如:
arrayOfNumbers[6] // Is six a magic number in this case?
我问这个问题是因为我的一位教授坚持认为程序中的所有立即数都是幻数。 对于我来说,仅使用实数访问数组的元素,而不是对每个元素使用命名常量,将是很好的。
谢谢!
#define ONE 1 ... i += ONE;
为了避免这种情况,上帝给了我们i ++:P
是。 6是一个幻数。始终最好避免在代码中使用幻数,例如:#define PI 3.1416,如果pi的值发生变化,则比在整个代码中使用3.1416更好。
@Mef:#define TWO 2 ... if (i % TWO) printf("i is odd
");。教授应该学会不要像这样过分归纳。"所有的文字数字都是魔幻数字"是作为教授的荒谬说法。
请不要在C ++中#define常量。请使用const。
@Fred:#define使其更具讽刺意味。
请不要使用ONE,TWO等作为常量名称,它不能解决任何问题,并且比在各处硬编码1、2更糟。如果两个完全不相关的常量的值为2,则使用TWO,需求的变化决定增加其中一个,该怎么办?尽管所有代码都可以查看哪个TWO实例相关。我看到了多达几百个常量的常量,两年后的代码仍然让我发笑。使用有意义的名称,例如NUM_OF_THINGS_IN_THING
当然,我们都知道42是唯一的实数。
@Mehrdad:是的。我只是想指出这一点,以便新手不要错过这个玩笑,并认为#define实际上是个好主意。
#定义一个1 void B1(); //销毁宇宙void BONE(); //给狗一个骨头int main(){BONE(); }
...以及PI的值多久更改一次?
@macbutch:那是个玩笑。我试图指出,诸如"所有魔术数字都不好"之类的笼统陈述通常是错误的。就是说,您仍然想在整个代码中使用PI而不是3.1416,因为它更具可读性。谁知道,pi的值可能会"更改"为3.141592656(即,您可能需要更高的精度)。天哪,我在开玩笑! :-)
#define NUM_OF_DIMENSIONS_IN_3D 3
如果程序中所有的文字数字都是"魔术数字"-为什么不将它们称为魔术而不是文字?在现实世界中,"一","二"和" PI"将被称为"清单常数"。数字本身从来没有神奇。仅结合某些系统设计,它们才具有优雅或神奇的特性(通常意味着使开发人员的生活更轻松)。
@Alok-不用担心;我也不是太认真...我完全同意在代码中使用PI比输入3.14159等更好:)
这确实取决于上下文。如果您有这样的代码:
arr[0] ="Long";
arr[1] ="sentence";
arr[2] ="as";
arr[3] ="array.";
...那么0..3不被视为幻数。但是,如果您有:
int doStuff()
{
return my_global_array[6];
}
...那么6绝对是一个魔数。
哦,好 那讲得通。
很神奇。
我的意思是,为什么要访问第六元素?该数字应采用什么语义?就目前而言,我们所知道的是"第六(从零开始)数字"。如果我们知道arrayOfNumbers的声明,我们将进一步了解其类型(例如int或double)。
但是如果你说:
arrayOfNumbers[kDistanceToSaturn];
...现在,对于阅读代码的人来说,它具有更多的意义。
通常,一个数组遍历一个数组,对每个元素执行一些操作,因为一个人不知道数组有多长,而且您不能仅仅以硬编码的方式访问它。
但是,有时数组元素具有特定的含义,例如在图形编程中。有时,数组总是大小相同,因为数据需要它(例如某些转换矩阵)。在这种情况下,按数字访问特定元素可能会或可能不会:领域专家会知道您在做什么,但通才可能不会。给魔术索引号起一个名字,对于那些必须维护您的代码的人来说更加明显,并有助于防止意外键入错误的代码。
在上面的示例中,我假设您的数组拥有从太阳到行星的距离。太阳将是第零个元素,因此arrayOfNumbers [kDistanceToSun] =0。然后,当您递增时,每个元素都包含与下一个最远的行星的距离:水银,金星等。这比仅键入行星的数字更具可读性。您想要的星球。在这种情况下,数组的大小是固定的,因为行星的数量是固定的(好吧,除了整个冥王星的崩溃)。
另一个问题是" arrayOfNumbers"没有告诉我们有关数组内容的任何信息。我们已经知道它是一个数字数组,因为我们在您说过int arrayOfNumers[12345];的地方看到了声明,或者无论如何声明了它。相反,类似:
int distanceToPlanetsFromSol[kNumberOfPlanets];
……使我们对数据的实际含义和语义有了更好的了解。作为程序员的目标之一就是编写以这种方式自我记录的代码。
然后我们可以在其他地方争论kNumberOfPlanets应该是8还是9。:)
好吧,这取决于您是否两次对火星进行计数。
您应该问自己为什么要进入那个特定职位。在这种情况下,我假设如果您正在执行arrayOfNumbers[6],则第六位置具有某些特殊含义。如果您认为这是什么意思,那么您可能会意识到这是一个隐藏它的神奇数字。
另一种查看方式:
如果程序偶然需要访问第7个元素而不是第6个元素怎么办?您或维护者如何知道?例如,如果第6个条目是CA中的树木数量,那么放个好东西
#define CA_STATE_ENTRY 6
然后,如果现在对该表重新排序,则可以看到有人需要将其更改为9(例如)。顺便说一句,我并不是说这是按状态维护树计数数组的最佳方法-可能不是。
同样,如果以后人们想要更改程序以处理俄勒冈州的树木,那么他们知道要替换
trees[CA_STATE_ENTRY]
同
trees[OR_STATE_ENTRY]
重点是
trees[6]
没有自我证明
当然对于c ++,它应该是一个枚举而不是#define
并非程序中的所有文字都真的可以称为"幻数"-但是,这个数字确实可以。 6告诉我们为什么要访问数组的特定元素。
要成为一个神奇的数字,即使在初次检查(或至少进行最少检查)时也要清楚其含义,为什么要使用该值。仅举例来说,许多代码将执行以下操作:&x[0]。在这种情况下,通常非常清楚," 0"实际上仅表示"数组的开始"。
您必须为有意义的答案提供更多的背景信息。不是所有的文字数字都是魔术,而是许多。在这样的情况下,虽然我能想到带有明确的数组索引>> 1的副手,但大多数情况下我都无法肯定地说,这可能算是魔术。
在符合MISRA的系统中,除0和1以外的所有值均被视为幻数。我的观点一直是,如果常数值很明显或可能不会改变,则将其保留为数字。如果有疑问,请创建一个唯一的常量,因为长期维护会更容易。
通常,并非所有软件中的常数值都称为幻数。
Java类文件始终以十六进制值0xcafebabe Windows .exe开头
MZ 0x4d,0x5a的文件,这使您可以快速(但不确定)来识别
二进制文件的内容。
这是教授的问题,他们通常过于学术化。从理论上讲,他像往常一样是正确的,但是通常在更严格的上下文中使用魔术数字,当数字嵌入到数据流中时,您就可以检测到该流的某些属性(例如,文件类型的签名标头) 。
另请参阅此Wikipedia条目。
然后,您应该使用命名常量,而不是幻数。
该死,你写的正是我要写的。+1。
如果您的程序正在做一些特别涉及数字6的非常特殊的事情,那么这并不是一个神奇的数字。你能提供一些背景吗?
如果您需要访问数组的特定元素,则可能是您做错了。
您几乎应该总是遍历整个数组。