これは、任意のポインターから構造体への値を他のポインターから構造体への変数に格納でき、その過程で有効なポインター・オブジェクトを作成し、中間変数から元のポインターを復元できることを意味します。対照的に、別のカテゴリのポインタを中間として使用することは許可されていません。例えば:
struct Foo * p = &x; // x is a struct Foo
struct Bar * q;
memcpy(&q, &p, sizeof p); // OK, it's allowed to read (but not dereference!) q
memcpy(&p, &q, sizeof q); // OK, p is now the same it was before
union Zip * r;
int * s;
// not allowed to do the same with (p, r) and (p, s)!
両方とも構造体へのポインタであるため、サイズと配置が同じであるため、memcpy
sはOKです。同じことが、ユニオンへの2つのポインター、またはintへの2つのポインターにも当てはまりますが、カテゴリーを混在させることはできません。p
q
別の非常に工夫された、しかし有効な例を次に示します。
struct Foo { int a; };
int f(struct Bar * p)
{
return (struct Foo *)(p)->a;
}
int main()
{
Foo x = { 12 };
return f((struct Bar *)(&x));
}
の関数パラメータが別のカテゴリのポインタ(たとえば、ポインタからユニオンまたはポインタから整数)の場合、このプログラムは無効になります。f
オブジェクトポインタを変換したり戻したりできる唯一のポインタ型はvoid *
です。f
(したがって、のパラメーターを作成することもできますvoid *
。これは間違いなく最も一般的なスタイルです。ただし、構造体ポインターにする方が効率的であるため、一部のプラットフォームでは望ましいと考えられます。)