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

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

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

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

Q&A

解決済

5回答

1671閲覧

間違いの理由を言語化できない

Murasaki_PurPle

総合スコア37

C

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

0グッド

0クリップ

投稿2019/08/17 15:04

for文の誤りを言語化できません

コード中でfor文を使っています。
途中、何が誤りなのか言語化できず困っている箇所があります。

該当のソースコード

#include<stdio.h> float func(float x) { float y; y=x*x; return y; } int main(void){ int a; float b;  b=func(a); for(a=1; a<100; a++){ printf("%f (x=%d)\n", b, a); } }

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

190663631313043456.000000 (x=1) 190663631313043456.000000 (x=2) 190663631313043456.000000 (x=3) 190663631313043456.000000 (x=4) 190663631313043456.000000 (x=5) 190663631313043456.000000 (x=6) 190663631313043456.000000 (x=7) 190663631313043456.000000 (x=8) 190663631313043456.000000 (x=9) 190663631313043456.000000 (x=10) 190663631313043456.000000 (x=11) 190663631313043456.000000 (x=12) 190663631313043456.000000 (x=13) 190663631313043456.000000 (x=14) 190663631313043456.000000 (x=15) 190663631313043456.000000 (x=16) 190663631313043456.000000 (x=17) 190663631313043456.000000 (x=18) 190663631313043456.000000 (x=19) 190663631313043456.000000 (x=20) 190663631313043456.000000 (x=21) 190663631313043456.000000 (x=22) 190663631313043456.000000 (x=23) 190663631313043456.000000 (x=24) 190663631313043456.000000 (x=25) 190663631313043456.000000 (x=26) 190663631313043456.000000 (x=27) 190663631313043456.000000 (x=28) 190663631313043456.000000 (x=29) 190663631313043456.000000 (x=30) 190663631313043456.000000 (x=31) 190663631313043456.000000 (x=32)

もちろん、正しくは「for文の中にb=func(a);を入れるべき」なのですが、なぜfor文より先に宣言してしまってはいけないのかわかりません。
また、表示された結果が何を反映している量なのかがわかりません(y=x*xとしたのに、19066363131043456って数字はどこからきたのでしょうか)。

超素人質問で申し訳ございません。
どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答5

0

多分。
b=func(a);
とすることで、bがfunc(a)と結び付けられる(束縛される)というイメージで捉えてしまったのではないでしょうか。そういう動作をすることになっている言語もあるかも知れませんが、C言語はそうではありません。決して少なくない割合でそういう誤解をしてしまう方をみかけます。

Cでの'=' 代入は、その時点での右辺の値を左辺にコピーするだけです。

#include <stdio.h> int main(void){ int a=0,b=0,c=0; a=b+c; //この時点でaはb+cを計算した結果つまり0がコピーされる  b=100; //bを変更しても、b+cが再計算されるわけでもなく、aの値は変わらない... printf("%d\n",a); //ことを確認。aは0のままです。 return 0; }

b+cでもfunc(a)でも同じこと。b=func(a);は、その時点でのaの値を以てfunc()を実行し、func()からreturnされた値をbに代入(コピー)するだけ、です。

もう一つ言っておくと、Cではローカル変数(関数の{ }の中で宣言される変数)は掃除されません。ご存知かも知れませんが、変数というのはコンピュータのなかにたくさんある「メモリ」の一部を変数として使うよう確保したものです。ローカル変数においては、確保したときに、以前になにかに使っていたデータがそのまま残っています。意味のあるデータならまだマシで、長いデータの一部だったりとかそういうこともあり、ローカル変数の初期値つまり宣言した直後の値は不定(0だとか、0以外だとか、なにか特定の値の条件を期待してはいけない)です。

それと、Cではポインタってやつがあって、一見上記と違う現象が起こっているように見えるかも知れませんが、騙されないように...

(追記)
その点で紛らわしいものにマクロ、なんていうのもあるか。あれはまた普通のプログラムの記述とは全然違う動作原理なのでこういう説明では扱いにくい。
質問者さんには例外的な部分はちょっと棚上げして、まず基本を抑えていただきたく。

投稿2019/08/17 17:29

編集2019/08/18 12:33
thkana

総合スコア7610

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

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

rubato6809

2019/08/18 09:20

> '=' 代入は、その時点での左辺の値を右辺にコピーするだけ ここは右辺・左辺が逆でしょう。「右辺の値を左辺にコピー」とすべきでは。
thkana

2019/08/18 12:27

指摘ありがとうございます。寝ぼけていたようです。本文修正しました。
guest

0

ベストアンサー

多分b=func(a);とすることで、bがfunc(a)と結び付けられる(束縛される)というイメージで捉えてしまったのではないでしょうか。

Cは最も初期に作られたプログラミング言語の1つです。単純なことしかやりません
Cはそれぞれ行にある文(statement)を上から順に実行するだけです。
最近のプログラミング言語はいろいろと補助します(bがfunc(a)と結び付けられるとか?)が、Cは何も補助しないと考えてください。

b=func(a);は関数呼び出しのfunc(a)と代入b=...の2つの部分から成り立っています。
関数呼び出しのfunc(a)a*aをreturnしているので、a*aを結果として返します。
b=...は結果であるa*aをbに代入します。

C

1b=func(1); /* bに1を代入 */ 2b=func(2); /* bに4を代入 */ 3b=func(3); /* bに9を代入 */ 4b=func(4); /* bに16を代入 */

なぜfor文より先に宣言してしまってはいけないのかわかりません。

for文の後であればaに値を代入しますが、for文より先であればaに値を代入(初期化)しません。
Cは上から順に実行するだけです。
代入していない変数の値はそのときメモリにたまたま入っていた数になるので19066363131043456が表示されます。

y=x*xとしたのに、19066363131043456って数字はどこからきたのでしょうか。

xの値の元はint aで、aの値が初期化されていません。
そのときaのメモリにたまたま入っていた数字をx*xしてやってきました。

最近のプログラミング言語はいろいろと補助します。
初期化していないと警告を出したりしますが、Cは何も補助しないと考えてください。

Cを使用するのであれば自分で注意して初期化し忘れをしないように書いてください。

C

1int main(void){ 2 int a; 3 a=0; /* aに0を代入して初期化 */ 4}

Visual Studio 2019のように最近のCなら何か補助があるかもしれません。
Visual Studioのオプションでコンパイラ警告をすべてエラーとして扱うというのがありました。
未初期化変数について何か補助してくれるかもしれません。

投稿2019/08/18 12:03

querykuma

総合スコア777

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

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

0

aを初期化していないために、変数aに適当な値が入ってそのaの値の2乗がbに格納されています。
変数を定義した時点でその変数の中に勝手に値が格納されるようにできているので、aにはコンピュータが決めた適当な値が入っています。試しにprintfでaの値を確認してみてください。また、コンピュータによってランダムに値が決まるので実行するたびに初期化していない変数の値は変わるかもしれません。試してみてください。

1から99までの2乗の値を表示したいなら以下のようにaの値を初期化すれば、正しい結果が得られます。

#include<stdio.h>
float func(int x){
float y;
y=x*x;
return y;
}

int main(void){
int a=1;
float b;
b=func(a);
printf("%f (x=%d)\n",b,a);
for(a=2;a<100;a++){
b=func(a);
printf("%f (x=%d)\n",b,a);
}

return 0;
}

投稿2019/08/18 02:00

sitosama

総合スコア18

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

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

0

int a で確保したメモリ領域にたまたまfloatに出来る値があった、ということでしょうか。
再度実行するとエラーになったり、違う値になったりしませんか?

投稿2019/08/17 15:57

meg_

総合スコア10577

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

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

0

b=func(a);が実行されたタイミングのaは初期化されてない。(ので誤りである)
という説明ではダメなんですかね。

投稿2019/08/17 15:10

gentaro

総合スコア8949

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問