K&Rのポインタについて質問です。


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を足して、引いたものを返している?)

すみませんが、解る方回答をお願いします。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:
  • 終了:2011/05/30 17:05:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答4件)

id:JULY No.1

回答回数966ベストアンサー獲得回数247

ポイント23pt
static char allocp = allocbuf;

と、宣言されているところがポイントです。

今、仮に、allocbuf の先頭アドレスが 100、つまり、allocp の初期値が 100 だったとします。

alloc(10) が呼び出されると、

  • alloc() の戻り値は 100
  • alloc() から戻ってきた時の allocp の値は 110

となります。

ということは、alloc() を呼び出し側は、アドレス 100 番地以降に 10 バイトのデータを確保した、という形になります。

で、次に、alloc(20) を呼び出すと、

  • alloc() の戻り値は 110
  • alloc() から戻ってきた時の allocp の値は 130

になります。

これで、最初の alloc(10) と alloc(20) で、割り当てられた領域が重複しないで済みます。

C言語編 第32章 ファイル分割

上記ページの「静的グローバル変数」というところに、グローバル変数に static を付けた場合の効能に関して記述があります。

id:mizore_chan

なるほど!!

有難う御座います。

staticで宣言されているから、変更が保存される訳ですね。

で、返り値は-nされたところのアドレスという訳で...。

【補足】

ローカル変数の宣言にstatic を付けると、プログラム開始時にメモリに記憶され、

関数を終了しても保持している値が消えることがなくなる  (リンク先より)

大変よく分かりました。

機会がありましたら、また宜しくお願いします。

2011/05/23 17:33:17
id:rsc96074 No.2

回答回数4504ベストアンサー獲得回数437

ポイント23pt

 本をちょっと見てみましたが、

static char *allocp = allocbuf; /* 次の空き位置 */

と、コメントに書いているので、allocpは次の空き位置を指すのに対して、

関数char *alloc()は、「n 文字へのポインターを返す」となっていますので、やっぱり、必要かと思います。

 難しく考えず過ぎず、コメント通り素直にとってもいいのではないでしょうか。

プログラミング言語C 第2版 ANSI規格準拠

プログラミング言語C 第2版 ANSI規格準拠

  • 作者: B.W. カーニハン D.M. リッチー
  • 出版社/メーカー: 共立出版
  • メディア: 単行本

id:wd0 No.3

回答回数14ベストアンサー獲得回数2

ポイント22pt

この場合は、関数外で定義された変数がstatic宣言されているので、意味が違います。ファイル外からは見えないという宣言です。こうしておけば、ファイル foo.c と ファイル bar.c で同名の変数を定義しても、別々のものとして扱われます。

http://www.jisc.go.jp/app/pager?id=68554

id:saijyoh_739 No.4

回答回数113ベストアンサー獲得回数10

ポイント22pt

まずは、説明から(既に理解されているとは思いますが)。


> 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以外からはアクセスできなくなり』というのは表現として微妙です。(アクセスが拒否されるなど阻害されたりはしないかと。)

http://www.mapee.jp/cpp/static_2.html

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません