6

私は、次のように定義されている関数に対するこの引数に混乱しています。

int bind(int s, const struct sockaddr *name, int namelen)

と呼ばれる

bind(sd, (struct sockaddr_in *) &addr, length);

ここで何struct sockaddr_in *を意味するのか理解できません。

これは機能しますbind (sd, &addr, length);か?

4

3 に答える 3

3

次のように呼び出す必要があります。

bind (sd, (struct sockaddr *) &addr, length);

理由については、これらの構造の定義を見ると、これがポリモーフィズムを行うCの方法です。

struct sockaddr {
    unsigned short    sa_family;    // address family, AF_xxx
    char              sa_data[14];  // 14 bytes of protocol address
};

// IPv4 AF_INET sockets:
struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
};

// IPv6 AF_INET6 sockets:
struct sockaddr_in6 {
    u_int16_t       sin6_family;   // address family, AF_INET6
    u_int16_t       sin6_port;     // port number, Network Byte Order
    u_int32_t       sin6_flowinfo; // IPv6 flow information
    struct in6_addr sin6_addr;     // IPv6 address
    u_int32_t       sin6_scope_id; // Scope ID
};

それらはすべて同じ最初のメンバーを共有しsa_familyます。これらの構造の1つへのポインターをbind()最初に関数にキャストするstruct sockaddr *と、関数内で、sa_family1つの関数ではなく、どの構造を渡して正しい構造にキャストバックするかを決定するために使用されます。構造ごとに、を受け入れる関数が1つありますsockaddr*

OOPの観点から見ると、それsockaddrがとの基本クラスであるsockaddr_inと想像してくださいsockaddr_in6。ポインタをに渡すことsockaddrは、基本型にキャストして総称関数を呼び出すことに似ています。これがそれをより明確にすることを願っています。

于 2012-11-11T17:13:45.013 に答える
2

ポインタを除いて、ポインタからポインタへvoidの変換は明示的である必要があります。TU

bind (sd, (struct sockaddr *) &addr, length);
于 2012-11-11T17:08:34.600 に答える
1

それは何であるかに依存しaddrます。

同じ構造体のアドレスでない場合は、型キャストする必要があります。そうでない場合は、から<type of addr>への暗黙の型キャストの警告が表示されます。const struct sockaddr*

プログラムのコンパイル時にコンパイラによって表示されるすべての警告メッセージを表示します。これの使用を開始します(コンパイラのgcc警告用):

gcc -Wall <test.c> -o <test>

これはプログラマーにとってのベストプラクティスです。

于 2012-11-11T17:08:56.273 に答える