0

私は次のcプログラムを持っています

     struct in_addr {
            unsigned long s_addr;  // load with inet_aton()
        };

        struct sockaddr_in {
            short            a;  
            unsigned short   b;    
            struct in_addr   c;     
            char             d[8];  
        };

        int main(int argc, char** argv) {

            struct sockaddr_in *record1;
            record1 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in*));
            memset(record1, 0, 14);
            record1->a = 16;
            record1->b = 4;
            //strcpy(record1->sin_zero, "1");
            printf("Struct record1: %x", *record1);
        }

record1->a = 16を単独で割り当てると、「 Struct record1: 10」が得られます

record1->a = 16record1->b =4を割り当てると 、「Struct record1:40010」が得られます (リトル エンディアンであることがわかりますが、それでも*期待される出力は04 10 * (short はそれぞれ 2 バイトかかります) )))

record1->a=16;を割り当てると、* record1->b =4; * record1->c.s_addr = 1UL; * strcpy(record1->d, "1"); ※出力は「Struct record1: 40010」のまま(Yはlongへの代入でchar[]は反映されていない?

誰でもこの動作を説明できますか? 構造体の内容がメモリにどのように割り当てられているかを確認したい。これを達成するためのよりスマートな方法はありますか?

4

3 に答える 3

3

のサイズではなく、ポインターのサイズにスペースを割り当てていますstruct sockaddr_in。したがって、割り当ての境界を超えており、未定義の動作に陥っています。

試す:

record1 = malloc(sizeof(*record));

次に、短編を印刷したい場合は、短編を印刷します。hex-int として出力されるポインター逆参照 (つまり、struct-val) を送信していることを考えると、printf がまったく機能することに少しショックを受けています。バイトを印刷しようとしている場合は、列挙アルゴリズムが必要です。

unsigned char *p = (unsigned char*)record1;
for (size_t i=0; i<sizeof(*record1); ++i)
    printf("%.2x ", p[i]);

あなたがそれを行うことができるそのような方法の1つです。投稿された設定により、次のmain()ものが生成されます。

10 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 

これは確かに理にかなっています。aは 16 で、2 バイトの short のリトルエンディアンは確かに10 00. 同様bに 4 であり、同じリトルエンディアンの 2 バイトの unsigned short は04 00.

于 2013-09-23T06:36:42.997 に答える
2

aは ashortで、これは通常 2 バイトの長さであり、 b は でありunsigned short、これも通常 2 バイトの長さです。(printf スタイルの書式設定)の 1 バイト%xは 2 つの ASCII 文字の長さであるため、2 バイトは 4 つの ASCII 文字の長さになります ( で印刷した場合%x)。したがって、aと をb合わせて最大 8 文字の ASCII 文字になります。とにかく、構造の内容を印刷する方法は実際には正しくありません...各メンバーを印刷する必要があります。

    struct in_addr {
        unsigned long s_addr;  // load with inet_aton()
    };

    struct sockaddr_in {
        short            a;
        unsigned short   b;
        struct in_addr   c;
        char             d[8];
    };

    int main(int argc, char** argv) {

        struct sockaddr_in *record1;
//      record1 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in*));
        record1 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
        memset(record1, 0, 14);
        record1->a = 16;
        record1->b = 4;
        //strcpy(record1->sin_zero, "1");
        printf("Struct record1:\n");
        printf("    a = 0x%04x\n", record1->a);
        printf("    b = 0x%04x\n", record1->b);
        printf("    c.s_addr = 0x%08x\n", record1->c.s_addr);
        printf("    d = %02x %02x %02x %02x %02x %02x %02x %02x\n",
               record1->d[0], record1->d[1], record1->d[2], record1->d[3],
               record1->d[4], record1->d[5], record1->d[6], record1->d[7]);
    }
于 2013-09-23T06:44:54.897 に答える
0

見つめている:

record1 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in*));

それはおそらくあなたが望むことをしません。おそらく、sockaddr_in 構造体を保持するためにメモリを割り当てるつもりです。そのステートメントは、sockaddr_in へのポインタのサイズのメモリを割り当てます。

正しい形式は次のようになります (sizeof の * がなくなっていることに注意してください)

record1 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));

これで、正しい量のメモリが割り当てられます。

印刷行では、構造体を直接印刷することはできません。次の行に沿って、自分で大変な作業を行う必要があります。

printf("Struct record1: %x %x %x %s", record1->a, record1->b, record->c.saddr, record1->d);

record1 へのポインターを出力するには、次のようなものを使用します (* がなくなっていることに注意してください。ポインターが指すものではなく、ポインターを出力する必要があります)。

printf("Struct record1: %x", record1);

メモリレイアウトを見たい場合は、次のようなものを使用できます

char* address;
for (address = record1 ; address < (record1+sizeof(sockaddr_in)) ; address++)
{
    printf("Address: %x  Contents: %x\n", address, *address);
}

もう 1 つ、"14" よりも sizeof() を使用することをお勧めします。

memset(record1, 0, sizeof(sockaddr_in));
于 2013-09-23T07:01:50.917 に答える