はじめての C

[Learning GNU C]

第12章 関数の 秘訣 trick

12.1. 仮想関数 virtual function とは なにか?

void データ型の 別の 使い方に 関数ポインタを つくることが ある。 これは 十分 進化した fairly advanced プログラミング テクニックだが 非常に 役にたち 満足するものに なる。これが 関数ポインタの 例題だ、

Example 12-1. virtual_function.c

int
main()
{
/* シマッタ、もっと 良いのを 書かないと ... */

return 0;
}

12.2 内部関数 nesting function

GCC では 別の 関数内にある 関数の 定義を 認めている。 こうして 定義された 関数は 内部関数と いわれ 変数と 同じ スコープの 基準 scoping rule に 従う。 親の 関数が 抜け出ると 子の 関数は スコープから 消えて 利用できなくなる。

12.3. 内部関数の 利点

GCC で 与えられる 内部関数の 柔軟性の 理由は おそらく、その性能の 向上が 小さいにも かかわらず、正確に 用いることで 効果が 得られるためだ。 内部関数は 字義どおり (内部の) スコープに 従い それを 含んだ 関数の 変数として 使うことが できる。

こうした 理由により それは 引数として ポインタを とる 関数が 要求される たいていの 仕事を 成し遂げることが できる。 ポインタを 使うと ポインタを もつ 変数は 記憶回路 register で 記憶できないという 理由から ほんの わずか 実行時の ロス performance loss が できる。 ポインタは けっして 機械の 記憶回路を 指し示さない、どうして このポインタが 使えるだろう?

12.4. 内部関数の 宣言と 定義

関数を 定義すると ...

Example 12-2. simple_nested_function.c

#include <stdio.h>

int swap(int *, int *);

int
main()
{
int first = 12, second = 34;

printf("f is %d and s is %d\n", first, second);
swap (&first, &second);
printf("f is %d and s is %d\n", first, second);

return 0;
}

int swap(int *a, int *b)
{
int tmp;

tmp = *a;
*a = *b;
*b = tmp;

return 0;
}

普通の 関数のように 内部関数を 宣言する 必要は ないが もし 望むなら (それは) 可能だ。 そうすることの 唯一の 理由は 読みやすさの ためだろうから 関数を それが 使われる 位置の 近くに もってくることは 好ましいかも しれない。 これは 自分次第だが、内部関数の 宣言を 決めたのなら 自分で それを 確実に correctly 宣言しないと いけない。

12.5. スコープ scope

内部関数は ローカルスコープ local scope を もっていて 内部関数を extern で 宣言すると エラーに なる。 static と inline とは ともに 有効だが この static の 意味が (なにか) 思いつかない。