C言語メモ

JavaプログラマのためのC作法」という本を読みながら、C言語について勉強しています。大学ではJavaをメインに習ったのでC言語ってあまりやってないんですよね。さてC言語で気になった点だけメモしておきます。

細かい点いろいろ

  • boolean型がない。そのかわりifでは、整数のようなスカラ型を使う
  • #defineは単なるテキスト置換じゃない

配列

  • Cでは配列の添え字をチェックしない
    • 範囲外の場合、メモリの変なところを書き換えてしまう恐れがある
  • 配列の長さを調べるときはsizeofを使う
    • 配列全体のメモリサイズと一つの配列要素のメモリサイズから要素数を調べる
  • mallocを使っても配列のようなものが作れる
    • 正確には配列ではない
    • できるだけ普通の配列を使うこと。
  • 普通の配列は定数のようなものであり、配列への参照ではない
    • ポインタと同じ振る舞いをするときがあるので、ポインタと勘違いしている人がいる
    • 配列の中身をコピーしたい場合は、forで回す必要があり
    • 式の中で&array[0]と書いても、arrayと書いても意味は同じ

配列は定数であり、変数じゃないので値の代入ができない。しかし、ややこしいことに場合によってはポインタのように振舞う。

int array[3] = {2,5,11};
int *p;

p = array; //正 このときarrayはポインタのように振舞う
//array = p; //誤 arrayは定数なので値を代入できない

さらに、ポインタによる操作で配列の各要素にアクセスできる

int array[3] = {2,5,11};
int *p;
p = array; // &array[0]と同じ
*(p+2) = 13; // array[2]に13を代入

またまた、ややこしいことにポインタは配列と似たような記述方法ができる。

int array[3] = {2,5,11};
int *p;
p = array;
//*(p+2) = 13;
p[2] = 13; //上の式と同じ意味。[]を使ってるけど配列ではない。

文字の扱い

  • 文字列を扱う専用の型はない。数値を文字列として扱う
    • intを使ってテストしたら上手くいかなかった
  • 普通はcharの配列を使う
    • このとき、各文字をシングルクォーテーション「'」で囲むこと
    • ダブルクォーテーション「"」の場合エラーがでる
    • 一番最後には終端記号「\0」を入れる
  • 数値なので加算、減算といった処理ができる
    • 加算や減算を用いて、アルファベットの大文字小文字を変換する例題がよく使われる
  • 文字列を扱うための標準ライブラリとしてstring.hがある

基本

char str[10];
str[0] ='h';
str[1] ='i';
str[2] ='!';
str[3] ='\0'; //終端記号
printf("%s",str);

実行すると、「hi!」と表示される。配列の長さが10とってあるので、添え字が4〜9までの要素は空になってる。また、おそらく「h」、「i」、「!」という文字列はコンパイルするとき最初に、文字コードの数字に変換される。そして、printfの際に、「%s」という記号によって、数値を文字列に直されている。

上の例を楽に書く方法

こっちの場合、終端記号「\0」がいらない。

char str[10] ="hi!";

また添え字を省略することもできる。この場合、文字の長さちょうどの配列が作られる。

char str[] ="hi!";

でも、こういうのは禁止。上の方法が使えるのは、宣言時だけ。

char str[10];
str = "hi!";
全角文字

charのサイズは1バイト。これに対して、日本語のような全角文字は2バイトなので、そのままだとcharに入らない。つまりcharを二つ使う必要がある。ためしに以下のようなコードを実行する

char str[10];
str[0] ='あ';
str[1] ='\0';
printf("%s",str); //b

このとき、私のパソコン環境では「あ」ではなく、「b」という文字が出力された。この方法はいけないらしい。しかし、次の方法では、きちんと表示された。

char str[10] = "あ";
printf("%s",str); //あ

一応うまく表示できたものの、これもまずい使い方かもしれない。もう少し調べてみないとなんともいえない。

文字列をポインタで操作

配列がポインタのように振舞ったのと同じように、文字列もポインタのように振舞う。

char *str;
str = "hi!";
printf("%s",str); //hi!

ポインタの細かい点

  • ポインタの初期値は0
  • 配列名、文字列、関数名それぞれポインタのように振舞う
    • 関数名も場合によってポインタのように振舞う
      • 配列名がポインタの振る舞いをしたように、関数名を括弧なしで書くと、関数を指すポインタのように振舞う
      • 関数の引数に、関数の参照を渡すことによってコールバック関数が実現できる