簡體   English   中英

將char [] []轉換為char **導致段錯誤?

[英]casting char[][] to char** causes segfault?

好吧我的C有點生疏,但我想我會在C中制作我的下一個(小)項目,所以我可以對它進行修改,不到20行,我已經有了一個seg錯誤。

這是我的完整代碼:

#define ROWS 4
#define COLS 4

char main_map[ROWS][COLS+1]={
  "a.bb",
  "a.c.",
  "adc.",
  ".dc."};

 void print_map(char** map){
  int i;
  for(i=0;i<ROWS;i++){
    puts(map[i]); //segfault here
  }
 }



int main(){
  print_map(main_map); //if I comment out this line it will work.
  puts(main_map[3]);
  return 0;
}

我完全混淆了這是如何導致段錯誤的。 [][]**時發生了什么? 這是我得到的唯一警告。

rushhour.c:23:3: warning: passing argument 1 of ‘print_map’ from incompatible pointer type
rushhour.c:13:7: note: expected ‘char **’ but argument is of type ‘char (*)[5]’

[][]**真的不兼容指針類型嗎? 他們似乎只是我的語法。

char[ROWS][COLS+1]無法轉換為char** print_map的輸入參數應該是

void print_map(char map[][COLS+1])

要么

void print_map(char (*map)[COLS+1])

區別在於char**意味着指向可以像這樣解除引用的東西:

   (char**)map
       |
       v
  +--------+--------+------+--------+-- ...
  | 0x1200 | 0x1238 | NULL | 0x1200 |
  +----|---+----|---+--|---+----|---+-- ...
       v        |      =        |
    +-------+   |               |
    | "foo" | <-----------------'
    +-------+   |
                v
             +---------------+
             | "hello world" |
             +---------------+

雖然char(*)[n]是指向這樣的連續存儲區域

   (char(*)[5])map
       |
       v
  +-----------+---------+---------+-------------+-- ...
  | "foo\0\0" | "hello" | " worl" | "d\0\0\0\0" |
  +-----------+---------+---------+-------------+-- ...

如果將(char(*)[5])視為(char**)則會產生垃圾:

   (char**)map
       |
       v
  +-----------+---------+---------+-------------+-- ...
  | "foo\0\0" | "hello" | " worl" | "d\0\0\0\0" |
  +-----------+---------+---------+-------------+-- ...
      force cast (char[5]) into (char*):
  +----------+------------+------------+------------+-- ...
  | 0x6f6f66 | 0x6c686500 | 0x77206f6c | 0x646c726f |
  +----|-----+---------|--+------|-----+------|-----+-- ...
       v               |         |            |
    +---------------+  |         |            v
    | "hsd®yœâñ~22" |  |         |       launch a missile
    +---------------+  |         |
                       v         v
               none of your process memory
                        SEGFAULT

當你做這個聲明時:

char main_map[ROWS][COLS+1]={
  "a.bb",
  "a.c.",
  "adc.",
  ".dc."};

您創建一個char-array數組。 char-array只是一個字符塊,而數組數組只是一個數組塊 - 所以總的來說, main_map只是一堆字符。 它看起來像這樣:

| 'a' | '.' | 'b' | 'b' | 0 | 'a' | '.' | 'c' | '.' | 0 | ... | 'd' | 'c' | '.' | 0 |

當你將main_map傳遞給print_map() ,它正在評估main_map作為指向數組第一個元素的指針 - 所以這個指針指向那個內存塊的開頭。 您強制編譯器將其轉換為char **類型。

當你在函數中評估map[0] (例如,對於循環的第一次迭代),它會獲取map指向的char *值。 不幸的是,正如你從ASCII藝術中看到的那樣, map 並沒有指向一個char * - 它指向一堆普通的char 那里根本沒有char *值。 此時,您將加載其中一些char值(4或8,或其他一些數字,具體取決於您的平台上char *大小),並嘗試將其解釋為char *值。

puts()嘗試遵循偽造的char *值時,就會出現分段錯誤。

看着我的代碼,我意識到列的數量是不變的,但它實際上並不重要,因為它只是一個字符串。 所以我改了它,所以main_map是一個字符串數組(呃,char指針)。 這使得我可以使用**來傳遞它:

char *main_map[ROWS]={
  "a.bb",
  "a.c.",
  "adc.",
  ".dc."};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM