Cでソケットプログラミングをする時なんかに、 構造体struct sockaddr_in
を bind
やaccept
, connect
などの関数に渡す際に、 struct sockaddr*
にキャストして渡します。
正直、僕にとっては、構造体へのポインタのキャストって、 イメージしづらい と感じます。 Javaとかのクラスであれば、多相性とかのイメージなんでしょうけれど、 Cの構造体はあくまでデータ構造の定義ですので...
例えば、こんなコードを考えてみます。
#include <stdio.h>
struct hoge {
double a;
int b;
};
struct piyo {
int age;
double height;
double weight;
};
void printHoge(struct hoge *h)
{
printf("a: %lf\n", h -> a);
printf("b: %d\n", h -> b);
}
void printPiyo(struct piyo *p)
{
printf("age: %d\n", p -> age);
printf("height: %lf\n", p -> height);
printf("weight: %lf\n", p -> weight);
}
int main(int argc, char **argv)
{
struct hoge h = {3.14, 10};
struct piyo p = {22, 169.5, 54.3};
printHoge(&h);
putchar('\n');
printHoge((struct hoge*)&p);
putchar('\n');
putchar('\n');
putchar('\n');
printPiyo((struct piyo*)&h);
putchar('\n');
printPiyo(&p);
return 0;
}
それぞれprintHoge
とprintPiyo
で、 構造体struct hoge
とstruct piyo
の内容を表示させます。 それぞれ、引数は構造体へのポインタを指定しています。 そこで、struct hoge
の変数h
とstruct piyo
の変数p
を それぞれキャストして渡してみます。 すると、実行結果は以下のようになりました。
$ ./struct a: 3.140000 b: 10 a: 0.000000 b: 0 age: 1374389535 height: 0.000000 weight: -322.000000 age: 22 height: 169.500000 weight: 54.300000 $
まあ、データ構造が全然違うので、当たり前かもしれませんが... おそらく、データ構造が全然違うものをキャストして使うこと自体が誤りなのでしょう。
今度は、少しデータ構造を似せてみます。 struct hoge
とstruct piyo
のデータ構造に共通部を持たせてみます。
#include <stdio.h>
#define SIZE 65536
struct hoge {
char buf[SIZE];
int hogera;
};
struct piyo {
char name[SIZE];
int age;
double height;
double weight;
};
void printHoge(struct hoge *h)
{
printf("buf:\t%s\n", h -> buf);
printf("hoge:\t%d\n", h -> hogera);
}
void printPiyo(struct piyo *p)
{
printf("name:\t%s\n", p -> name);
printf("age:\t%d\n", p -> age);
printf("height:\t%lf\n", p -> height);
printf("weight:\t%lf\n", p -> weight);
}
int main(int argc, char **argv)
{
struct hoge h = {"hoge", -1};
struct piyo p = {"ponta", 20, 170.4, 61.2};
printHoge(&h);
putchar('\n');
printHoge((struct hoge*)&p);
putchar('\n');
putchar('\n');
putchar('\n');
printPiyo((struct piyo*)&h);
putchar('\n');
printPiyo(&p);
return 0;
}
struct hoge
とstruct piyo
の先頭の構造を、char
の配列と、 int
をメンバ変数に共通させてみます。 このコードの実行結果は以下の通りです。
$ ./struct2 buf: hoge hoge: -1 buf: ponta hoge: 20 name: hoge age: -1 height: 0.000000 weight: 0.000000 name: ponta age: 20 height: 170.400000 weight: 61.200000 $
今度はchar
への配列とint
のメンバ変数の内容が表示されました。 struct hoge
の変数をprintPiyo
関数にstruct piyo*
型にキャストして実行してみたら、 自分の環境(FreeBSD 10.2-RELEASE-p24, clang version 3.4.1
)では、double
のメンバ変数の中身は0.000000
と表示されました。 おそらく、環境依存だと思いますが...
とりあえず、なんとなく挙動は確認してみたのですが、 やはり勉強不足なので、もうちょっと調べてみようかなと思います。 そんなこんなで、今回はここまで。
構造体へのポインタのキャストについて、筆者が理解した内容をこちらの記事にまとめました。