C/C++ - 構造的プログラミング編 第1回 〜制御構文と演算子〜

真偽値と演算子

C 言語には、真偽値を値とする型が存在せず、リテラル、 または整数の値からその都度判定することとなる。

基本的に、偽となる真偽値には、次のものがある。

 整数リテラル     0
 浮動小数点数リテラル 0.
 文字リテラル     '\0'
 NULL定数       NULL

偽とならない全ての値は真である。たとえば、文字リテラル '0' は、真を表す真偽値である。

真偽値 v に対して、

!v

は、v が偽であるとき真、真であるとき偽を返す真偽値を返す。

2つの真偽値 v1, v2 に対して、

v1&&v2

は、v1 が 真であり v2 も真であるならば、その時に限り真の値を返す。

変数

変化させられるリテラル、つまり、型と値を持ち、それ自身を示す名前・シンボルと、 それ自身に対する固有のリテラルである、ポインタと呼ばれる4つの要素を持つ構造。

リテラルが右辺値であるわけで、ポインタは左辺値になる。

自動変数

型Tとする名前tの自動変数の宣言は、

T t;

である。値を取得するときは、ただ、

t;

となり、ポインタを取得するときは、&オペレータを用いて、

&t;

とする。

宣言時に=オペレータを用いると左辺の値を、右辺のリテラル、または変数の値で初期化する。

T t=t1;

自動変数の生存期間は、宣言時から現在のスコープ間であり、 スコープを抜けた瞬間に自動変数は破壊される。

静的変数

型Tとする名前tの静的変数の宣言は、

static T t;

である。自動変数と異なるのは、その生存期間であり、 プログラムの最初から最後までである。プログラムの開始と同時に値が初期化される。

ポインタ変数

本来、左辺値であるポインタを右辺値、つまり、値としてとる変数である。 型Tの変数のポインタを値としてとるポインタ変数の宣言は、

T *p;

である。pは、型 T * のポインタ変数である。

変数である以上、初期化、

T *p=&t;

を行うことができ、単独で p; とすれば値としてもつポインタの取得をし、 そして、&p; とすれば、ポインタ変数 p 自身がもつリテラルとしてのポインタを取得することができる。

ポインタ変数は、*オペレータを持ち、

*p;

とすることで、p が値としてもつポインタをリテラルとする変数として機能する。

関数

大きく分けて2つの機能を持つが、まぁ、とりあえず、他のスコープから初期化して、 他のスコープに値を渡す構造である。

他のスコープ側の立場に立つと、要するに、ある初期化値を与えることで、 新しく値、リテラルを構築するものである。

型 S と型 U の変数、s,u で初期化し、型 T の値を返す関数 f の宣言は、

T f(S s, U u);

である。

s,u は関数の定義スコープ間で有効な変数として機能する。定義内で型 T の変数、リテラル t に対して、

return t;

とすることで、関数f(s1,u1)は型Tでtの値を持つリテラルとして機能することとなる。

s1, u1 は引数と呼ばれ、t が戻り値と呼ばれる。

代入オペレータ

変数に=オペレータをつけると、右辺の値を左辺の値に代入する。このとき、右辺の型と 左辺の型は等しくなくてはならない。

T t=t1, s=s1;
T *p=&t, *q=&s;

となるような初期化がなされている各変数に対して、 t=s;としたり、t=*p;、あるいはp=qや、*p=*q とするときは、左辺と右辺の型が等しいため代入可能である。

右辺値とは、そのまんま、この代入オペレータ=の右辺にある変数の値である。 それに対応して、左辺値は代入オペレータ=の左辺にある変数のポインタとなるわけで、 ポインタを持っていないリテラルなどが左辺にくることはあり得ない。

本来左辺値であるポインタも、左辺がそれを右辺値とすることができるポインタ変数ならば、 &オペレータを経由して代入することができる。

キャスト

左辺と右辺の型が等しくなければ代入オペレータは使用できない。 したがって、型が違うときに代入したい場合は、右辺の型を変換しなくてはならない。

型 S の変数 s を型 T に変換した変数は、

(T)s;

と表される。(T)s; は、型Tの変数として機能する。こういう奴を静的キャストとかって呼ぶんだな。

型 S * の変数 p を型 T * の変数に変換した変数は、

(T *)p;

と表される。もちろん、(T *)p; は、型T *の変数として機能するわけで、こういう奴を再解釈キャストって呼ぶ。

型と sizeof オペレータ

リテラルと変数の双方に対して、型ってのが定義されてるわけで、 型ってのは、各変数やリテラルを区別するための使われる。

区別するってのは、結局のところ、その値を記憶するための方法を区別するってことであり、 型が違えば、記憶の方法が変わることとなる。

記憶の方法って、要するにメモリに0,1で記録するわけで、8ビットを1バイトとして、こいつを基本単位として 記録してくこととなる。

sizeofオペレータは、リテラルや変数、そして型に対して作用することで、この記憶する領域の大きさを 返すものとして機能する。

T t=t1;

に対して、sizeof(T)もsizeof(t)も、もちろん、sizeof(t1)も機能するわけだな。


文章作成 : yukki-ts (-+-twilight serenade-+- [stage])