2014年1月7日火曜日

Pre K&R C の無名構造体を用いたバイトアクセス

UNIX V6 の Pre K&R C では無名の構造体のメンバが外部に公開されており、 -> 演算子を使って構造体メンバにアクセスできる。 (この時、必ずしも左辺値はポインタ型でなくてもよい。) 16bit の int 型へのポインタから無名構造体のメンバにバイトアクセスする方法を 実験してみた。

struct { 
    char a; 
    char b;
};

int main()
{
    register *p;
    register pa, pb;
    int x;

    x = (0125 << 8) | 0252;
    p = &x;
    printf("%d\n", *p);
    pa = (*p).a;
    pb = (*p).b;
    printf("%d %d\n", pa, pb);
    pa = p->a;
    pb = p->b;
    printf("%d %d\n", pa, pb);

    return (0);
}

実行結果は以下の通り。

# ed main.c
?
a
struct {        char a;         char b;};int main(){    register *p;    register pa, pb;        int x;          x = (0125 << 8) | 0252; p = &x; printf("%d\n", *p);     pa = (*p).a;    pb = (*p).b;    printf("%d %d\n", pa, pb);      pa = p->a;      pb = p->b;      printf("%d %d\n", pa, pb);      return (0);}
.
w
252
q
# cc main.c
# ./a.out
21930
-86 85
-86 85
#

x に 0x55AA ((0125 << 8) | 0252) を代入して、p に x へのポインタを代入する。 当然ながら、*p の値は 0x55AA (21930) になる。 ANSI C と同様に、(*p).a と p->a の結果は一致するが、p->a と p->b の値は それぞれ -86 と 85 になっている。これは、PDP11 がリトルエンディアンであるため、 16bit の p->b によってアクセスされるのは 0x55 (85) であると解釈できる。 同様に、p->a によってアクセスされるのは 0xAA であるが、構造体メンバ a が char 型なので符号拡張されて、0xFFAA (-86) になると解釈できる。

0 件のコメント:

コメントを投稿