質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

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

Q&A

解決済

4回答

332閲覧

動的配列についての動作

Rivia

総合スコア23

C

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

0グッド

0クリップ

投稿2017/09/16 13:55

動的配列について最近知りました。
思い通りに動作しないので助言お願いします

#include<stdio.h> #include<stdlib.h> int main(void){ int i; int *heap; heap = (int*)malloc(sizeof(int)*10); for(i = 0;i<sizeof(heap);i++){ heap[i] = i; } printf("%d",heap[i]); heap = (int *)realloc(heap,sizeof(int)*15); for(i = 0;i<sizeof(heap);i++){ heap[i] = i; } printf("\n\n\n"); printf("%d",heap[i]); free(heap); return 0; }

イメージ説明

理想とする画面:
10

15

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

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

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

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

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

guest

回答4

0

ベストアンサー

こんにちは。

恐らく2種類の間違いがあります。
まず、sizeof演算子は、変数自体のバイト数を返却します。
heapはポインタです。ポインタのサイズは32ビット・ビルドでは4バイト(=32ビット)、64ビット・ビルドでは8バイト(=64ビット)です。ですので、恐らく4か8になります。

次に、for文はiの初期設定i=0→継続条件判定i < sizeof(heap)→ループ内の処理heap[i] = i;→次処理i++→継続条件判定i < sizeof(heap)→...と進みます。
つまり、sizeof(heap)=4、i=3の時は、heap[3] = 3;i++4 < 4でループを抜けます。
そして、printf("%d",heap[i]);は、printf("%d",heap[4]);となりますが、heap[4]には値を設定していませんので、不定値が表示されます。

なお、heap[4]は今回はたまたま0でしたが0になることも期待しない方が良いです。処理系によって異なります。

投稿2017/09/16 14:08

Chironian

総合スコア23272

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

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

Rivia

2017/09/16 14:23

ありがとうございます。 for文について勘違いしていました。 そしてsizeofについても詳しく知ることができて大変感謝しております ですが。そうなると要素数の確認はどうすればいいのでしょうか。 よろしければご鞭撻ください
cateye

2017/09/16 14:30

>要素数の確認・・・intの配列として扱うのであれば最初は10,realloc()の後は15ですが・・・もし、確保した領域のポインタを関数などに渡すのであれば、渡された方では領域のサイズが分からないのでパラメータなどを使って、教えてやる必要があります。
Chironian

2017/09/16 14:34

C言語の場合は、残念ながらコンパイラはmallocで獲得した領域の要素数を管理してくれません。 要素数を別途プログラムで管理するしかありません。今回の場合は、10や15を何か変数に入れて要素数として管理するのです。 例えば、ポインタと要素数変数を構造体で管理するなどですね。 以下の処理を適切な関数に分けて書くイメージです。 // 管理領域の定義(C++になれているのでC言語だとちょっと違うかも。) struct dyn_array {   int* heap;   int count; }; // 管理領域獲得 dyn_array array; // 初期化 array.heap=NULL; // 動的配列獲得 array.count=15; array.heap=(int*)realloc(array.heap, sizeof(int)*array.count); ちなみに、C++ならdyn_arryの中に初期化やrealloc()的な処理を記述できるのでプログラムがすっきりします。
Rivia

2017/09/16 14:53

う~ん、理解力が足りていないのか、いまいち分かりません。 mallocでは要素数を管理してくれないことと、 管理するプログラムを別に作ることの意図までは分かるのですが なぜそのプログラムで要素数を管理することが出来るのかがいまいち。。。
Chironian

2017/09/16 15:07 編集

array.countに15を入れてます。例えば、各要素をfor文で列挙したい時は、下記処理でできます。 for (int i=0; i < array.count; ++i) printf("[%d] %d\n", i, array.heap[i]); array.countが10の場合でも同じプログラムで対応できます。 このようにheapとcountをセットにしてハンドリングすれば多少楽になります。 関数に渡す際もいちいちheapとcountを別々に渡さなくていよいです。 動的配列を複数渡したい時などに効いてきます。
Rivia

2017/09/16 15:16

なるほど!二つとも自分で入力してあげるのですね! そしてそれを構造体でまとめてあげると、、、 分かりやすい説明ありがとうございます! わざわざお時間いただきありがとうございました
guest

0

sizeof(heap)は、malloc()で確保したサイズではなく、ポインタのサイズです(4or8)。なので、意図した動きではないと思います。また、他の方の指摘にもあるようにprintf("%d",heap[i]);のiは(確保したメモリ内にありますが)数値を入れた所ではないデータを表示すると思います。・・・たまたま0だったd^^

投稿2017/09/16 14:16

cateye

総合スコア6851

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

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

Rivia

2017/09/16 14:27

malloc関数及びrealloc関数についてあまり理解が及んでませんでした。 色々なサイトをめぐり学んでいるのですが、未だに理解できません・・・
guest

0

やはりこうなりましたか、前回の質問の方の私の回答を参考に下さい。

ちなみに、もうひとつ。ループを終了した時点においてカウンタ変数iは添え字の範囲の外になっていることに注意です。(0から9まで数え上げていったとしたら、ループ終了時には10となっている)

投稿2017/09/16 14:07

HogeAnimalLover

総合スコア4830

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

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

Rivia

2017/09/16 14:25

前回に続き回答ありがとうございます! for文について勘違いしていました。 気づかせていただきありがとうございます。 では要素数はどうやって確認すればいいのでしょうか 是非よろしければ教えてください
HogeAnimalLover

2017/09/16 14:28

mallocで確保されたバイト数を事後的に調べる万能な方法はありません。malloc時に使った引数を継続的に記録し続け、必要に応じて使うしかありません。
Rivia

2017/09/16 14:35

それはプログラムをみてバイト数を確認するということでしょうか。。。 それではmalloc関数を使ってバイトを確保するときにはコメント文は絶対必要ですよね
HogeAnimalLover

2017/09/16 14:40

意味が分かりませんが、「プログラムソース記述の段階で確認するしかない」という意味ならばその通りです。いずれにしろ動的に(プログラム実行中に)確認することはできません。引数の値を変数に格納しておくなりしておかないといけません。
guest

0

パッと見ループ抜けてから i 使ってるからじゃないですか?

投稿2017/09/16 14:05

Zuishin

総合スコア28656

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

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

Rivia

2017/09/16 14:24

ループを抜けたときiはループ終了後の値になっているのではないのですか? だからループのたびに初期値を決めるのだと思っておりましたが
Zuishin

2017/09/16 14:26

ループ内で使われた値に 1 足したものになっていると思います。 ++ した結果、ループ条件から外れた時にループが終わるので。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問