setpri(up)
{
register *pp, p;
pp = up;
p = (pp->p_cpu & 0377)/16;
p =+ PUSER + pp->p_nice;
if(p > 127)
p = 127;
if(p > curpri)
runrun++;
pp->p_pri = p;
}
のように、整数へのポインターであるppから構造体のメンバーに平気で参照を行っている。
メンバー名の頭に「p_」がついているのはproc.hで定義しているstruct procである。
Version 6のC Reference Manualの記述は以下のとおり。
すなわち、左辺は構造体へのポインターでなくてもよいのはもちろん、ポインターである必要すらない。 整数型はともかく文字型でもよいのである。7.1.8 primary-expression -> member-of-structure
The primary-expression is assumed to be a pointer which points to an object of the same form as the structure of which the member-of-structure is a part. The result is an lvalue appropriately offset from the origin of the pointed-to structure whose type is that of the named structure member. The type of the primary-exporession need not in fact be pointer, it is sufficient that it be a pointer, character, or integer.
たとえば、関数main()の冒頭部にある
UISD->r[0] = 077406;
がそうである。これはいずれもseg.hで定義されていて
#define UISD 0177600 /* first user I-space descriptor register */および
/*
* structure used to address
* a sequence of integers.
*/
struct
{
int r[];
};
となっている(Lions本では後者はparam.hに移っている)。つまり、整数値から
直接構造体のメンバー(しかも要素数の指定のない配列)にアクセスしているの
である。
0177600->r[0] = 077406;
これは、のちの言葉で言うと、
メンバーを指定することにより構造体のポインター型への、
暗黙の型変換(キャスト)がおこなわれているわけである。
当時、構造体のメンバー名は全構造体をつうじて一意だったので、
このような芸当が可能だったのである。
当時のドキュメントには型変換が見当たらない。 param.hには前項で見たように、 暗黙の型変換のための無名の構造体が定義されている。
/*
* structure to access an
* integer in bytes
*/
struct
{
char lobyte;
char hibyte;
};
/*
* structure to access an integer
*/
struct
{
int integ;
};
ところで、これを「代入演算子」と呼ぶのは変といえば変である。 「自己演算子(endo-operator)」とでも呼びたいところである。
特に、今日iを整数値に適当に使用するように、 pを汎用のポインターとして使っているあたりである。 一般のポインターから構造体メンバーへの参照が自由におこなえるのでこういう芸当が可能であった。