dポイントプレゼントキャンペーン実施中!

 文字列をポインタを使って扱うとき、例えば、初期化は次のように行えますよね。

#include <stdlib.h>
char *s;
s = (char *)malloc(1000);
(これに続いてscanf("%s", s);など)

 これと同様にして、二次元の配列を、ポインタのポインタを使って表したいとき、

char **s;

と宣言したものを、malloc()関数を使って初期化することはできるのでしょうか。よろしくお願いします。

A 回答 (8件)

mallocで2次元配列を確保するためには


まず各行の先頭アドレスを確保してから、各行の先頭アドレスに各列を確保するようにします。
具体的には10行20列を確保したい場合

int c = 10, r = 20;
char **s;
s = (char**)malloc(c*sizeof(char*));
for(i=0; i<c; i++){
  s[i] = (char*)malloc(r*sizeof(char));
}

と確保します。

注意としてはメモリの解放のfreeは、メモリを確保した各場所で行わないと適正に解放されないので
for(i=0; i<c; i++){
  free(s[i]);
}
free(s);

とします。
    • good
    • 0
この回答へのお礼

 ありがとうございます。大変よく分かりました。

お礼日時:2014/09/27 07:46

sizeof演算子は、アライメントが加味された値を返すのではありませんでしたか?>#7.





> 何度もありがとうございます。よろしければ、問題点を具体的に指摘して下さいませんか。
以下のページの説明とかどうでしょう。

C言語-ポインタとメモリと型(構造体)の関係 (2)
http://www.mm2d.net/c/c-15.shtml
    • good
    • 0
この回答へのお礼

 ありがとうございます。参照ページを一読しましたが、処理系依存の話ですか。また時間を取ってじっくりと勉強してみます。

お礼日時:2014/09/28 18:21

あれ? アライメントの問題が発生する可能性がまったくないとはいえないような気がする>#6.

    • good
    • 0
この回答へのお礼

 何度もありがとうございます。よろしければ、問題点を具体的に指摘して下さいませんか。

お礼日時:2014/09/28 06:25

No.2 と同じだが、一度のmalloc/freeで済ますには:



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

int main() {
int R = 3;
int C = 4;
int i, j;

int** data;

/* 領域確保 */
int* p = (int*)malloc(sizeof(int*)*R + sizeof(int)*R*C);
/* 初期化 */
data = (int**)p;
(int**)p += R;
for ( i = 0; i < R; ++i ) {
data[i] = p; p += C;
}

/* 代入 */
for ( i = 0; i < R; ++i ) {
for ( j = 0; j < C; ++j ) {
data[i][j] = i*10 + j;
}
}
/* 参照 */
for ( i = 0; i < R; ++i ) {
printf("%p: ", data[i]);
for ( j = 0; j < C; ++j ) {
printf("%02d ", data[i][j]);
}
printf("\n");
}

/* 領域解放 */
free(data);
return 0;
}
    • good
    • 0
この回答へのお礼

 ありがとうございます。

お礼日時:2014/09/28 06:24

C言語では、void*型からは任意の型へのポインタへ暗黙の内に型変換を行うので



s = malloc(c*sizeof(char*));

と書いても大丈夫です。

C++では、void *から任意のポインター型への変換には明示的なキャストが必要なので、
上記の書き方ではエラーがでます。
    • good
    • 0
この回答へのお礼

 何度もご丁寧に、誠にありがとうございました。感謝致します。

お礼日時:2014/09/27 17:01

>No.2さんのご回答のように、void *型からchar **型へのキャスト、というのは、必要ないのでしょうか。



#3には「してもいいし、しなくてもいい」と書いてるんですが。
必須じゃありませんので好きにしてください。
malloc()がどうのより、void *の意味を理解した方がいいんでしょうけど。
    • good
    • 0
この回答へのお礼

 済みません、ちゃんと書いてありましたね。void *の意味をよく勉強したいんですが、また機会があれば情報源を当たってみたいと思います。ありがとうございました。

お礼日時:2014/09/27 17:00

>質問文に書いたみたいに、malloc()の戻り値をキャストしなくていいのでしょうか。



malloc()の戻り値の型はANSI-C準拠ならvoid *なのでキャストしてもしなくてもいいです。
    • good
    • 0
この回答へのお礼

 ありがとうございます。No.2さんのご回答のように、void *型からchar **型へのキャスト、というのは、必要ないのでしょうか。

お礼日時:2014/09/27 10:53

ふつ~に


s = malloc(sizeof *s);
みたいに初期化できる.
    • good
    • 0
この回答へのお礼

 ありがとうございます。質問文に書いたみたいに、malloc()の戻り値をキャストしなくていいのでしょうか。

お礼日時:2014/09/27 07:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!