5.4 アドレス計算 K&R プログラミング言語C

5.4 アドレス計算

  • 正常にアドレスを指し示すポインタは 0 にはならない。
  • 0 は異常値を表し、stdio.h で定義されている NULL を使う。
  • ポインタは同じ配列の要素を指し示している場合には、==, !=, <, >, <=, >= などの関係演算子を利用できる。
  • ポインタと整数との間の加減算は、ポインタが指し示すオブジェクトの型のサイズに応じて適切にスケールされる。
    p + n(p の先頭アドレス) + (sizeof p) * n となる。

正しいポインタ演算

  • 同じ型のポインタの代入
  • ポインタと整数の加算・減算
  • 同じ配列の要素を指し示すポインタの引き算と比較
  • ゼロ(NULL)の代入やゼロ(NULL)との比較

alloc, afree

以下のプログラム例での allocbuf の状態。

allocbuf の状態図

#include <stdio.h>

#define ALLOCSIZE 10000 /* 使用可能な場所の大きさ */

static char allocbuf[ALLOCSIZE]; /* alloc のための記憶場所 */
static char *allocp = allocbuf;  /* 次の空き位置(allocbuf の先頭アドレスを指して初期化) */

char *alloc(int);
void afree(char*);

int main(void)
{
    int n;
    char *p, *q;

    printf("p => %p\n", p);
    printf("q => %p\n", q);
    n = 10;
    p = alloc(n);
    printf("p => %p\n", p);
    *p = 'a';
    *(p+1) = 'b';
    *(p+2) = 'c';
    *(p+3) = '\0';
    printf("allocbuf => %s\n", allocbuf); /* p で確保した allocbuf の領域が使用されている */
    q = alloc(n);
    printf("q => %p\n", q);
    *q = 'A';
    *(q+1) = 'B';
    *(q+2) = 'C';
    *(q+3) = '\0';
    printf("allocbuf[n] => %s\n", &allocbuf[n]); /* q で確保した allocbuf の領域が使用されている */
    afree(p);
    afree(q);
    printf("p => %p\n", p);
    printf("q => %p\n", q);

    return 0;
}

/* n 文字へのポインタを返す */
char *alloc(int n)
{
    if (allocbuf + ALLOCSIZE - allocp >= n) { /* 入りきる */
        allocp += n;
        return allocp - n; /* 古い p */
    } else { /* 十分な空きがないとき */
        return 0; /* 異常事態を表わす 0 、通常は NULL (stdio.h で定義) を使う */
    }
}

/* p によって指される領域を解放する */
void afree(char *p)
{
    if (p >= allocbuf && p < allocbuf + ALLOCSIZE) {
        allocp = p;
    }
}

実行結果

$ ./alloc
p => 0x7fff5fbfebe8
q => 0x0
p => 0x100001080
allocbuf => abc
q => 0x10000108a
allocbuf[n] => ABC
p => 0x100001080
q => 0x10000108a
プログラミング言語C 第2版 ANSI規格準拠
B.W. カーニハン D.M. リッチー
共立出版
売り上げランキング: 9726
«
»