🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

5回答

1647閲覧

ダブルポインタを使ってchar型の二次元配列を動的確保する方法が分からない

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2020/12/23 04:02

ダブルポインタを使ってchar型二次元配列を動的確保するにはどういうふうに定義するのでしょうか?
色々調べたのですが該当するサイトが見つからなかったのでここで質問させてもらいました。
該当するサイトの提示もしくは、サンプルコードを提示していただけると嬉しいです!

C

1char str[5][10]; // <- これを動的確保で作りたい

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ダブルポインターとの関係がわかりませんが、

char str[5][10]; // <- これを動的確保で作りたい

であれば、

C

1 char (*str)[5][10]; 2 int i,j; 3 4 str = malloc(sizeof *str); 5 6 for(i=0; i<5; i++){ 7 for(j=0; j<10; j++){ 8 printf("[%d][%d] = %p\n",i,j,&((*str)[i][j])); // => 連続領域に取られる 9 } 10 }

投稿2020/12/23 04:24

otn

総合スコア85893

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C

1int main() 2{ 3 int rows = 5; 4 int cols = 10; 5 6 char **str; //※ダブルポインタを使うことがmustらしい 7 { 8 size_t RowPtrsSize = sizeof(char*)*rows; 9 size_t Char2DBuffSize = sizeof(char)*rows*cols; 10 11 str = (char**)malloc( RowPtrsSize + Char2DBuffSize ); 12 str[0] = (char*)( str+rows ); 13 for( int i=1; i<rows; ++i ){ str[i] = str[i-1] + cols; } 14 } 15 16 {//Test 17 for( int i=0; i<rows*cols; ++i ) 18 { str[0][i] = 'a' + (i%26); } 19 20 for( int r=0; r<rows; ++r ) 21 { 22 str[r][cols-1] = '\0'; 23 printf( "%s\n", str[r] ); 24 } 25 } 26 27 // 28 free( str ); 29 return 0; 30}

投稿2020/12/23 05:14

fana

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hidezzz

2020/12/23 06:23 編集

すみません。先程書いた下記の指摘は間違っていました。回答の書き方で正しいです。 --- 以下間違い -- ポインタの配列部から2次元配列部へポイントするように初期化する処理は、 > str[0] = (char*)( str+rows ); だと2次元配列の入る領域の先頭位置が本来意図する位置よりも後ろにずれてしまうと思います。 > str[0] = (char*)str + rows; とかではないでしょうか。
fana

2020/12/23 06:33 編集

T*型のポインタに +k とか演算すると,sizeof(T)*k だけアドレスが進む. ここでは,str[0]の指す位置として「strが指す位置から sizeof(char*)*rows だけずれた場所」としたいので, char**型のポインタであるstrに対して +rows している,という話になります.
hidezzz

2020/12/23 06:35

すみません。おっしゃるとおりですね。お手数をおかけしました。
fana

2020/12/23 06:53

この回答だと, str と &(str[0][0]) とで値が異なってしまう点が良くない感,みたいな.
guest

0

ベストアンサー

char**内のchar*も動的配列とするのなら
下記コードのようになるのではないでしょうか。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <stddef.h> 4#include <string.h> 5 6int main(void){ 7 size_t col = 5; 8 size_t row = 12; 9 10 // メモリ確保 11 char** mem = (char**)malloc(sizeof(char*) * col); 12 for(size_t c=0; c<col; ++c) mem[c] = (char*)malloc(sizeof(char) * row); 13 14 // 全ての行へ文字列を流し込む 15 for(size_t c=0; c<col; ++c) strcpy(mem[c], "hello world"); 16 17 // すべての行の文字列表示 18 for(size_t c=0; c<col; ++c) printf("%s\n", mem[c]); 19 20 // 開放 21 for(size_t c=0; c<col; ++c) free(mem[c]); 22 free(mem); 23 24 /*---------------------------------------------------- 25 *実行結果* 26 hello world 27 hello world 28 hello world 29 hello world 30 hello world 31 *///-------------------------------------------------- 32}

投稿2020/12/23 04:36

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/12/23 04:43

ありがとうございます!
fana

2020/12/23 04:58

これでは「ジャグ配列」になってしまうのではないでしょうか.
退会済みユーザー

退会済みユーザー

2020/12/23 05:31 編集

ジャグ配列という言葉自体初耳なので おかしなことを言ってたら失礼します。 ジャグ配列とググってみると > ジャグ配列とは、その要素も配列である配列です。 と出てくるのですが 動的配列の動的配列という意味合いでしたら 確かにジャグ配列ということになりますが ジャグ配列ではなぜまずいのかが 私にはわからないので教えていただけたら幸いです。
fana

2020/12/23 05:36

あ,すみません.言葉の使い方をナチュラルに間違いました.(おかしなことを言っているのはこちらですね) 言いたかったのは, char str[5][10]; の場合は50要素分のメモリは連続しているのに対して,この方法ではメモリが連続でなくなる(ので,用途次第では問題が生じ得る)という点でした.
otn

2020/12/23 05:52

まあ、 > ダブルポインタを使ってchar型二次元配列を動的確保する と > char str[5][10]; // <- これを動的確保で作りたい が違うことを言ってるので、やりたいこととしてどっちが正しいの?ということですね。 これがベストアンサーと言うことは、前者だったと言うことかな。
退会済みユーザー

退会済みユーザー

2020/12/23 06:21 編集

確かにメモリを並べたいのなら size_t trans_index(const size_t col, const size_t row, const size_t row_max) { return col * row_max + row; } int main(void){ size_t col = 5; size_t row = 12; char* mem = (char*)malloc(sizeof(char) * col * row); for(size_t i=0; i<col; ++i) strcpy(mem + trans_index(i, 0, row), "hello world"); for(size_t i=0; i<col; ++i) printf("%s\n", mem + trans_index(i, 0, row)); free(mem); } のように一次元動的配列で無理やり二次元動的配列を表現するしかないかもですね...
otn

2020/12/23 06:26

いや、単に書けばOKです。
guest

0

c

1#define ROW_SIZE (5) 2#define COL_SIZE (10) 3 4char **str; // ポインタの宣言 5 6str = (char **)malloc( size_of(char)*ROW_SIZE*COL_SIZE ); // 動的メモリ取得 7 8 str[2][3] = 0; // アクセス 9}

こんな感じですかね。

投稿2020/12/23 04:12

hero1000

総合スコア56

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hidezzz

2020/12/23 04:19

「char**」(ポインタのポインタ)と2次元配列とではデータ構造が違っています。 また仮に「char**」で行くのならstrの先にあるポインタの初期化が足りていないと思います。
tatsu99

2020/12/23 04:39 編集

あなたの指示に従って、以下のプログラムを作成し、実行したところ、異常終了しました。 #include <stdio.h> #include <stdlib.h> #define ROW_SIZE (5) #define COL_SIZE (10) int main(void) { char **str; // ポインタの宣言 str = (char **)malloc( sizeof(char)*ROW_SIZE*COL_SIZE ); // 動的メモリ取得 str[2][3] = 0; return 0; }
guest

0

投稿2020/12/23 04:07

y_waiwai

総合スコア88040

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/12/23 04:10

もちろん読みました!それとは別に char **str = (char**)malloc..... このように定義する方法も知りたいです
y_waiwai

2020/12/23 04:14

その回答に提示されてますよ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問