【问题标题】:How do I figure out the size of struct members and paddings?如何确定结构成员和填充的大小?
【发布时间】:2018-02-11 02:04:28
【问题描述】:

说如果我有一个结构为:

struct simple_struct_1
{
  long long a;
  char b;
  long c;
};

a的地址是:0x7ffd415c8b20 b的地址是:0x7ffd415c8b28 c的地址是:0x7ffd415c8b30 simple_struct_1 的大小为 24

我已经打印了每个成员的地址和结构的大小,我如何显示这个结构是如何在内存中放置的?就像在simple_struct_1 中一样,a 占用 111 个字节并有 222 个填充字节,然后b 占用 333 个字节,后面有 0 个填充字节,c 占用 444 个字节,后面有 555 个填充字节。

【问题讨论】:

  • 这看起来类似于Struct memory layout
  • 同时打印每个成员的sizeof()。它将在char 中为您提供它们的大小。然后,您可以轻松地从地址中推断出 char 的字节数。
  • 通常使用或依赖结构的特定内存布局会产生错误代码。

标签: c struct padding


【解决方案1】:

您可以尝试使用pahole (poke -a -hole)。这将帮助您满足您的需求。

这是对它的引用。 pahole

【讨论】:

    【解决方案2】:

    您可以使用offsetofsizeof 获取每个单独字段的详细信息以及整个结构的大小,例如:

    printf ("a      is %d@%d\n", sizeof(simple_struct_1.a), offsetof(simple_struct_1, a));
    printf ("b      is %d@%d\n", sizeof(simple_struct_1.b), offsetof(simple_struct_1, b));
    printf ("c      is %d@%d\n", sizeof(simple_struct_1.c), offsetof(simple_struct_1, c));
    printf ("struct is %d@0\n",  sizeof(simple_struct_1));
    

    这应该能让你锻炼身体:

    • 所有字段的偏移量和大小;
    • 字段之间的间隙;和
    • 最后一个字段之后的间隙(将其偏移量和大小与整个结构的大小相结合。

    不用担心 第一个字段之前填充,ISO 标准禁止这样做。

    例如,假设您在左侧看到以下输出,右侧显示的是大小和间隙:

    a      is 16@0        16 bytes for a long long
                          no gap (0 + 16 = 16, next at 16)
    b      is 1@16         1 byte  for a char
                           7 bytes gap (16 + 1 = 17, next at 24)
    c      is 8@24         8 bytes for a long
    struct is 32@0        no gap at end (24 + 8 = 32, next at 32)
    

    【讨论】:

      【解决方案3】:

      您可以使用offsetof() 宏从第一个成员开始查找每个字段的字节偏移量(它必须与struct 具有相同的地址,因为不允许在第一个成员之前进行填充)。

      将此信息与使用sizeof 运算符获得的各种成员的大小(以及整个struct 的大小以查找尾随填充字节的数量)相结合,可以推断出填充字节的位置.这是一个打印成员地址和偏移量的程序。它还打印成员字节和填充字节的图形表示;破折号表示填充字节。

      #include <stdio.h>
      #include <stdlib.h>
      #include <stddef.h>
      
      struct simple_struct_1 {
          long long a;
          char b;
          long c;
      };
      
      char * graph_member(char *ptr, size_t member_sz, size_t padding_sz);
      
      int main(void)
      {
          struct simple_struct_1 my_struct;
      
          printf("sizeof (struct simple_struct_1) = %zu\n",
                 sizeof (struct simple_struct_1));
          putchar('\n');
      
          void *ptra = &(my_struct.a);
          void *ptrb = &(my_struct.b);
          void *ptrc = &(my_struct.c);
      
          size_t offset_a = offsetof(struct simple_struct_1, a);
          size_t offset_b = offsetof(struct simple_struct_1, b);
          size_t offset_c = offsetof(struct simple_struct_1, c);
      
          /* Allocate memory for struct padding visualization */
          char *graph = malloc(sizeof my_struct + 1);
      
          if (graph == NULL) {
              perror("Virtual memory exhausted");
              exit(EXIT_FAILURE);
          }
      
          char *ptr = graph;
      
          printf("&(my_struct.a) = %p\n", ptra);
          printf("sizeof my_struct.a = %zu\n", sizeof my_struct.a);
          putchar('\n');
          ptr = graph_member(ptr,
                             sizeof my_struct.a,
                             offset_b - sizeof my_struct.a);
      
          printf("&(my_struct.b) = %p\n", ptrb);
          printf("sizeof my_struct.b = %zu\n", sizeof my_struct.b);
          printf("&(my_struct.b) - &(my_struct.a) = %zu\n", offset_b - offset_a);
          putchar('\n');
          ptr = graph_member(ptr,
                             sizeof my_struct.b,
                             offset_c - offset_b - sizeof my_struct.b);
      
          printf("&(my_struct.c) = %p\n", ptrc);
          printf("sizeof my_struct.c = %zu\n", sizeof my_struct.c);
          printf("&(my_struct.c) - &(my_struct.b) = %zu\n", offset_c - offset_b);
          putchar('\n');
          ptr = graph_member(ptr,
                             sizeof my_struct.c,
                             sizeof my_struct - offset_c - sizeof my_struct.c);
      
          /* Null-terminate graph string and display */
          ptr = '\0';
          puts(graph);
      
          free(graph);
      
          return 0;
      }
      
      char * graph_member(char *ptr, size_t member_sz, size_t padding_sz)
      {
          /* Indicate member */
          for (size_t i = 0; i < member_sz; i++) {
              *ptr = '*';
              ++ptr;
          }
      
          /* Indicate padding */
          for (size_t i = 0; i < padding_sz; i++) {
              *ptr = '-';
              ++ptr;
          }
      
          return ptr;
      }
      

      示例程序输出:

      sizeof (struct simple_struct_1) = 24
      
      &(my_struct.a) = 0x7ffee4af4610
      sizeof my_struct.a = 8
      
      &(my_struct.b) = 0x7ffee4af4618
      sizeof my_struct.b = 1
      &(my_struct.b) - &(my_struct.a) = 8
      
      &(my_struct.c) = 0x7ffee4af4620
      sizeof my_struct.c = 8
      &(my_struct.c) - &(my_struct.b) = 8
      
      *********-------********
      

      【讨论】:

        猜你喜欢
        • 2016-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-28
        • 2012-08-22
        • 2020-07-26
        • 2011-03-23
        • 1970-01-01
        相关资源
        最近更新 更多