プログラミング C 03 - Soft Forum P.C. Club

取っ掛かりを終了し, 本格的にC言語の解説を始めます.

変数, 型について説明します.

main関数(entry point)

毎回必ずmainという関数を書いているのに気が付きましたか? というかこれだけ書かして何の説明もなしってどういうことなんだって感じですが.

これはprogramが実行されると最初に実行される関数です. programが実行されるとELFインタープリタからmain関数が実行されます.(理解しなくて大丈夫. わざと難しく書いています.)

変数(variable)

変数っていうテーマで今回行います. 変数って名前, いかにも数学的ですが, 変数があればもちろん定数もあることだけ覚えておいてもらえれば...

変数とは, データを入れる箱であるとよく言われます. C/C++言語では実際そのものぴったりで, 本当に箱です.

次のコード例を見てください.

#include <stdio.h>

int main(int argc, char **argv) {
  int i = 10;
  printf("%d\n", i);
  return 0;
}

intっていうのは変数の型です. またあれな例なんですが, 「コンピュータは01で動いてる!」っていうのを実はここで感じることができたりしちゃったりします. データは蓋を開けたらほんとに01しかなくて, コッチ側はある一定の決まりをもったある一定の大きさのデータをひとかたまりにして, 決まり通りに扱うことで, さも様々なデータが存在するかのように扱うわけです.

ここでは, integer, つまり整数のデータの入れ物を宣言しています. 宣言とは, 「今から使うよ!」とコンパイラに向かってまさに「宣言」しているわけです. そして, このデータは整数として扱うよというのもコンパイラに伝えています.

こうして確保した領域に, 10という値を代入しています. これよりint型の変数iの中には10というデータが入っているわけです. それをprintfで%d(decimal)で表示します.

また, ある関数で使う変数は, 関数のはじめで宣言しなければいけません.

#include <stdio.h>

int main(int argc, char **argv) {
  printf("%d\n", 10);
  int i = 10;
  printf("%d\n", i);
  return 0;
}

はダメだということです. これは現在のgccではまあこれなのですが, C99の仕様的には途中宣言可能になっています. ただ, オプションが必要なので, この場合は移植性も考えこの形式で行きます.

変数名(identifier)とキーワード(keyword)

今さっきの例ではint型変数iとしました. このi, 数学とかではa-zやギリシャ文字を使って変数を表したりしますが, Cではある程度好きな長さが使えます. 昔のものだと31文字までとかありますが...

#include <stdio.h>

int main(int argc, char **argv) {
  int this_is_integer = 10;
  return 0;
}

みたいに. 変数の名前を識別子(identifier)といいます. これは豆知識的なので覚える必要はほぼないです.

これには使えないものがあって, 数字及び英文字(大文字小文字区別する)と_(アンダースコア)が使えます.

this_is_integer
array2pointer
ThisIsInteger
_KOREMO_daijoubu

みたいな感じです. しかし, 先頭文字は数字を使えません.

02_is_integer_janai

はダメと言うことです. これは, 簡単に言えば数字のリテラルと区別がつきにくいからで, コンパイラの都合上丁度いいからです. コンパイラとしては, 最初の一文字を見た時点でidentifierか数値リテラルか区別したいのでこのようになっています.

また, 変数にintなんて名前をつけられると困ってしまいます. そこで, コンパイラが特別扱いする名前のことをキーワードといい, これも変数名には使えなくなっています.

型(type)

int以外にもたくさんの型があります. ここでは特に使うであろう物を...

以下の大きさについては, 現在主流のPCにおいてはという意味で, 実は正確性に欠けます.

stdint.hには正確極まりないものがあります... (ex: uint32_t)

型名大きさ説明
int4整数
long4大きな整数
short2小さな整数
char1文字
float4浮動少数点数
double8倍精度浮動少数点数

C言語の特徴であり, そして強みであり, またハマリどころでもあるのですが, これらの型というのは, コンパイラの決めた決まりごとに従って私たちが扱うデータであり, 実態は結局01です.

それを今から表示することができます. 以下のprogramを作って実行してみてください.

#include <stdio.h>

int main(int argc, char **argv) {
  char ch = 'a';
  printf("%c = %d\n", ch, ch);
  return 0;
}

'a'はsingle quoteに注意です.

a = 97

と出たら大丈夫です. %cは文字, %dは数値として引数を考え, それを印字するのでした.

char ch = 'a';でchの中には文字aの情報が入ります. そしてもちろん, これは01のデータです. これを私たちが「文字だ!」と考えたらaで, この同じ01のデータを「数字だ!」と考えたら97だったということです.

01の中で文字を表すには文字に数字を割り当てて良くやり方を取ります. これが俗に言う文字コードというものです.

この決まりの中で, 文字aは数字97で表されていたということです.

数値97と文字aのデータは大きさ以外は同じデータです. このように同じデータでも, こちらの受け取る決まり次第で全く違った意味に取れます.

今はあんまりわかんなくても大丈夫です. ただ, 結局はデータであるということ, 型は私たちがこのデータをどういうふうに考えているかをコンパイラに伝えているのだということが伝われば.

リテラル(literal)

10とか, そのままデータを書いてきました. これをリテラルといいます.

int main(int argc, char **argv) {
  // 'a' は文字リテラル
  char ch = 'a';

  // "This is string" は文字列リテラル
  const char * str = "This is string";

  // 10は数値リテラル
  int i = 10;

  // 0.1は数値リテラル
  float f = 0.1;

  // 20e30は数値リテラル
  double d = 20e30;

  return 0;
}

というふうにいろいろ書けます. 文字列リテラルを受ける変数の宣言が見慣れない物だらけだと思いますが, しばらくは文字列リテラルを変数にとることはしません. きちんと解説が出来る段階まで後回しします.

(自分で調べたい人用に: 変更不可能であるためconstであり, 文字ポインタで先頭ポインタを受け取る必要がある. C++0xではconstが抜けるとコンパイル不可になるそうで...)

符号の有無(signed, unsigned)

計算機基礎などの授業を受けた方はわかることですが, 受けてない方にもわかるように説明します.

int は4byte, つまり0/1が8*4の32こで出来ています. これで表せるパターンは2の32乗ですね.

もしあなたが負の数も考えたいとします. すると, その数が+であるか-であるかを表すために1bit欲しいですね. このbitを一般には左端のbitをとり, これをMSB(Most Significant Bit)といいます.

で, それを考えると, 数字に使えるのは31bitであるということになります. この範囲によって, intの表せる数字の範囲が分かります.

しかし, もしあなたが負数を考える必要がなければ, 0から2の32乗-1までで+の数を2倍大きな数まで考えることができます.

C言語は非常にprimitiveなので, これをこちら側で選べます. それがsigned or unsignedです.

ちなみに, 通常intとかくと, singed intのことです.

int main(int argc, char **argv) {
  // 符号なし(unsigned)の整数(int)
  unsigned int ui = 1000000;
  // 符号あり(signed)の整数(int)
  signed int si = -1000000;
  return 0;
}

このように選ぶことができます.

Soft Forum P.C. Club