2016-12-30 91 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

再次,我不會在語法聲明修飾符和單詞常量之間建立任何重要的聯繫。一個具有數學/物理意義,另一個涉及算法並且更加明確。 –

相關問題