Член структуры нулевой длины

Тема в разделе "LANGS.C", создана пользователем srm, 24 авг 2011.

  1. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Здравствуйте. У меня в языке С задана структура:

    Код (Text):
    1. typedef struct _A
    2. {
    3.   int a;
    4.   char b[0];
    5. } A;
    Собственно, вопросы:
    1. равно sizeof(A) == sizeof(int)?
    2. насколько такое определение структуры вообще корректно (VS выдаёт варнинги)?
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Код (Text):
    1. "ComeauTest.c", line 3: error: the size of an array must be greater than zero
    2. char a[0];
     
  3. 7mm

    7mm New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2009
    Сообщения:
    442
    Возможность такого определения зависит от компилятора и стандарта. Если поддерживает, то sizeof(A) будет равно sizeof(int).
     
  4. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    А выравнивание как может повлиять?
     
  5. 7mm

    7mm New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2009
    Сообщения:
    442
    Я думаю никак, но не могу этого гарантировать.
     
  6. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    Читаем стандарт C ISO/IEC 9899

    Т.е. вообще говоря нельзя так и стандарт говорит что константы должны быть больше 0!
     
  7. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
  8. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
  9. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Если не секрет, для чего такое странное объявление нужно?
     
  10. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Если размер данных заранее неизвестен. Например,
    Код (Text):
    1. typedef struct {
    2.     size_t length;
    3.     char data[0];
    4. } VArray;
    При создании этой структуры с помощью malloc выделяют памяти sizeof(VArray) + length и обращаются к данным через поле data (ведь контроля границ массива нет).
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Ну и зачем?
    Код (Text):
    1. typedef struct {
    2.     size_t length;
    3.     char *data;
    4. } VArray;
     
  12. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Затем, что в вашем варианте надо выделять память 2 раза, а в моём только один раз. А ещё если данные уже пришли в этом формате. Например, мы прочитали пакет с сокета.
     
  13. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Я не говорю, что так надо делать всегда. Я показываю, что массивы нулевой длины могут быть полезны и это не такое уж и причудливое объявление.
     
  14. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Booster
    Например для реализации строки таким образом:
    Код (Text):
    1. struct my_string
    2. {
    3.     size_t size, len;
    4.     char str[0]
    5. };
    6.  
    7. struct my_string* new_my_string(size_t size)
    8. {
    9.     struct my_string *str = malloc (sizeof(*str) + size);
    10.     str.size = size;
    11.     str.len = 0;
    12.     return str;
    13. }
    При таком подходе можно сэкономить на количестве malloc'ов и разадресаций. Но есть и ещё один бонус: бинарные структуры в файлах и всяческих сетевых протоколах, подчастую переменного размера.
     
  15. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    KIV
    Если подсмотреть в виндовые хедеры, то можно увидеть, что эту проблему решают массивом в 1 элемент.
     
  16. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Если память выделяется через malloc, которой мы просто обязаны явно указывать размер, тогда нет смысла писать именно 0. Можно написать любое число, например 1, и не ломать голову над ворнингами компиляторов. Если волнует вопрос использования sizeof+доп.размер, то определить константу на единицу меньше sizeof, и вместо sizeof использовать ее.
     
  17. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    srm

    смысл такой огород городить ??? фактически вы пытаетесь дублировать механизм установки метки через структуру и заморачиваетесь вопросом размера
     
  18. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Так не получится:
    Код (Text):
    1. struct A
    2. {
    3.  int x;
    4.  char s[0];
    5. };
    6. sizeof(A) == 4;
    7.  
    8. struct A
    9. {
    10.  int x;
    11.  char s[1];
    12. };
    13.  
    14. sizeof(A) == 8;
    Плюс ещё выравнивание полей структуры... Если нужно так:
    Код (Text):
    1. struct A
    2. {
    3.  short x;
    4.  char s[1];
    5. };
    то вообще хз что получится. sizeof(A) - sizeof(A::s) ничего хорошего не даст, т.к. в зависимости от выравнивания может быть 8 - 1, а может 4 - 1.

    Смысл в удобстве использования.
     
  19. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Я никак не могу вспомнить, в каких случаях в C можно пропускать имена вышестоящих структур при обращении к полям вложенных структур. Нельзя ли здесь так же выкрутиться?

    Что-то типа:
    Код (Text):
    1. struct Header
    2. {
    3.   int size;
    4.   double something_else;
    5. };
    6.  
    7. struct Packet
    8. {
    9.   struct Header hdr;
    10.   char data[1];
    11. };
    12.  
    13. ...
    14. {
    15.   ...
    16.   packet=malloc(sizeof(Header)+datasize);
    17.   //packet->hdr.size=datasize;  //<-- Можно ли не так,
    18.   packet->size=datasize;           //<-- а вот так ?
    19.   ...
    20. }
    Или это к енумам относилось?
     
  20. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Dmitry_Milk
    В C ни в каких. В C++ в том случае, если вложенная структура безымянная:
    Код (Text):
    1. struct _MY_STRUCT
    2. {
    3.     DWORD first;
    4.     struct
    5.     {
    6.         DWORD second;
    7.     };
    8. } my_struct = {5, {7}};
    9. my_struct.second; //<- обращение к члену вложенной структуры
    Это полезно при использовании вложенных объединений. Со структурами не помню, чтобы пригодилось.