inetについてntoa関数の思考


socket addressのデータ構造
//*Structure describing an Internet socket address.  */struct sockaddr_in  {    __SOCKADDRAGMON(sin_);    inuplort sinuplort;            /* Port number.  */    struct inudr sinuddr;        /* Internet address.  */   /* Pad to size of`struct sockaddr'  */    unsigned char sinuzo[size of(struct sockaddr)-               __SOCKADDRAGON MONZE-               sizeof-               sizeof;  };
#include 
#include 
#include 
#include 
#include 
#include 


void main()
{
    struct in_addr addr1, addr2;
    unsigned int uip1, uip2;
    uip1 = inet_addr("127.0.0.1");
    uip2 = inet_addr("172.16.16.123");
    printf("     :ip1=%u,ip2=%u
",uip1,uip2); // memcpy(&addr1, &uip1, 4); memcpy(&addr2, &uip2, 4); printf(" IP :ip1=%s,ip2=%s
",inet_ntoa(addr1),inet_ntoa(addr2)); system("pause"); }
     :ip1=16777343,ip2=2064650412
    IP :ip1=127.0.0.1,ip2=127.0.0.1

私たちが予想していた結果ではありません.なぜですか?printf関数の割当値は「右から左」、つまり上書きの問題があることを知っています.関数inetuntoaの内部実現メカニズムを分析します.
関数inet ntoaは文字ポインタを返します.自動変数はスタックにメモリを割り当てます.自動変数の関数またはコードが終了すると、その占有メモリ空間は回収されます.関数またはコードが終了すると、これらの変化量のメモリにアクセスすることができます.次のような方法があります.
(1)
文字列の定数を返します.返された文字列は変更できません.inet ntoa関数はメソッドを使用しないことが明らかです.
(2)グローバル変数を定義します.欠点は関数外のコードも修正できます.inetheuntoa関数の入出力から見ても、この方法ではないことは明らかです.
(3)静的変数を使用して、欠点は呼び出しごとに前回の内容を上書きするということです.inet ntoa関数はこのような方式を採用しています.先にinet ntoa(addr2)を実行して静的変数を127..16.123に変更し、inet ntoa(addr1)を実行して静的変数を127..0.1に変更します.したがって、最終的に出力するときは127.1.0.1です.
(4)メモリを動的に割り振ります.(mallocなどの関数を通じて)inethotoa関数がこのような方式を採用すれば、一度も呼び出さずにメモリを解放してもいいですか?しかし、linuxはこのfreeの方法を提供していません.
分析によると、inet ntoa関数の入力パラメータはunsigned intタイプのipアドレスであり、戻ってきたのはip文字列のポインタを指しています.明らかに、ip文字列が占めているメモリは関数の内部に割り当てられていますが、メモリを解放する必要はありません.
したがって、割り当てられたメモリは静的で、つまり次の関数を呼び出すとこの配列の内容が上書きされますので、上記のような結果が出ます.