知っていると、複雑なif文の条件式を簡潔に記述できることがある。
if節とelse節(またはelse if節)に同じようなコードを記述している場合は、再考すべし。
A || A == A && A == A
A || B == B || A A && B == B && A
(A || B) || C == A || (B || C) (A && B) && C == A && (B && C)
(A || B) && A == A (A && B) || A == A
(A || B) && C == (A && C) || (B && C) (A && B) || C == (A || C) && (B || C)
(A || !A) == TRUE (A && !A) == FALSE
!(A && B) == !A || !B !(A || B) == !A && !B
A || TRUE == TRUE A && TRUE == A A || FALSE == A A && FALSE == FALSE
ブーリアン型は一般的に TRUE(0以外) と FALSE(0) の整数値で表わされる。
ただし、実際にTRUEの値がいくつに定義されているかに注意する必要がある。
TRUE | FALSE | |
C++ | 1 | 0 |
VB | -1 | 0 |
C++のクラス(class, struct)の場合は、仮想関数テーブルへのポインタ変数など自動的に含まれてしまうことがあるため、単純に定義したメンバだけでサイズの計算ができないので注意。
ここではC言語の構造体について述べる。
以下の構造体を例として、構造体のメンバ変数の相対位置とサイズを考える。
#pragma pack(4) // コンパイラのオプションとしてアライメントを 4 に設定した場合 struct A{ char a; short b; long c; double d; char e; };
項目 | サイズ | アライメント |
struct A | ||
char a | 1 | 1 |
short b | 2 | 2 |
long c | 4 | 4 |
double d | 8 | 4 |
char e | 1 | 1 |
項目 | サイズ | アライメント |
struct A | ||
char a | 1 | 1 |
パディング | 1 | - |
short b | 2 | 2 |
long c | 4 | 4 |
double d | 8 | 4 |
char e | 1 | 1 |
項目 | サイズ | アライメント |
struct A | 20 | 4 |
char a | 1 | 1 |
パディング | 1 | - |
short b | 2 | 2 |
long c | 4 | 4 |
double d | 8 | 4 |
char e | 1 | 1 |
パディング | 3 | - |
これで、構造体のメンバ変数の相対位置とサイズが決定する。
struct B{ char f; short g[2]; char h; struct A i; };別の構造体のメンバ変数が含まれている場合は、内側の構造体から同様に考えていけばよい。
項目 | サイズ | アライメント |
struct B | 28 | 4 |
char f | 1 | 1 |
パディング | 1 | - |
short g[2] | 4 | 2 |
char h | 1 | 1 |
パディング | 1 | - |
strcut A i | 20 | 4 |
浮動小数点で一般的に利用されている表現方式。
小数を正規化(「1.xxx * 2^n」の形にすること)して符号、指数部、仮数部に分けて格納する。
代表的なのは、32ビット単精度(single/float)と64ビット倍精度(double)の2種類。
+なら0、-なら1。
2を基数として正規化した数「1.xxx… * 2^n」の n を格納する。
負の数を表現するために、バイアス方式を用いる。単精度なら127、倍精度なら1023を加える。
2の補数を用いない理由は、浮動小数点同士の比較を単純に行うため。
正規化した数「1.xxx… * 2^n」の xxx… の部分を格納する。
<32ビット単精度> 1 8 23 ビット幅 +-+--------+-----------------------+ |S| Exp | Fraction | +-+--------+-----------------------+ 31 30 23 22 0 ビット番号 <64ビット倍精度> 1 11 52 ビット幅 +-+-----------+----------------------------------------------------+ |S| Exp | Fraction | +-+-----------+----------------------------------------------------+ 63 62 52 51 0 ビット番号 S は符号部、Exp は指数部、Fraction は仮数部
例:「-5.25」
例:- なので「1」
例:「5.25」
例:「5.25」→「101.01」
例:「101.01」→「1.0101 * 2^2」
例:「0101」→「01010000000000000000000」
例:「2+127=129」→「10000001」
例:「1 10000001 01010000000000000000000」→「0xC0A80000」
∞など
符号/指数部/仮数部それぞれ、変換して格納される。
0 か 1 をそのまま格納する。
バイアスを考慮した変換を行う。(127引いて、1023加える)
29ビット増えることになるため、0 で埋める。これによって小数点以下7桁目近辺の値にゴミが発生することがある。(最初からdouble型で表現しているときよりもゴミが大きくなるか、同じ値になる)
全て32bitに拡張され、呼出規約に従ってスタックに積まれ、使用後にクリアされる。
名称 | 説明 | 引数の渡し方 | スタックのクリア | 関数名の修飾(マングル) ※元はfunc()とする | 大文字/小文字の変換 | VC++でのキーワード |
cdecl | C/C++ プログラムのデフォルトの呼出規約。 可変引数リストを使用可能。 関数呼び出し毎にスタックのクリアコードが生成されるため、実行コードが大きくなる。 | 右から左にスタックに積まれる。 | 呼び出し側 | _func | なし | __cdecl |
stdcall | Win32API用の呼出規約。 Cで作ったDLLの関数をVBで呼ぶ場合はこれにする。 | 右から左にスタックに積まれる。 | 呼び出された側 | _func@12 ※末尾の数字は引数の合計バイト(10進) | なし | __stdcall |
fastcall | 高速にアクセスできるレジスタを使用した呼出規約。 実行時の効率重視。 | 最初の2つの32bit以下の引数はECX,EDXに入れて渡される。 それ以外は、右から左にスタックに積まれる。 | 呼び出された側 | @func@12 ※末尾の数字は引数の合計バイト(10進) | なし | __fastcall |
thiscall (可変引数リストなし) | クラスのメンバ関数用の呼出規約。 可変引数リストを使用可能。 可変引数リストを使用するか否かで規約内容が異なる。 | thisポインタがECXに入れて渡される。それ以外はstdcallと同様。 | なし | |||
thiscall (可変引数リストあり) | 引数を右から左にスタックに積んだ後、thisポインタも積む。それ以外はcdeclと同様。 |
一致するデータが存在する場合のソート結果が定まっているものを安定ソート、未定義のものを非安定ソートと呼ぶ。
バブルソートは安定ソート、クイックソートは非安定ソートである。
非安定ソートであっても、比較処理を工夫することで安定化できる場合がある。(各データにユニークな値が必要)
比較処理の例