2010-05-06 112 views
4

爲什麼數組c初始化

static char *opcode_str[] = { "DATA" 
          , "DATA_REQUEST_ACK" 
          , "ACK_TIMER_EXPIRED" 
          , "ACK_UNEXPECTED_SEQ" 
          , "ACK_AS_REQUESTED" 
          } ; 

工作,但

static char **opcode_str = { "DATA" 
          , "DATA_REQUEST_ACK" 
          , "ACK_TIMER_EXPIRED" 
          , "ACK_UNEXPECTED_SEQ" 
          , "ACK_AS_REQUESTED" 
          } ; 

失敗SEGV時opcode_str [0] printf'd?

我認爲這是因爲第二個列表沒有爲指針的五個元素數組分配內存,但我需要更全面的解釋。

一切順利,

克里斯。

回答

10

這是正確的。你基本上試圖將一個數組分配給一個指針。 GCC 4.4.1警告這個默認:

opcode_str.c:4: warning: initialization from incompatible pointer type 
opcode_str.c:5: warning: excess elements in scalar initializer 

它重複多餘的元素預警4次,因爲你基本上把5個球​​,其中只有一個會適合。您可以使用gcc -Werror將所有警告強制爲錯誤。

你可以這樣做:

static char **opcode_str = malloc(sizeof(char *) * 5); 
opcode_str[0] = "DATA"; 
opcode_str[1] = "DATA_REQUEST_ACK"; 
opcode_str[2] = "ACK_TIMER_EXPIRED"; 
opcode_str[3] = "ACK_UNEXPECTED_SEQ"; 
opcode_str[4] = "ACK_AS_REQUESTED"; 

但是你已經發現做到這一點的最好辦法。就錯誤發生時,一旦你調用未定義的行爲,你真的不能指望特定的時間來顯示問題。

但我認爲opcode_str包含一個指向DATA的指針。所以(假設爲32位),它將嘗試解釋opcode_str('D','A','T','A')的前四個字節,作爲char *的四個字節。

+0

謝謝。爲什麼在編譯時或指針初始化時不會失敗? – fadedbee 2010-05-06 14:36:36

+2

@chrisdew它是未定義的行爲,違反了C中的語義規則。違反的規則是*標量的初始值設定項應該是一個單獨的表達式,可選地用大括號括起來*但是,您有多個表達式括在花括號中。 – 2010-05-06 14:37:52

+1

就是這樣,我會讓警告從我的屏幕上滾動。衛生署! 我現在可以看到,我將char **指針設置爲char *指向「DATA」的值。然後評估「DATA」,就好像這四個/八個字節持有一個指針並且這引起了段錯誤。 – fadedbee 2010-05-06 14:44:32