【问题标题】:How to print object of structure in bits representing its contents in C?如何在 C 中以表示其内容的位打印结构对象?
【发布时间】:2013-09-23 06:33:05
【问题描述】:

我有以下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*(short 每个需要两个字节))

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

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

【问题讨论】:

  • 查看内容的最聪明方法是使用调试器(如果可用)。

标签: c struct


【解决方案1】:

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

试试:

record1 = malloc(sizeof(*record));

其次,如果要打印短片,请打印短片。考虑到您正在发送要打印为十六进制整数的指针取消引用(即 struct-val),我对您的 printf 甚至 works 都感到有些震惊。如果您尝试打印 bytes,您需要一个枚举算法来执行此操作。

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

【讨论】:

  • @phonetagger 呵呵。等待火龙生成。
【解决方案2】:

ashort,一般是2字节长,b是unsigned short,一般也是2字节长。 %x 中的一个字节(printf 样式格式)是两个 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]);
    }

【讨论】:

    【解决方案3】:

    看着:

    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);
    

    要打印 pointer 到 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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      • 2011-01-27
      相关资源
      最近更新 更多