externとか配列とか(C入門中)

(追記: Enterキー押したら投稿されてもうた。ちょっと修正。はてなェ・・・)

何やってるの?

観念して望洋本の入門編を入手したので、読んだり書いたりしています。あぁ、ごく基本的な文法事項の説明がちゃんと載っている・・・ 恥ずかしがらずに最初から入門編を読めばよかった・・・。

他の言語でプログラミングをしたことがあるなら、この本は4章まで斜め読みして、5章(配列)、6章(関数)あたりから読めばよいと思います。

覚えたこと

文字列リテラルの連結

"hoge""moga"とする。Javaのように"hoge" + "moga"ではない。

配列宣言

配列宣言の要素数は、定数でなければならない。関数ローカルな変数は使えない。オブジェクト形式マクロは使える。

配列の初期化
  • 配列の初期化子が足りない場合は0で初期化される。
    • 「足りない場合」というのは、初期化子を1つ以上与えた場合に限られる。
    • 初期化子を1つも与えない場合は、次のように、何らかの(おそらく処理系に依存する)値で初期化される。
#include <stdio.h>

int main(void){

    int vc[3] = {0};
    int vd[3];
    int i;

    for(i = 0; i < 3; i++){
        printf("vc[%d]: %d\t", i, vc[i]);
        printf("vd[%d]: %d\n", i, vd[i]);
    }

    return 0;
}

実行結果。

vc[0]: 0        vd[0]: -858993460
vc[1]: 0        vd[1]: -858993460
vc[2]: 0        vd[2]: -858993460
配列の受渡し
  • 配列の識別子と別の配列の識別子を代入演算子で結んで、丸ごとコピーすることはできない。要素を1つずつコピーする。
  • 関数の仮引数が配列のときは、hoge[]、あるいは *hoge と書くことができる。
  • 配列は参照渡しになる。関数の仮引数にconstをつけると、関数内で値を変更できなくなる。
    • Javaのfinalみたいな感じ。
extern

関数外のどこかで定義された変数を使うときは、externで変数を宣言する。

externで変数を宣言すると、宣言のみを行い、定義を行わない。int hoge; と extern int hoge; は違う。

  • extern宣言をすると、その変数なり関数なりの定義がどこかにあることを、コンパイラが知ることができる。
  • しかし、変数や関数がスコープ内に存在する場合は、extern宣言をしなくても、もちろん使える。
    • それでも書く場合があるのは、可読性のためだろうか?
    • グローバル変数を別ファイルから参照するときに使う。

Javaのstatic importのようなもの、という理解をしている。

  • 参考: POINTER 「補足:externについて」の項

Cでグローバル変数を使用する場合、単純にヘッダファイルで、
int global_variable;
のように宣言し、それを使用する(複数の) .c ファイルで #include している例は多い。
しかし、本来は、グローバル変数は、プログラム全体のどこか一箇所で 定義し、残りの個所では extern すべきである。

POINTER

興味深い。まさにグローバル変数はincludeしまくって使うものだと思っていた(実際そういうコードを見かけるし・・・)。誤解だったみたい。

関数プロトタイプ宣言

main関数より後ろの行で定義した関数を、main関数の中から使えるようにする。そのために、関数の仕様(Javaでいうとメソッドのシグネチャ? インタフェース?)だけを、main関数よりも前に宣言しておく。

仮引数には、名前を与えなくてもよい。

よく分からないこと

オブジェクト形式マクロと変数の使い分け

作法がよく分かっていない。同じファイル内の別の関数から呼ぶときに、マクロにすればよいのか? つまり、判断基準はスコープ次第ということでよいのか?

関数プロトタイプ宣言の使いどころ

Cのコードは、include文、関数プロトタイプ宣言、main関数、その他の関数、の順に並んでいた方が、個人的には読みやすい。しかし、main関数を最後に書くべし、という考え方もあるようだ(望洋本はこちらを推奨している)。それは、関数の仕様を変更したらプロトタイプ宣言と関数定義の両方を修正しなければならないからだ。そういわれると納得できる。

望洋先生がいうように書くのが正しいのかな?

構造体の位置づけ

C言語で書かれたコードを読んでいると、構造体がDTOのような使い方をされていることがある。だから、構造体はクラスの代用だと思っていた。

しかし、入門書を読むとリストの代用として紹介されている。そういう使い方もありなのか。というより、単純にも複雑にも使えるように供されている単なるデータ構造の1つ、という認識でよいのか。

構造体は、異なる要素型を持てるという点で、(Javaの)Listよりはクラスに近いような気がする。