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

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

ただいまの
回答率

90.51%

  • C

    4534questions

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

C言語についての質問です。

解決済

回答 5

投稿

  • 評価
  • クリップ 0
  • VIEW 3,249

welld

score 1

最近、C言語を学習し始めた者です。
以下のソースコードを実行したところ、エラーが発生しました。
エラーの原因が知りたいです。基礎的な質問だと思いますがよろしくお願いします。

該当のソースコード

#include <stdio.h>

void func(int *p,int i);

int main(void){
    int *p,i;
    func(p,i);
    printf("%d\n",*p);
    return 0;
}

void func(int *p,int i){
    i=100;
    p=&i;
    return;
}

発生している問題・エラーメッセージ

Segmentation fault (コアダンプ)
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

checkベストアンサー

+2

C言語では、引数はすべて値渡しです(構造体引数すら、コピーして値渡しという挙動になります)。つまり、funcの中で代入した変数は、mainの中の変数とは別なので、呼び出したmainの側に影響することはありません。

そして、main内でのint *pは初期化されないままなので、それを逆参照した結果は「未定義」です。つまり、「コンパイルに失敗する」「何事もなかったかのようにどこかわからない場所を参照する」「コアダンプする」「システムごとクラッシュする」など、何が起きるともしれないプログラム、ということです。

関数から外側に値を伝える方法は3つあります。

  1. 返り値を返す
  2. 外部変数(グローバル or ファイル単位のstatic)を書き換える
  3. ポインタで受け取って、そのポインタ経由で書き込む(ポインタ自体を書き換えたいなら、int **のようにダブルポインタとする必要があります)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/26 10:57

    回答有り難うございます。

    キャンセル

+2

main の printf で参照している *p が未初期化(アドレス未定義)な状態だからだと思います。
p を func で設定しているつもりかと思われますがこれでは main の p にアドレスは設定されていません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/26 10:49

    回答ありがとうございます。

    キャンセル

+2

エラーとしては、他の回答者の通り、main関数内のpの値が初期化されていないことが原因です。

void func(int *p,int i){
    i=100;
    p=&i;
    return;
}


について、

  1. p=&i;にて、関数func内の変数pに変数iのアドレスを代入していますが、main関数の変数pはそのアドレスを指しません。
    (main関数のpと関数funcのpは別の変数であるため。)
  2. 変数pはmain関数で初期化されていないので、printf("%d\n",*p);で参照した時に妥当なアドレスを見ていません。(ここでエラー)

printf("%d\n",*p);で関数funcに与えた変数iの値を表示したいならば、

  1. main関数内でpが妥当な領域を指せるようにする(p=&iをfunc内ではなくてmain関数に書くなど)
  2. 関数func内でpに値を代入する(p = &i)のではなく、pが指す領域に値が入るよう(*p = i)にする

と良いと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/26 10:50

    回答ありがとうございます。

    キャンセル

  • 2016/05/26 10:57 編集

    (回答が修正されたので、コメントも取り下げておきます)

    キャンセル

  • 2016/05/26 11:04 編集

    ありがとうございます。早とちりしていました。修正します。(ベストアンサーは取り下げてください。)

    キャンセル

  • 2016/05/26 11:05 編集

    (コメント内容が変更されたのでそれに対する私のコメントも適当ではなくなってしまったので内容削除しておきます)

    キャンセル

  • 2016/05/26 11:15 編集

    修正しました。最初の回答は誤っていました。申し訳ありませんでした。

    キャンセル

  • 2016/05/26 11:42

    コメントは履歴が残らないのですね。HiroshiWatanabeさんの削除を促した変更点ですが、最初のコメントに"(ベストアンサーは取り下げてください。)"を追記したことです。当初は誤った回答に対する指摘とベストアンサーを訝しむコメントを頂いておりましたが、ご指摘まで削除させてしまいました。申し訳ありません。

    キャンセル

+1

int *p はポインタです。
使用する前にアドレスを設定する必要があります。
例えば、int a という変数を作成し、p = &a; とします。

int main(void){
    int *p,i,a;
    p = &a;
    func(p,i);
    printf("%d\n",*p);
    return 0;
}


これでpはaを参照することになります。
つまり、
    printf("%d\n",*p);

    printf("%d\n",a);
は同じ値になります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/26 10:50

    回答ありがとうございます。

    キャンセル

+1

いくつかの回答で網羅されていますが、2つの誤解が組み合わさっているように思います(実引数のアドレスを返せるという誤解+値渡しに関する誤解)。

おそらくやりたいことを実現するには以下のようにする必要があります。

#include <stdio.h>
void func(int **p, int *i);

int main(void){
    int *p,i;
    func(&p, &i);
    printf("%d\n", *p);
    return 0;
}

void func(int **p, int *i){
    *i = 100;
    *p = i;
}

それと、コンパイラには警告という機能があるので、基本これをONにして使うよいです。例えばgccでは普通は-Wallオプションを使います。すると以下のように怪しい箇所を警告してくれます。

ファイル名:行: warning: ‘p’ is used uninitialized in this function [-Wuninitialized]
ファイル名:行: warning: ‘i’ is used uninitialized in this function [-Wuninitialized]

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/26 11:11 編集

    回答有り難うございます。

    キャンセル

同じタグがついた質問を見る

  • C

    4534questions

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