2012-09-05 95 views
1

我有以下C代碼,其工作原理:如何通過指針的指針的陣列用C

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <malloc.h> 

int pw = sizeof(char*);  // width of pointer (to char) 

int num; 
int first = 1; 
int size = 0; 
int incr = 10; 

char *(*arr)[];  // pointer to array of pointers to char */ 

test(char* s, int i) 
{ 

    int j; 
    char *(*newarr)[];  // pointer to array of pointers to char 

    if (first) {   // first time 
    arr = malloc(pw*incr); // malloc array 
    first = 0;   // skip from now on 
    size = incr;  // save the size 
    } 


    if (i >= size) {   // out of space 
    newarr = malloc(pw*(size+incr)); // get incr bigger space 
    for (j=0; j<size; j++)  // copy the elements from the old 
     (*newarr)[j] = (*arr)[j];  // array to new array 
    free(arr);     // free the old array space 
    arr = newarr;   // point old array to new array 
    size = size+incr; 

    }; 

    int len = strlen(s);  // length of s 
    (*arr)[i] = malloc(len+1); // assign pointer to pointer array element 
    strcpy((*arr)[i], s);  // copy s to array 
        // both arguments must be pointers 

    printf("%d\t%s\n", i, (*arr)[i]); 
}; 

main() 
{ 

    char* s = "this is a string"; 

    for (num=0; num<30; num++) // add 30 pointers to s to *arr 
    test(s, num); 

    for (num=0; num<30; num++) 
    printf("%d\t%s\n", num, (*arr)[num]); // print out what they point to 
}; 

它打印出「I \ t這是一個字符串」爲「i」的從0到29的兩倍。我想要做的是從文件頂部傳遞'arr'作爲'test'的參數。我想這樣做的原因是因爲我想傳遞幾個不同的數組,所有這些數組都被聲明爲相同的方式。如果我做最小的改動要做到這一點,我得到:

0 this is a string 
Segmentation fault (core dumped) 

這裏是diff命令的輸出,顯示最小的變化:

13c13 
< char *(*arr)[];  // pointer to array of pointers to char */ 
--- 
> char *(*jarr)[];  // pointer to array of pointers to char */ 
15c15 
< test(char* s, int i) 
--- 
> test(char* s, int i, char *(*arr)[]) 
52c52 
<  test(s, num); 
--- 
>  test(s, num, jarr); 
54,55d53 
< for (num=0; num<30; num++) 
<  printf("%d\t%s\n", num, (*arr)[num]); // print out what they point to 

換句話說一切都只是重命名相同'arr'作爲'jarr'並傳遞給'test'。

由於提前, 邁克

+1

當您遇到分段錯誤或任何其他崩潰時,您的第一反應應該是在調試器中運行您的程序。它會幫助你找到崩潰的位置,並且讓你檢查可能導致崩潰的變量。 –

+0

謝謝你。我應該說它崩潰在''(* arr)[i] = malloc(len + 1); //在第二次通過時將指針指向指針數組元素'。 – user1625815

+2

看起來你正在使這種方式比它需要更復雜 - 爲什麼不使用'char **'並按照通常的方式分配內存呢? –

回答

0

當你打電話時出現麻煩:

test(s, num, jarr); 

你傳入jarr的價值。在函數內部,您正在重新分配(難道 - 爲什麼不使用realloc()爲您進行復制?)數組,但該更改不會影響jarr'main()'中的值,因爲它是按值傳遞的。通過循環第二次,你仍然將一個空指針傳遞給該函數,但是你將取消引用該空指針,這是個壞消息。

如何解決?

公平的問題......我不確定是否舊的「好吧,如果我想到那裏,我不會從這裏開始」堵嘴通過召集。

在「簡單」的變化是修改呼叫:

jarr = test(s, num, jarr); 

,然後「只是」修改功能,使得它返回一個指向字符指針的陣列。這是一個非常深奧的功能。我的大腦還沒醒(咖啡因不足),所以我用了一箇中間typedef來解決如何編寫函數聲明和定義問題:

typedef char *(ArrayString[]); 

ArrayString *test3(char *s, int i, char *(*arr)[]); 

ArrayString *test3(char *s, int i, char *(*arr)[]) { (*arr)[i] = s; return arr; } 

它編譯沒有警告;這不是保證它是正確的。

主要的選擇是將指針傳遞給指向該函數的一個char指針數組,該指針更加深奧。


但是,這些都是'從這裏開始'的解決方案。總體而言,你會做得更好,設計一種處理事物的不同方式。指向數組的指針當然是C的一部分,但它們位於C的外邊緣,你通常應該假設如果你的設計需要使用它,那麼你的設計可能不是最好的。你應該使用一個更簡單的char **(或者,消亡的想法,char ***;最好避免三重間接,但這並非總是可行)。

+0

謝謝喬納森,完美的工作。所有的答案都取決於'test'函數必須處理一個間接級別而不是數組聲明(或指向它的指針)的事實。其他答案涉及到獲取指向數組的指針的地址,並修改'test',同時在聲明中(從指針到數組,僅僅是數組),刪除了一個間接級別。你的答案是我正在尋找的。至於C語言,它是一種三重間接或指向指針數組的指針來完成我想要做的事情。 – user1625815

+0

此外,您的答案與我發佈的答案略有不同。 – user1625815

1

您似乎誤解了數組和指針的工作原理。比方說,你想字符串動態數組,這基本上是一個指針的char指針:

char **arr = NULL; 

要爲你做例如分配內存

arr = malloc(sizeof(char *) * current_size); 

現在你有一個「數組」的字符指針。比方說,你希望每個這些是一個特定的字符串str

for (int i = 0; i < current_size; i++) 
{ 
    arr[i] = strdup(str); 
} 

哦,現在你需要增加弦數,前全部初始化爲相同的字符串爲:

size_t new_size = current_size + 10; 
arr = realloc(arr, sizeof(char *) * new_size); 

for (int i = current_size; i < new_size) 
{ 
    arr[i] = strdup(str); 
} 

現在的問題是,你想在一個單獨的函數中完成上述所有操作。現在是第一次,你必須添加另一個間接。

0

我認爲你可以對在測試(s,0,jarr)和測試(s,0,jarr)中分配給jarr的第一個malloc值進行雙重檢查; jarr assignement不成功,因爲您在傳遞值中更改指針值。