2017-09-02 87 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 

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