char** args = (char**)malloc(MAX_ARGS*sizeof(char*));
と
char* args = (char*)malloc(MAX_ARGS*sizeof(char*));
これら2種類の宣言の違いを説明してください。なぜ2つ星が必要なのか、なぜ1つ星が必要なのですか?
どちらの場合も、キャストは不要であり、エラーを隠すことができます。以下のキャストを削除します。(をmalloc()
返しますvoid*
。これは、暗黙的に何へのポインタにも変換できます。)
char **args = malloc(MAX_ARGS*sizeof(char*));
これは、ポインタから文字へのポインタとして定義され、各要素がである要素args
を保持するのに十分な大きさのメモリのチャンクを指すように初期化します。これを行ったら、それらの要素に値を割り当てて、文字列を指すようにする必要があります。MAX_ARGS
char*
char*
char *args = malloc(MAX_ARGS*sizeof(char*));
これは合法ですが、ほぼ確実に論理的なエラーです。 はcharへのポインタです。これは、単一のオブジェクト、または要素の配列の最初の要素のargs
いずれかを指すことができることを意味します。ただし、ポインタを保持できるメモリを割り当てています。char
char
MAX_ARGS
より可能性の高いことは次のとおりです。
char *s = malloc(MAX_LEN);
これにより、要素(最大の長さの文字列)s
を保持できるメモリの領域を指すようになります。(定義上、注意してください。)MAX_LEN
char
MAX_LEN - 1
sizeof (char) == 1
タイプの不一致を回避するための便利なトリックがあります。タイプのポインタはFOO*
、どのタイプFOO
でも、タイプの1つ以上の要素を古いものにするのに十分な大きさのメモリのチャンクを指す必要がありますFOO
。あなたが書く場合:
ptr = malloc(count * sizeof *ptr);
でありptr
、FOO*
その後sizeof *ptr
は-と同じですが、後でBAR`に変更したsizeof (FOO)
場合は、行を更新する必要はありません。ptr
pointer to
あなたの場合、pointed-to型はそれ自体がポインタなので、次のように書くことができます。
char **args = malloc(MAX_ARGS * sizeof *args);
また、を呼び出すときは、成功したかどうかmalloc
を常に確認し、失敗した場合は何らかのアクションを実行する必要があります。そのアクションがプログラムをエラーメッセージで終了する場合でも、次のようになります。
if (args == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
2つの星は、pointer-to-a-pointer_type-to-data_typeを意味します。したがって、char **の場合、これはchar*[MAX_ARGS]の配列を作成することを意味します。
したがって、この場合、 args[n]はchar*であるため、以下が有効になります。
args[0] = (char*)strdup("aaa");
args[1] = (char*)strdup("bbbb");
args[2] = (char*)strdup("ccccc");
注:引数を解放する前に、配列の各メンバーを解放することを忘れないでください。そうしないと、ポインターが失われます。
単一の星の場合、それは単なるデータへのポインタであり、基本的にはchar [MAX_ARGS * sizeof(char *)]を記述しています。
この場合、args[n]はchar型です。
args[0] = 'a';
args[1] = 'b';
args[2] = 'c';
このchar-arrayを使用すると、cスタイルの文字列とも呼ばれる単純な文字配列を作成できます。
2つの星はマトリックス(または2次元配列)のようなものです。最初のmallocは、最初の行のメモリのみを取得します(2番目のmallocが他の行のためにスペースを予約するように、その要素を反復処理する必要があります)。