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

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

ただいまの
回答率

89.99%

C言語のポインタ、これで実行できない理由を教えてください。

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 916

yassuda

score 13

授業とは違うプログラムを作ったのですが、これでうまく実行できない理由がわかりません。

問題

三⾓形の底辺の⻑さを格納するint型変数を指すポインタxpと、⾼さを格納するint型変数を指すポインタhpと、⾯積を格納す
るためのfloat型変数を指すポインタapを仮引数として受け取ると、三⾓形の⾯積を計算してapが指すfloat型変数に格納する
calc_area関数を作成せよ。さらに、適切にmain関数を設け、三⾓形の底辺の⻑さと⾼さを整数値で標準⼊⼒すると、三⾓形
の⾯積を⼩数点以下2桁まで標準出⼒するプログラムを作成せよ。

回答のプログラム

#include<stdio.h>

void calc_area(int *xp, int *hp, float *ap);

int main(void) {
  int x, h;
  float area;

  printf("x = "); scanf("%d", &x);
  printf("h = "); scanf("%d", &h);

  calc_area(&x, &h, &area);

  printf("Area = %.2f\n", area);

  return 0;
}

void calc_area(int *xp, int *hp, float *ap) {
  *ap = *xp * *hp * 0.5;
}

自分の回答

#include<stdio.h>

void calc_area(int *xp, int *hp, float *ap);

int main(void) {
  int *x, *h;
  float *area;

  printf("x = "); scanf("%d", x);
  printf("h = "); scanf("%d", h);

  calc_area(x, h, area);

  printf("Area = %.2f\n", *area);

  return 0;
}

void calc_area(int *xp, int *hp, float *ap) {
  *ap = *xp * *hp * 0.5;
}

アドレスとしてxを定義するとxの変数のアドレスを準備したことにはならないということですか?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

xがどこを指しているかが問題です。

正回答では、格納する場所を作り、それを指すポインタをscanfに渡しました。

int x;//格納する場所
int* x_p = &x;//格納する場所を指すポインタ
scanf("%d", x_p);

ここで上例でx_pのみの状態が誤回答の状態です。どこを指しているか不明なポインタを渡しています。

 追記

ポインタはあらかじめ格納する場所を用意しておく必要があるということですか?

じゃないと何を指し示すのか(point)わからないじゃないですか。

ちなみにどこを指しているかわからない or NULL pointerはdereferenceしてはいけません。dereferenceとは具体的に言うと、operator *(単項演算子), operator []の呼び出しです。

int x;
int* p1 = &x;
int* p2;
int* p3 = NULL;
int* p4 = malloc(sizof(int));
*p1;//OK
//*p2;//NG: Undefined Behavior: C11, 6.5.3.2p4
//*p3;//NG: Undefined Behavior: C11, 6.5.3.2p4
*p4;//OK
free(p4);

ref:

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/23 14:20

    int *x;
    これだけでは、格納する場所がxでそのポインタを表す。
    というふうにはならないということですか?
    つまり、ポインタはあらかじめ格納する場所を用意しておく必要があるということですか?

    キャンセル

  • 2017/07/23 14:26

    >格納する場所がxで

    ちがいますね。その場合xはポインタを格納する場所です

    キャンセル

  • 2017/07/23 15:18

    ポインタに関する理解が深まりました。
    ありがとうございました。

    キャンセル

  • 2017/07/23 15:19

    >ポインタはあらかじめ格納する場所を用意しておく必要がある

    ちがいます。ポインタをdereferenceする前に有効なポインタ(NULLポインタとかどこ指しているかわからんぽいんたではない)にしましょう、というお話。

    キャンセル

0

ポインターは実体が無いので、実体のアドレスを代入してあげます。

#include<stdio.h>

void calc_area(int *xp, int *hp, float *ap);

int main(void) {
  int *x, *h;
  float *area;
  int ix, ih;
  float farea;
  x=&ix;
  h=&ih;
  area=&farea;

  printf("x = "); scanf("%d", x);
  printf("h = "); scanf("%d", h);

  calc_area(x, h, area);

  printf("Area = %.2f\n", *area);
 printf("Area = %.2f\n", farea);

  return 0;
}

void calc_area(int *xp, int *hp, float *ap) {
  *ap = *xp * *hp * 0.5;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/23 15:17

    >ポインターは実体が無いので

    それまたおかしな話。ポインタにも実体があるのでポインタをさすポインタ型があるんですががが

    キャンセル

  • 2017/07/23 15:24

    その通りです。値を持たない?アドレスを指していない?とか表現能力の欠如でした。
    ポインターなので定義されただけでは、型と領域は持っていますが、アドレス情報が無いので使う前に、値が入っているアドレスを指してあげる必要が有ります。

    キャンセル

  • 2017/07/23 15:30

    >使う前

    というよりdereferenceする前ですね。「使う」だとなんのことかわかりにくいので。

    キャンセル

  • 2017/07/23 15:33

    日常そんな会話しかして居ないのですみません。dereferenceですね。ありがとうございます。

    キャンセル

0

変数は、ロッカーみたいなものです。

プログラムくんが起動したとき、OSちゃんは、「このロッカーの10番までは好きに使って。中身は捨ててもいいよ。」って言ってくれました。プログラムくんは、友達のアイオーくんから荷物を受けとるために、「1番のロッカーの中に入ってる指示書に従って」とアイオーくんに伝えましたが、メモを入れるのを忘れていました。

アイオーくんが1番のロッカーの中を覗くと、OSちゃんが捨て忘れた「20番のロッカーに入れる」ってメモが入っていました。アイオーくんが20番のロッカーを開けようとしたら、OSちゃんが「えっち、もう知らない!」って怒ってしまいました。プログラムくんにも口を利いてくれません。

ポインタってのは、上に書いたメモみたいなものです。慣れれば大変便利なものです(1つのロッカーに入りきらないときに、どこのロッカーに入れたかのメモがあれば思い出せる)。けど、プログラムが起動したときは色々入っていたりすることがあって、中身を捨てずに残っていたメモを見てロッカーを開けようとすると、怒られてしまうのです。

プログラムさんとしては、メモを捨てて「(自分が使える)2番、3番のロッカーに入れる」という内容の新しいメモを入れないといけなかったのです。

これが、上手く動かなかった理由です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/23 15:52

    その説明よく見かけるけど、ポインタへのポインタ型の説明とかconstとかどう説明する気なんだろうといつも思う。

    キャンセル

  • 2017/07/23 16:07

    質問にわかば*ガール…じゃなかった、若葉マークがあったので、文系の入門者向けの説明をしましたよとだけ。CPUの機能とかアセンブラとか説明しても、初心者バイバイになると思うと…ねorz

    キャンセル

0

解決済みのようですが一言

ポインタ変数は定義しただけでは有効領域を指し示しません。(つまりそれだけでは意味をなさない)常に有効領域を指し示すかまたは明示的にNULLを代入しておくことをお勧めします。(暗黙的にNULLが代入されるとは限りません)


int* p = NULL;//(定義時に初期化)

free(p);
p = NULL;//メモリ開放関数を使ったらNULL埋め

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる