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 ”(我可以发现它是 Little Endianness,但*我的预期输出仍然是04 10 *(每个短需要两个字节))

当我分配record1->a=16; *记录1->b =4;*记录 1->c.s_addr = 1UL;* strcpy(record1->d, "1"); * 输出仍然是“ Struct record1: 40010 ”(Y 是赋值给 long 和 char[] 没有反映?

谁能解释这种行为。我想看看结构的内容是如何在内存中分配的。有没有更聪明的方法来实现这一目标?

4

3 回答 3

3

您正在为指针的大小分配空间,而不是为 a 的大小分配空间struct sockaddr_in。因此,您超出了分配界限并陷入了未定义的行为。

尝试:

record1 = malloc(sizeof(*record));

其次,如果要打印短片,请打印短片。考虑到您正在发送要打印为十六进制整数的指针解引用(即 struct-val),我对您的 printf 甚至完全可以工作感到有些震惊。如果您尝试打印字节,则需要枚举算法来执行此操作。

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

是您可以做到的一种方式。通过您发布的设置,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,两字节短的 little-endian 确实是10 00. 同样b是 4,同样,一个两字节的无符号短,相同的小端,是04 00.

于 2013-09-23T06:36:42.997 回答
2

a是 a short,一般是 2 字节长, b 是 a unsigned short,一般也是 2 字节长。(printf 样式格式)中的一个字节%x是两个 ASCII 字符长,因此 2 个字节将是 4 个 ASCII 字符长(使用 打印时%x)。所以两者ab在一起最多可以有 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);
}

还有一件事,喜欢使用 sizeof() 而不是“14”:

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