2017-09-02 85 views
1

说,如果我有一个结构为:如何确定结构构件和填充的大小?

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

的地址A:B的0x7ffd415c8b20 地址是:c的0x7ffd415c8b28 地址是:0x7ffd415c8b30simple_struct_1大小是24

我已打印每个成员的地址和结构体的大小,我如何显示这个结构体是如何放置在内存中的?如果在simple_struct_1中,a占用111个字节并且具有222个填充字节,之后b占用333个字节,其后有0个填充字节,并且c占用444个字节,其后有555个字节的填充。

+1

这看起来类似于[STRUCT存储器布局](https://stackoverflow.com/questions/2748995/c-struct-memory-layout) –

+0

另外打印每个成员的'sizeof()'。它会在'char'中给你它们的大小。然后,您可以轻松推断地址中“char”的字节数。 – spectras

+1

一般来说,使用或依赖特定内存布局的结构会产生错误的代码。 – StephenG

回答

0

您可以尝试使用pahole(戳 - 孔)。这将有助于你如何需要它。

这里是对它的引用。 pahole

4

您可以使用offsetofsizeof让每个单独的领域和结构的大小作为一个整体的细节,比如用:

printf ("a  is %[email protected]%d\n", sizeof(simple_struct_1.a), offsetof(simple_struct_1, a)); 
printf ("b  is %[email protected]%d\n", sizeof(simple_struct_1.b), offsetof(simple_struct_1, b)); 
printf ("c  is %[email protected]%d\n", sizeof(simple_struct_1.c), offsetof(simple_struct_1, c)); 
printf ("struct is %[email protected]\n", sizeof(simple_struct_1)); 

这应该使您能够制定出:

  • 所有字段的偏移量和大小;
  • 间隙该字段;和
  • 最后一个字段后的间隙(结合其与整个结构的尺寸偏差和大小。

不要担心之前填充第一场,ISO标准禁止这一点。

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

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

可以使用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 

*********-------********