2009-06-11 89 views
0

我最近在辦公室參加的編碼風格演示文稿提出,變量在定義時不應分配(默認值)。相反,它們應該在使用之前被分配一個默認值。 所以,像同時定義和分配的變量

應該皺起了眉頭。

顯然,「INT」的例子是簡單的,但相同的如下的其它類型也一樣指針等

此外,也有人提到,C99兼容的編譯器現在嘔吐提到在上述警告案件。

上述方法對我來說只對結構有用,即只在使用前將它們memset。如果僅在錯誤分支中使用(或填充)結構,這將是有效的。

對於所有其他情況,我發現定義和我也遇到了很多,因爲未初始化指針錯誤的分配到默認值的審慎演習都在編寫和維護的代碼。此外,我相信C++通過構造函數也提倡相同的方法,即定義和分配。

我想知道爲什麼(如果)C99標準不喜歡定義&分配。他們在編碼風格演示所倡導的方面有什麼可觀的優點?

回答

1

通常我會建議初始化變量時,他們是否應該有值是已知的定義,並留下未初始化的變量,如果該值不是。無論哪種方式,儘可能將它們放在範圍規則允許的範圍內。

相反,它們應該在使用之前被分配一個默認值。

通常你根本不應該使用默認值。在C99中,您可以混合使用代碼和聲明,因此在爲其分配值之前定義變量沒有意義。如果你知道它應該採取的價值,那麼有一個默認值是沒有意義的。

此外,還有人提到C99兼容編譯器現在在上述情況中提出警告。

不適用於您顯示的情況 - 您沒有得到int x = 0;的警告。我強烈懷疑有人搞混了。編譯器警告,如果您使用的變量,而不給它分配一個值,如果您有:

... some code ... 

int x; 

if (a) 
    x = 1; 
else if (b) 
    x = 2; 
// oops, forgot the last case else x = 3; 

return x * y; 

那麼你將得到的是在不被初始化,至少用gcc使用X警告。

如果您在if之前爲x指定值,您將不會收到警告,但分配是作爲初始者完成還是作爲單獨的語句完成是無關緊要的。

除非您有特別的理由爲兩個分支分配兩次值,否則沒有必要先將默認值分配給x,因爲它會停止編譯器警告您已經覆蓋了每個分支。

0

我有點與建議同意,即使我並不完全確定的標準說這事,我很懷疑有關編譯器警告位爲真。

問題是,現代編譯器可以檢測未初始化變量的使用。如果您在初始化時將變量設置爲默認值,則會失去該檢測。並且默認值也可能導致錯誤;當然在你的例子中,int a = 0;。誰說0對於a是合適的值?

在20世紀90年代,建議會錯誤的。如今,這是正確的。

+0

當你說detect時,你的意思是編譯器將它標記爲Warning,對吧?我還沒有看到編譯器因爲未初始化的變量而拒絕編譯。 – 2009-06-11 07:01:54

+0

如果這取決於我,這將是一個致命的錯誤,但C是它的語言,警告可能是唯一適當的迴應。 但是,嘿。一個被賦值爲默認值的變量(即使它不應該)也不會產生任何警告。 – 2009-06-11 07:24:13

0

我發現它非常有用的預分配一些默認數據變量,這樣我就不必做(許多)的代碼null檢查。

1

還有沒有這樣的要求(或者我知道的指南)在C99中,編譯器也沒有提醒你。這只是一個風格問題。

就編碼風格而言,我認爲你從字面上理解了一些東西。例如,你的說法是正確的下列情況下...

int i = 0; 

for (; i < n; i++) 
     do_something(i); 

......甚至......

int i = 1; 

[some code follows here] 

while (i < a) 
     do_something(i); 

...但也有另一些情況下,在我的腦海裏,更好地處理早期的「申報和分配」。考慮堆棧或各種面向對象的結構構造結構,像:

struct foo { 
     int bar; 

     void *private; 
}; 

int my_callback(struct foo *foo) 
{ 
     struct my_struct *my_struct = foo->private; 

     [do something with my_struct] 

     return 0; 
} 

或者像(C99結構初始化):由於未初始化的指針

void do_something(int a, int b, int c) 
{ 
     struct foo foo = { 
       .a  = a, 
       .b  = b + 1, 
       .c  = c/2, 
     }; 

     write_foo(&foo); 
} 
0

我見過這麼多的錯誤,我總是主張用NULL_PTR聲明每個變量,並且聲明每個具有一些無效/默認值的基元。

由於我在RTOS和高性能但低資源系統上工作,所以我們使用的編譯器可能沒有捕獲到非初始化的用法。儘管我懷疑現代編譯器也可以100%依賴。

在Macro廣泛使用的大型項目中,我看到了罕見的場景,即使Kloclwork/Purify也未能找到非初始化的用法。

所以我說堅持下去,只要你使用普通的舊C/C++。

像.Net這樣的現代語言可以保證初始化變量,或者爲未初始化的變量使用提供編譯器錯誤。以下鏈接進行性能分析並驗證.NET有10-20%的性能影響。分析非常詳細,並且很好解釋。

http://www.codeproject.com/KB/dotnet/DontInitializeVariables.aspx