- ベストアンサー
C言語の代入についての質問
- C言語の代入についての質問です。プログラム内の特定の代入文がエラーとなる理由を知りたいです。
- C言語の代入についての質問です。プログラム内での3行目の代入文がエラーとなり、その理由を知りたいです。
- C言語の代入に関する質問です。プログラム内の特定の代入文がエラーとなる理由について教えてください。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
追加:グローバル変数はとにかく初期化しておいた方が安全、と思います(意見を異にする人もいますが)。 ---- もしかして、私が間違ったことを言っていないか、検索してみたのですが。 (以下は、分からなくてもOKです。c言語はあまり初心者向きでない部分が多いので、最初から覚えようとすると混乱します)。 int global_x; というような(externをつけない)形を関数の外に書くと、初期化されていないグローバル変数の定義(メモリを確保する)になるのですが、分割コンパイルの場合、同じ定義が複数のソースファイルにあってはいけないと思い込んでいたのです。しかしこの場合は、別にエラーにならないようです。そして、同じ型・名前の初期化されていないグローバル変数が複数定義されていた場合、同じオブジェクトとされるようです。1箇所だけ初期化があっても大丈夫。ただし、2箇所以上で初期化が行われるとエラーのようです。・・・ということは、複数の人間で分担してプログラミングしている場合、2人のプログラマが相手の作業を知らずに、たまたま同じ名前の初期化されていない変数を定義した場合、警告も出ずに同じグローバル変数となってしまうので、わけのわからないバグが出る可能性がありますね。これは結構怖いです。 一応、初期化されていないグローバル変数・静的変数は0で初期化されるはずですが、「それをあてにしてはいけない」というc言語プログラマも多いようです。 ・・・やはり最初慣れるまでは、危うきに近づかず、ということで、いちいち初期化した方がよさそうです。
その他の回答 (6)
- kmee
- ベストアンサー率55% (1857/3366)
グローバル変数は、main関数が呼ばれる前に「初期化」されます。 たとえば int x[2]={1,1} ; とあれば、x[0]=1, x[1]=1に初期化されます。 ただし、実行順番は環境依存です。 対し、 int x[2] ;の後の x[0] = x[1] = 1; は命令文です。 初期値を代入する、という意味で初期化ではありますが、C言語の仕様としての「初期化」ではありません。 これが実行できてしまうと「最初にmain関数を実行する」というC言語の仕様に矛盾することになります。 宣言と同時に初期化したい場合は、初期化子を使った「初期化」をする 代入式を使いたかったら、main関数の中に書く というのがCの約束です。
お礼
C言語の仕様としての初期化でなければ、main関数の外部で行ってはいけないのですね。それが決まりなら仕方がありません。教えていただきありがとうございました。
一応、念のため。 int x[2]={1,1}; の「=」は代入演算子ではなく、初期化を表し、最初に1度だけ初期化されます。 また、c言語は、複数のソースファイルをコンパイルして結合して一つの実行ファイルを作れますが、この場合、このような「定義」は1箇所でしか許されません。他のファイルでxを使いたい場合は、 extern int x[2]; というような「どこかで定義されるxを使うよ」という宣言だけにします(普通はこういう宣言は手作りのヘッダーファイルに入れて、定義は.cのソースファイルに書くことが多いです。) とはいえ、 ※ どうしても必用がある場合以外は、できるだけ、外部変数は使わない方がいい です。 外部変数は、あまりにも適用範囲が広すぎるからです。
お礼
私はファイルを複数使うプログラムを作成したことがないのでグローバル変数の使用は影響が少ないと思うのですが、これからC言語を学んでいく上でファイルが2つになったりする可能性があるので、必要以上にグローバル変数を定義するのは控えたほうがよさそうですね。御意見ありがとうございました。
- bajutsu
- ベストアンサー率20% (139/693)
>私はグローバス変数として定義されたx[2]にx[0]=x[1]=1と代入してからmainを実行するのかと思っていましたが、もしかして代入はmain関数の外ではできないのですか Cのプログラムは、mainから始まります。 だから、「代入してから」「mainが動く」のはおかしいと思いませんか?
お礼
おっしゃるとおりです。Cの基本的なところがまだまだ理解できていないようです。教えていただきありがとうございました。
No.1さんのおっしゃるとおり、どんなタイミングで実行されるかわからないなどの理由で、トップレベルで実行文を書くことはできません。 c言語の仕様です。 一応、 int x[2]={1,1}; の形だと、実行文ではなく、(初期化を伴った)定義なので、コンパイラも通るはずです。
お礼
taparonさんの言うとおりにしたら、コンパイラが上手くいきました。やはりそれがC言語の決まりである以上はそれに従うしかありませんね。御意見ありがとうございました。
- puyo3155
- ベストアンサー率34% (229/663)
なぜって言っても、質問文中にあるように、そういう決まりだから。としか言えません。 プログラミング言語とはそもそも、 テキストで書いたわかりやすい表現のプログラム > マシン語 に変換するための、プログラムです。コンピュータはそもそも、マシン語しか実行できないので、コンパイルさたマシン語には、プログラミング言語は無関係です。(マシン語の展開の仕方に特徴はあったとしても) したがって、プログラミング言語の違いは、いかにしてコンピータを利用する上で必要となる機能を、分かりやすく表現するかで決まるわけです。したがって、なぜ、そうなるか?に、本質的な応えはありません。 C言語のルールによれば、 実行は、main という関数から行われる その前には、変数の定義や、取り込むべきライブラリを記述する ということで、代入というのは、実行機能なので、main にかかなければならない。 というだけのことです。別の言語を開発して、変数宣言とともに、初期値を代入すると決めれば、そういうプログラミング言語を作ることだって可能です。
お礼
やはりそういうものなのですね。それがC言語のルールなのであれば仕方がありません。御意見ありがとうございました。
- yorozu_ya
- ベストアンサー率54% (76/140)
もしエラーにならないとしたら、 どういう順序で実行されることを期待しますか? ※ main関数から実行開始されることは理解してますよね。
お礼
私はグローバス変数として定義されたx[2]にx[0]=x[1]=1と代入してからmainを実行するのかと思っていましたが、もしかして代入はmain関数の外ではできないのですか?
お礼
ここまで詳しく教えていただきありがとうございます。勉強になりました。C言語は結構微妙なところがあるので私も悩むことがあります。それにコンパイラの勉強をしたら、パソコンによって処理のされ方が違うなどとも書いてありましたし。でも初期値の設定をするのは必ずmainの中で、これはC言語の決まりごとですからどのパソコンでも同じです。今後は初期化はなるべくmainのなかで、そしてグローバル変数の多用を避けるようにしたいと思います。それが正しく動作をさせるプログラミングの基本になるはずですから。本当にありがとうございました。