雖然這樣做可能會很方便些,但是總感覺會不會對程序結構之類的造成不好的影響,總感覺好像沒有寫一個又返回值的函數好的樣子。

發編程經驗豐富的大家可以幫我分析一下這樣做的利弊嗎,我對編譯原理和一些變成上的習慣瞭解的不夠多,小白在這裡有點慌張。*_*


如果問題描述改成「使用全局變數是不是不太好?」,那麼答案是肯定的,而且你的分析也正確。你這樣描述的話,有點歧義,感覺是你都用了全局變數了,又不想在函數內修改,那你在哪裡修改?出了函數也沒其它地方了吧。就像是在問,作為一個正人君子,我娶了三妻四妾,然後跟她們住一起是不是不太好。。


修改全局變數不太好,那麼你的對策是不修改,還是把它變成非全局變數呢?不修改是不可能的吧?在面向事件編程的框架裏,事件響應函數肯定要修改全局變數的。有些人的習慣是把此類內容封裝到一個結構裏,叫做context,把它的指針傳送到每一個函數去。這樣架構師心理上會好受一些。但是當context足夠大足夠複雜、幾乎每個函數都需要它的時候,實際效果跟直接用全局變數也差不多,都是難以分析難以管理的。


函數中修改全局變數的行為是函數的副作用(side effect),帶副作用的函數是不純函數。與之對應的,對於相同的輸入,總返回相同的結果,不附帶其他效果的函數是純函數(pure function)。

不純函數不一定是不好的,在有些場合需要函數的副作用,如隨機數函數、輸入輸出等。但純函數有一些更好的性質,如降低代碼間的耦合;如調用可以直接以計算出的返回值代替的引用透明性(referential transparency)。

在某些編程語言(像Haskell),會極力的強調純函數,而對副作用則需要採取特殊的手段實現(monad),達到限制不純代碼的作用。

對於C語言,雖然編寫一個不純函數非常容易,但不純的代碼仍然可能帶來一些意想不到的問題。因此,盡量編寫純函數也應是一種好的風格。


工程實踐中,千萬不要教條。

在函數內修改全局變數的值這個行為,你要知道它有什麼好處,有什麼壞處,這樣才能針對具體情況分析得到結論。

函數內修改全局變數,壞處就是如果修改的地方多了,會在排查錯誤的時候比較痛苦,因為搞不清楚變數在什麼地方被錯誤修改。這就是所謂的耦合程度高了。好處就是這樣寫可能代碼會比較精簡,結構會比較清晰。

要不要在函數內修改全局變數,要不要把一個變數設置為全局變數,需要具體情況具體分析,才能得到結論。


坦率地講,不可教條主義。

全局變數,既然是變數,就可以修改,關鍵是文檔。我寫程序,主要是兩種方式修改全局變數。

其一,專門修改全局變數的函數。具體函數具體負責某一項修改;

其二、直接在函數中直接修改;

更多時候,我用第二種,第一種方式,條理清晰,但是教條主義。我很注重文檔,查閱文檔可以讓我知道,具體的全局變數都可以(允許)在哪些情況下被修改,修改它們的具體函數是哪個,還會不厭其煩的標註內次修改後的行號。

文檔很重要,不要嫌麻煩。好記性不如爛筆頭,記清楚幾月幾號幾點幾分修改了什麼,為什麼修改。日後,它就是你的系統圖紙,無需讀代碼,看文檔就知道當時是怎麼考慮的了。


你的直覺非常正確,這會對程序結構造成非常惡劣的影響。

一個函數,依賴哪些參數,應該從參數表裡面就能看出來;修改了哪些東西,也應該一目瞭然。

函數通常只有返回值,不應該改別的東西,如果一定要改,也要在函數名和參數列表裡面能看出來,比如function setUserName(user,newName)這樣的。


的確不太好。

函數很重要的作用就是隔離,封裝。所以有自己一套邏輯。全局變數在函數內被修改,很難說符合函數邏輯。稍微複雜的話,後期維護調試都會有很大問題,比如多個函數修改同一個全局變數。


粗淺的談一下,我也是初級的。函數主要表示的是一個行為,行為可以有結果也可以沒有結果,而在行為內對全局變數的修改我認為沒什麼關係,唯一可能的就是對函數的可重用性有點影響,這點也可以通過把全局變數當作參數傳進去進行修改來解決,總體來說我個人認為函數內修改全局變數很正常。


單片機編程時,可能只有全局變數


全局變數一旦初始化就不能修改了嗎?


你要考慮設計的話建議面向對象


在函數內修改全局變數說明你的全局變數是可變的,那麼多線程情況下的data race是容易出現的,因此在多線程下是不合適的。

但是在單線程程序下同樣不合適,Make your functions functional這篇文章提到了一個break function,個人覺得就是破壞了程序結構。有興趣可以看看上面鏈接的文章,這裡就不重複了。


弱弱的問一句,怎麼才能做到在函數以外修改全局變數呢?

全局變數本身設計就不太好


推薦閱讀:
相關文章