2013-12-12 2 views
2

Чтение source code of Redis:указатель на указатель не совпадает с массивом символов?

struct sdshdr { 
    int len; 
    int free; 
    char buf[]; 
}; 

Я обнаружил, что char buf[] не может быть заменить char *buf, в том смысле, что char* buf бы увеличить размер структуры.

Но я не понимаю, почему, может кто-нибудь пролить свет на это?


Edit: Я проверил это на моем x86_64 Ubuntu (3.2.0-23-родовой) с GCC 4.6.3, как это:

Е ("sdshdr Len =% zu \ n ", sizeof (struct sdshdr));

С char buf[] он выводит sdshdr len = 8 и sdshdr len = 16 с char *buf.

+2

'символ * buf' не будет увеличивать размер структуры. – moeCake

+0

Да, да, см. Мой обновленный вопрос. @moeCake – adamsmith

+0

[% zu - правильный спецификатор формата для size_t] (http://stackoverflow.com/questions/940087/whats-the-correct-way-to-use-printf-to-print-a-size-t), что и возвращает 'sizeof'. –

ответ

3

Путь buf члена объявляются принимает преимущество признака C99 называется гибких массивов, главное преимущество состоит в том, чтобы получить use of variable length array like features inside a struct. Поскольку buf объявлен без размера, он не занимает пробела, пока вы явно не выделите его при динамическом распределении struct sdshdr *.

Это более эффективно, чем использование символа *, так как если buf был символа * мы должны выполнить два динамических распределение, первым для STRUCT sdshdr *, а затем снова buf и указателя потребуется дополнительное пространство. Это чище, так как распределение либо преуспевает, либо не работает, поскольку блок и очистка проще, поскольку требуется только один free. Мы также получаем локальность данных, поскольку вся структура распределена в блоке и не требует отдельного разыменования для доступа buf.

draft C99 standard в разделе 6.7.2.1 есть хороший пример, который показывает, как использовать эту функцию:

EXAMPLE After the declaration: 

    struct s { int n; double d[]; }; 

the structure struct s has a flexible array member d. A typical way to use this 
is: 

    int m = /* some value */; 
    struct s *p = malloc(sizeof (struct s) + sizeof (double [m])); 

and assuming that the call to malloc succeeds, the object pointed to by p 
behaves, for most purposes, as if p had been declared as: 

    struct { int n; double d[m]; } *p; 

(there are circumstances in which this equivalence is broken; in particular, the 
offsets of member d might not be the same). 
+0

Огромное спасибо за обновленный ответ, который очень помогает! – adamsmith

Смежные вопросы