###前提・実現したいこと
作成したプログラムを動くようにしたいのですが、エラーが出て動きません
どう変更すれば動くでしょうか
###発生している問題・エラーメッセージ
パラメータは一度も使用されていない
代入した値は使われていない
###該当のソースコード
#include <stdio.h>
int func(int a, long b)
{
a = 20;
b = 50;
return 0;
}
int main(void)
{
int a = 30;
long b = 90;
func(a, b); printf("a = %d\n",a); printf("b = %ld\n",b); return 0;
}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/08/19 08:27
回答3件
0
要旨
- ご質問のコードではエラーは出ませんでした。
- Cの関数では基本的に引数の値は変更されません。
- 関数で変数の値の書き換えを望むのであればポインタ渡しを使うべきです。
説明
私の環境での動作結果
まず、ご質問のコードを私の環境でコンパイル、実行してみました。
linux の gcc です。
bash
1$ cat sample.c 2#include <stdio.h> 3 4int func(int a, long b) 5{ 6a = 20; 7b = 50; 8 9return 0; 10} 11int main(void) 12{ 13int a = 30; 14long b = 90; 15 16func(a, b); 17 18printf("a = %d\n",a); 19printf("b = %ld\n",b); 20 21return 0; 22} 23$ gcc -o sample sample.c 24$ ./sample 25a = 30 26b = 90 27$
以上のように私の環境ではエラーはでませんでした。
もしも、あなたの環境で以上と異なるエラーメッセージが出ているのであれば、
そのエラーメッセージを質問に追加してください。
私にそのエラーが分かれば回答できますし、
できなくても他の方に回答してもらえる可能性が生まれます。
(エラーメッセージが記述されていないと、そのエラーメッセージについて詳しい人でも答えようがありません。)
もしも、あなたの環境でも以上と同様の動作結果であったのであれば、
以下の部分は、
発生している問題・エラーメッセージ
パラメータは一度も使用されていない
代入した値は使われていない
と書くよりも
発生している問題・エラーメッセージ
エラーメッセージはでていません
と書いた方が、回答者に正しく情報が伝わると思います。
(もう一ヶ所「エラーが出て」と書かれている部分がありますが、そこもなくしてしまった方が、誤解されず、回答が得られやすくなると思います。)
質問意図に関する私の推測
エラーメッセージが出ていないので、
作成したプログラムを動くようにしたいのですが、エラーが出て動きません
どう変更すれば動くでしょうか
とのご質問に直接お答えすることはできませんが、ご質問のコードと実行結果から、
以下のような質問意図ではなかったかと私は推測しました。(外していたらごめんなさい)
変数 a, b の内容を関数 func() によって変更しようとしたのですが、
実行された結果を見ると、func() を呼び出す前の値と同じで、書き換わっていません。
どのように記述すれば、書き換えることができるのでしょうか?
推測した質問に関する答え
目的の結果が得られるコード
以下のように記述すれば、ご期待の結果になると思います。
bash
1$ cat sample2.c 2#include <stdio.h> 3 4int func(int *a, long *b) 5{ 6*a = 20; 7*b = 50; 8 9return 0; 10} 11int main(void) 12{ 13int a = 30; 14long b = 90; 15 16func(&a, &b); 17 18printf("a = %d\n",a); 19printf("b = %ld\n",b); 20 21return 0; 22} 23$ gcc -o sample2 sample2.c 24$ ./sample2 25a = 20 26b = 50 27$
■ コードの説明
以下にコードの動作に関するざっくりとした説明を書きます。
このプログラムの動作に関して、あなたがどう動作すると予想し、
現在の動作にどのような疑問をもたれているかを質問に書いていただけると、
もうすこし立ち入った説明ができると思うのですが、
現状ではその辺りがよくわからないので、おおまかな説明だけ書きます。
これで分からない場合(多分これだけではよくわからないと思うので)は、
以下の項目に関して調べて見てください。
- 大域変数(グローバール変数)と局地変数(ローカル変数)
- 値渡しとポインタ渡し
元のコードにおける動作
C言語の関数における引数の扱いは「値渡し」と呼ばれる方法が使われます。
最初のコードで、変数a に関して説明すると以下のような動きになります。
ポイントは、関数main()に置ける変数 a と func() 関数における変数 a はまったくの別物(それぞれの変数のローカル変数)であるということです。
サンプルリスト1(変更前) 1 #include <stdio.h> 2 3 int func(int a, long b) 4 { 5 a = 20; 6 b = 50; 7 8 return 0; 9 } 10 int main(void) 11 { 12 int a = 30; 13 long b = 90; 14 15 func(a, b); 16 17 printf("a = %d\n",a); 18 printf("b = %ld\n",b); 19 20 return 0; 21 }
- (12行目「int a」辺り) 関数main()で int 型の入れ物を用意する(仮に「入れ物一番」とします)。
- (12行目「int a」辺り) 上で用意した入れ物に「a」という(関数main()の中出だけ有効な)名前をつける。(関数main()の変数a)
- (12行目「= 30」辺り) 関数main()の変数a(入れ物一番)に値30を入れる。
- (15 行目)関数main()の変数a の 値 を第一引数として、関数func()を 呼び出す
- (3行目「int a」辺り)関数 func() では、第一引数の値を入れるために ** int 型 ** の入れ物を用意する(仮に「入れ物二番」とします)。
- (3 行目「int a 」辺り)上で用意した入れ物(入れ物二番)にaという(関数func()の中でだけ有効な)名前をつける。(関数func()の変数a)
- (3行目「int a」辺り)関数func()の変数a(入れ物二番)に、第一引数の値 ** 30 ** を入れる。
- (5行目) 関数func()の変数a(入れ物二番)に、値 20 を入れる
- (8行目)関数func()のを終了し、関数main()に戻る(ここで「入れ物二番」(関数func()の変数a)は中の値共々捨てられる)
- (17行目) 関数main()の変数a(入れ物一番)の値(この場合、12行目で設定した 30)を出力する。
つまり、12行目で宣言した変数 a は、初期化で値 30 を代入された後、まったく変更されていません。
変更したコードにおける動作
次に、変更したコードにおける動作を説明します。
このコードでは、引数の渡し方を変えています。
ポイントは、関数func()の変数 a が持つのは、関数main()の変数a へのポインタであるということです。
サンプルリスト2(変更後) 1 #include <stdio.h> 2 3 int func(int *a, long *b) 4 { 5 *a = 20; 6 *b = 50; 7 8 return 0; 9 } 10 int main(void) 11 { 12 int a = 30; 13 long b = 90; 14 15 func(&a, &b); 16 17 printf("a = %d\n",a); 18 printf("b = %ld\n",b); 19 20 return 0; 21 }
- (12行目「int a」辺り) 関数 main()で int 型の入れ物を用意する(仮に「入れ物一番」とします)。
- (12行目「int a」辺り) 上で用意した入れ物に「a」という(main()関数の中出だけ有効な)名前をつける。(関数main()の変数a)
- (12行目「= 30」辺り) 関数 main()の変数a(入れ物一番)に値30を入れる。
- (15 行目) 関数 main() の 変数a の ポインタ(入れ物一番のアドレス) を第一引数として、func() 関数を 呼び出す
- (3行目「int *a」辺り) 関数 func() では、第一引数の値を入れるために int 型の ** ポインタ ** の入れ物を用意する(仮に「入れ物二番」とします)。
- (3 行目「int a 」辺り) 上で用意した入れ物(入れ物二番)にaという(関数func()の中でだけ有効な)名前をつける。(関数func()の変数a)
- (3行目「int a」辺り) 関数 func()の変数a(入れ物二番)に、第一引数の値である ** 関数main()の変数aへのポインタ(入れ物一番のアドレス) ** を入れる。
- (5行目) 関数 func() 変数a(入れ物二番)*が値として持つポインタの示す変数(関数main()の変数a(入れ物一番))へ、値 20 を入れる
- (8行目)関数 func() を終了し、関数main()に戻る(ここで「入れ物二番」(func() における変数a)は中の値共々捨てられる)
- (17行め) 関数main() の変数a(入れ物一番)の値(この場合、5行目で設定した 20)を出力する。
投稿2016/08/19 10:30
総合スコア1193
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
変数と有効範囲(スコープ)を理解されていないように感じました。
関数main()で宣言した変数a,bは関数main()の中でしか有効ではありません。
こんなページがありますのでごらんになってください。
局所変数,大域変数,有効範囲
投稿2016/08/19 08:11
総合スコア356
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
環境によりけりでしょうか?Visual Studioでやったら普通にコンパイルできましたが。
ただ、この処理ですが関数の引数は値渡しをしている(アドレスを渡していない)ため意味のないことをしています。
参照渡しをしなければ値を変えることはできません。
関数の仮引数というのは呼び出す前に生成され、実引数が代入され、関数が終了するときに仮引数が解放されます。
仮引数は関数終了後に捨てられるので、代入しても無意味です。
つまりは、以下のようにポインタを渡して編集すれば、ポインタが関数終了時に破棄されても編集するのはアドレスの指す先なんで問題ないです。
C
1int func(int *a, long *b) 2{ 3*a = 20; 4*b = 50; 5 6return 0; 7} 8int main(void) 9{ 10int a = 30; 11long b = 90; 12 13func(&a, &b); 14 15printf("a = %d\n",a); 16printf("b = %ld\n",b); 17 18return 0; 19}
投稿2016/08/19 08:07
総合スコア161
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。