P124 ポインタと配列で、以下のコードがあります。
static char allocbuf[ALLOCSIZE];
static char allocp = allocbuf;
char *alloc(int n)
{
if(allocbuf + ALLOCSIZE - allocp >= n ) {
allocp += n;
return allocp - n;
} else {
return 0;
}
ここで、
allocp += n;
return allocp - n;
とあります。
allocp += n;
は、不要だと思うのですが何故あるのでしょうか?
(nを足して、引いたものを返している?)
すみませんが、解る方回答をお願いします。
static char allocp = allocbuf;
と、宣言されているところがポイントです。
今、仮に、allocbuf の先頭アドレスが 100、つまり、allocp の初期値が 100 だったとします。
alloc(10) が呼び出されると、
となります。
ということは、alloc() を呼び出し側は、アドレス 100 番地以降に 10 バイトのデータを確保した、という形になります。
で、次に、alloc(20) を呼び出すと、
になります。
これで、最初の alloc(10) と alloc(20) で、割り当てられた領域が重複しないで済みます。
上記ページの「静的グローバル変数」というところに、グローバル変数に static を付けた場合の効能に関して記述があります。
この場合は、関数外で定義された変数がstatic宣言されているので、意味が違います。ファイル外からは見えないという宣言です。こうしておけば、ファイル foo.c と ファイル bar.c で同名の変数を定義しても、別々のものとして扱われます。
まずは、説明から(既に理解されているとは思いますが)。
> allocp += n;
> は、不要だと思うのですが何故あるのでしょうか?
必要です。割り当て済みアドレスを管理している変数なので、その処理を行わないと前回のメモリ割り当て要求時に割り当ててしまっているアドレスを返す事になります。
> (nを足して、引いたものを返している?)
nが足された状態というのは割り当て要求量を加えた割り当て領域最後のアドレスで、ALLOCSIZEを越えてない事の確認用に使っています。そこからnを引いた値は割り当て先頭アドレスでalloc()で割り当ててもらえたアドレス(割り当ててもらえなければ0となる)です。
===
staticについては他の回答者がいわんとしている事はわかるんだけど、表現は正しくないという気がします。
> ファイル外からは見えないという宣言です。こうしておけば、ファイル foo.c と ファイル bar.c で同名の変数を定義しても、別々のものとして扱われます。
シンボルを外部に出さない(ldで結び付けれない)という宣言ですね。
『ファイル外からは見えない』という表現は曖昧です。
実際、アドレス渡せば内容が使えます(参照も変更も行えます)し。
1の説明は正しいですが、それに対する質問者のお返事は誤解している様に見える内容となっています。
> staticで宣言されているから、変更が保存される訳ですね。
staticという修飾がなくても値が保存されるし正常に動作しますよ。
関数内では呼ばれるたびにスタックが生成・終了した時にそのスタックが破棄される可能性があるため関数内のauto変数では値が保持されないです。
しかし、大域変数(global)だと恒久的に割り当てられるので値は保持され続けます。staticであろうがなかろうが。
それと、回答1の参照ページ中にある以下の記述ですが、
>更にもう1つ試してほしいのが、 main.cのg_numの宣言にstaticを付けることです。staticを付けると、静的グローバル変数となり、main.c以外からはアクセスできなくなります。そのため、例えextern付きで宣言してもsub.cから、g_numをアクセスすることはできません。よってこの場合も、「g_numの定義が見つからない」というエラーになります。
シンボルを導出しないのでg_numという名前は参照できませんが、そのアドレスを渡せばアドレス介してアクセスする事は可能ですので『main.c以外からはアクセスできなくなり』というのは表現として微妙です。(アクセスが拒否されるなど阻害されたりはしないかと。)
なるほど!!
有難う御座います。
staticで宣言されているから、変更が保存される訳ですね。
で、返り値は-nされたところのアドレスという訳で...。
【補足】
ローカル変数の宣言にstatic を付けると、プログラム開始時にメモリに記憶され、
関数を終了しても保持している値が消えることがなくなる (リンク先より)
大変よく分かりました。
機会がありましたら、また宜しくお願いします。