2017-03-21 44 views
0

當我練習K編程語言的第5.8節(第113頁)時,我有問題。C:函數返回指針數組的元素

原始的源代碼是在這裏

/* month_name: return name of n-th month */ 
char *month_name(int n) 
{ 
    static char *name[] = { 
     "Illegal month", 
     "January", "February", "March", 
     "April", "May", "June", 
     "July", "August", "September", 
     "October", "November", "December" 
    }; 
    return (n < 1 || n > 12) ? name[0] : name[n]; 
} 

而且我已經知道,我們不能返回局部變量的指針,因爲它從棧在函數返回的,它會被破壞(?)。但在這個例子中,他們使用靜態來保持這個變量。

問題是「爲什麼他們仍然工作後,我刪除靜態表示法」。

我改變代碼

/* month_name: return name of n-th month */ 
char *month_name(int n) 
{ 
    char *name[] = { 
     "Illegal month", 
     "January", "February", "March", 
     "April", "May", "June", 
     "July", "August", "September", 
     "October", "November", "December" 
    }; 
    return (n < 1 || n > 12) ? name[0] : name[n]; 
} 

,他們仍然很好地工作。

但是。如果我返回name而不是name[n],它不會按我的預期工作。

它爲什麼有效?

回答

2

它仍然有效,因爲數組包含指向字符串的指針。字符串文字具有靜態存儲持續時間,即使數組持有他們的地址沒有。

事實上,一個優化編譯器應該明智的事實,並在這兩種情況下產生相同的代碼。

但是,當您返回name時,您記錄的規則也適用。所以你得到未定義的行爲。儘管除非您更改函數的返回類型,否則返回name不應編譯,因爲char*char**是不兼容的類型。

+0

如果沒有指向字符串的指針,它是否仍然保留在靜態存儲中? 如何釋放內存? –

+0

@ScottLee - 如果指針不是字符串(或其他具有靜態存儲持續時間的字符串),那麼通常關於內存管理的警告就適用,是的。如何自由取決於他們如何分配,即使如此也很棘手。 – StoryTeller

+0

如果編譯器知道它們永遠不能使用,編譯器可以優化字符串文本的存儲。 –