2011-01-21 11 views
1

多次元配列にデータを書き込もうとしていて、配列を別の関数にconst char**として渡します。私がchar*を宣言されている関数でローカルに印刷すると、すべて正常に動作します。しかし、別の関数でchar*の配列を印刷しようとすると、それらはすべて空文字列になります。多次元char配列は関数内で出力されますが、別の関数に渡されたときは出力されません

私は、次のコードを使用しています:

void my_print (const char** lines, unsigned int num) 
{ 
    int i = 0; 

    for (i = 0; i < num; i++) { 
     fprintf(stderr, "lines[%d]: %s", i, lines[i]); 
    } 
} 

void my_func() 
{ 
    char cfg[2][200]; 
    unsigned int value = 5; 

    snprintf(cfg[0], 200, "one two three\n"); 
    snprintf(cfg[1], 200, "my value = %u\n", value); 

    fprintf(stderr, "lines[0] = %slines[1] = %s\n", cfg[0], cfg[1]); 

    my_print((const char**) cfg, 2); 
} 

これは、次の出力が生成されます。

lines[0] = one two three 
lines[1] = my value = 5 
lines[0]: 
lines[1]: 

代わりに、与えられたmy_funcの、私は次のように使用している場合:

void my_func() 
{ 
    char* cfg[2]; 
    unsigned int value = 5; 

    cfg[0] = malloc(200); 
    cfg[1] = malloc(200); 
    snprintf(cfg[0], 200, "one two three\n"); 
    snprintf(cfg[1], 200, "my value = %u\n", value); 

    fprintf(stderr, "lines[0] = %slines[1] = %s\n", cfg[0], cfg[1]); 

    my_print((const char**) cfg, 2); 
} 

それから、すべて動作し、私は得ます:

lines[0] = one two three 
lines[1] = my value = 5 
lines[0]: one two three 
lines[1]: my value = 5 

ここで背景には何が起こっていますか? my_printが文字列を印刷できるようにするために、なぜmallocを使用する必要がありますか?

おかげであなたは

答えて

6

配列はポインタ

配列彼らの最初の要素へのポインタに崩壊ないが、しかし、それは唯一の最初次元で起こります。だから、2次元配列がポインタへのポインタにない崩壊しないことは、あなたの関数に渡す必要がありますものですので、それだけで、配列へのポインタに崩壊:

// lines is of type "pointer to array 200 of const char" 
void my_print (const char (*lines)[200], unsigned int num) 

コードのこのラインは非常にあります、非常に間違っ:

my_print((const char**) cfg, 2); 

あなたはおそらく、コンパイラを黙らせるconst char**にキャストを挿入します。 ではなくを実行します - コンパイラはあなたに何か間違っていると伝えようとしています!シャットダウンするのは間違ったことです。

my_print(cfg, 2); 
+0

2D配列がポインタへのポインタに崩壊しないという事実が答えです。ありがとう! – DuneBug

0

た説明が良いです::へのポインタのポインタはない多次元配列と同じものであるmy_printの定義に上記の変更を使用すると、任意のキャストは必要ありません。端的に説明

、構文を使用して2次元アレイ

チャーCFG [2] [200]。

は、隣接するメモリセルに割り当てられることが保証されます。 mallocで割り当てられた2次元のポインタからポインタへの配列はでなく、は隣接するメモリセルに割り当てられます。ヒープ全体に割り当てられます。 mallocを呼び出すたびに、新しいセグメントを割り当てます。 C言語の多次元配列のジェネリック関数を作ることは、このために非常に難しいです。