2016-12-30 159 views
8

我在看一个最小二乘法码,和我碰到下面的几行来:为什么使用静态“常量”而不是实际值?

static double one = 1.0; 
static double p1 = 0.1; 
static double p5 = 0.5; 
... 

,我想知道为什么会有人定义为static1.0。例如,我可以理解pi,但对于像1.00.1等那样的微不足道的数学数值?我认为它会使代码更不易读,但它可能还有一些我缺少的好处。

那么,是否有这些定义的原因?或者,如果它不与现代代码一起使用,那么对于旧编译器是否有任何理由?我知道我正在查看的代码已经从FORTRAN转换为C/C++。 FORTRAN中有这个原因吗?

+5

更糟糕的是,它们甚至不是'const' ...如果某人在某些API调用中需要指向/引用此数字的指针/引用,但在公式中直接使用它,这可能非常有用。 – Rames

+0

您发布的代码不使用'const'。 –

+0

我误解了这个问题......对不起人们。 – coderredoc

回答

3

不,这个常数很愚蠢。如果因为没有其他原因而不是,它实际上并不是常数

+0

你可以在这个主题上多加一点解释吗? – coderredoc

+2

你还需要更多解释吗?看,这就是为什么基于意见的帖子不允许在这里。我不应该真的回答! –

+0

不,这很好,你回答..它有帮助,但我只是问..静态变量不contant这是你说的对吗?它不是.. – coderredoc

5

使用

static double one = 1.0; 
static double p1 = 0.1; 
static double p5 = 0.5; 

没有多大意义的我。如果变量被赋予了更有意义的东西,那将是有意义的。我看到类似的值:

static double defaultCoefficient = 1.0; 
static double defaultRateOfIncrease = 0.1; 
static double defaultRatio = 0.5; 

在第二组中,使用代码中的变量比使用相应的常量更有意义。

使它们保持不变会更有意义。

static double const defaultCoefficient = 1.0; 
static double const defaultRateOfIncrease = 0.1; 
static double const defaultRatio = 0.5; 

I know that the code that I'm looking at was translated to C/C++ from FORTRAN.

如果翻译是由程序来完成,为什么变量命名为他们的方式是可以理解的。

如果翻译是由人完成的,他们可能会遵循一些关于如何快速移动内容的指导原则,并且不一定通过理解代码来创建有意义的变量名称。

+0

这很有道理,但在这段代码中,它是字面值'1.0',所以例如,当他们想要使用单位矩阵时,它们通过:'diag [i] = one;'来初始化它。 –

+5

这些仍应作为常量。 –

+5

'one'是100%傻,毫无疑问。但是公平起见,如果从一篇正在实施的科学论文中引用诸如变量* p1 *或* p5 *之类的名称,那么像'p1'和'p5'这样的名称就有意义。当然,如果他们代表“零点”1和“零点”5,他们就像“一”一样愚蠢。 – Angew

6

I know that the code that I'm looking at was translated to C/C++ from FORTRAN. Were there any reasons for this in FORTRAN?

FORTRAN对所有子程序参数使用传递引用。但是,与其他带有传递引用的语言不同,它仍然允许您传递“rvalues”作为参数。在幕后,FORTRAN编译器转换代码,如:

CALL SUBFOO(X + Y, 4) 

为如下代码

TEMP1 = X + Y 
TEMP2 = 4 
CALL SUBFOO(TEMP1, TEMP2) 

而这正是你的C++代码是这样做的:为了创建变量传递一个指针(或引用)转换为子程序FORTRAN风格。

当然,这不是惯用的C或C++。通常情况下,您会通过价值通过double

(代码示例从我的回答中复制到this question。)

+0

谢谢,那么通过定义'four = 4'然后使用'call sub(four)... call sub2(four)...'而不是使用文字'4.0'来获得性能提升?它仍然是这样吗?或者做新的编译器照顾这个? –

+2

这是我的假设,但显然这些变量的大多数用途实际上并不是函数参数。看起来他们只是机械地替换每一个文字,也许是因为它比专门针对功能参数更容易。另外,[Fortran参数关联并不完全按照引用传递](https://software.intel.com/zh-cn/blogs/2009/03/31/doctor-fortran-in-ive-come-here-for -an-参数);有一些奇怪的特殊情况。 – user2357112

+1

@ user2357112这是真的,除了一行:'temp = mp_dmax1(zero,one-temp * temp);'其余的不用作任何调用的参数,据我所见。 –

5

我曾经见过使用哈佛架构的一些(旧的,嵌入式)平台。

说我有一个(外部库)函数,它接受一个指针作为参数:

void Foo(double *Bar); 

如果我想要一个常数传递给这个函数我显然不能直接写。我必须像在开场白中那样做,所以我可以将one的地址作为例子。

Foo(&one); 

在一些哈佛平台const值放入程序ROM或闪存代替RAM,这样就无法正常工作,你会走的ROM地址,而不是所需的内存地址。

然后使它成为一个全局(静态)变量,以便在启动代码中初始化一次(从ROM复制到RAM一次的值),而不是在每次需要时将其变为自动变量。

我承认一个利基用例。

+0

C标准是否允许这样的内存模型?我知道它允许代码指针位于与数据指针不同的地址空间(对于某些x86-16内存模型是必需的),但是它可以不允许将非常量'T *'带到全局的'const T'对象,即使该对象从未被该指针修改过? – dan04

+0

@ dan04:找到了这个:https://www.securecoding.cert.org/confluence/display/c/EXP05-C.+Do+not+cast+away+a+const+qualification。似乎抛弃'const'就是UB。不应该没有演员编译(用'-pendantic-errors'在gcc上验证)。 – Unimportant

1

实际上有一个很好的理由来做到这一点,它涉及到软件开发过程本身。

比方说,你有一些调用函数的一些数字参数翻译单元,自然你会使其成为一个常数:

static const double epsilon = 1.e-3; 

尼斯,干净的代码。但是现在你意识到你设定的epsilon不是那么好,你需要一个更好的epsilon。你真的没有一个肯定的方式来确定它应该是什么,所以你去一些试验和错误:

static const double epsilon = 1.e-4; 

你重建你的程序。它仍然不好。如果再次更改它,则必须等待构建完成,并且在一些不重要的项目上可能需要一段时间。该怎么办?嗯,调试器让你改变变量的值,只要它们驻留在内存中(而不是像真正的常量一样被消除)。所以我们做以下操作:

static double epsilon = 1.e-4; 

现在我们在该文件的某处设置了一个断点。我们可以修改epsilon而无需每次重建我们的程序。我们最终节省宝贵的开发时间。我们立即找到合适的价值。

我们离开吧非const?不是。这是一个常量,因此我们在检查代码之前将它标记为const。将它保留为非const是一种代码异味。这没有更多的目的。

+0

尽管我为了调试的目的而喜欢变量与常量的关系,但我个人不喜欢将c语法转化为像原则一样的对象的意识形态。例如,我总是不喜欢他们通常教O.O.P的方式。在那里我应该想,“哦,狗是一个自然的物体......”然后继续进行反对的定向编程。对我来说,一个常量不会比编程语言中的函数具有更多的含义,并且它将如何影响该程序的执行。对我来说,我会使用一个常量来保存一个不会改变软件使用寿命的数据。 –

+0

@marshalcraft - *“将c语法转化为象原则一样的对象的思想”*我不确定我是否遵循。一个常数应该被指定为一个常量。 C++用'const'和C用宏来完成它。除了执行某种设计之外,没有任何意识形态。 – StoryTeller

+0

再次,我不会在语法声明修饰符和单词常量之间建立任何重要的联系。一个具有数学/物理意义,另一个涉及算法并且更加明确。 –

相关问题