struct has an illegal zero-sized array
От: Аноним  
Дата: 06.01.10 16:10
Оценка:
Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?

/** Logical Volume Integrity Descriptor (ECMA 167r3 3/10.10) */
struct logvol_integrity_desc_s
{
  udf_tag_t       tag;
  udf_timestamp_t recording_time;
  udf_Uint32_t    integrity_type;
  udf_extent_ad_t next_integrity_ext;
  udf_Uint8_t     logvol_contents_use[32];
  udf_Uint32_t    i_partitions;
  udf_Uint32_t    imp_use_len;
  udf_Uint32_t    freespace_table[0];
  udf_Uint32_t    size_table[0];
  udf_Uint8_t     imp_use[0]; 
} GNUC_PACKED;
Re: struct has an illegal zero-sized array
От: Vamp Россия  
Дата: 06.01.10 16:18
Оценка:
А>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?
Массивы из нуля элементов запрещены. А нафига они?
Да здравствует мыло душистое и веревка пушистая.
Re[2]: struct has an illegal zero-sized array
От: cppguy  
Дата: 06.01.10 16:25
Оценка:
Здравствуйте, Vamp, Вы писали:

А>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?

V>Массивы из нуля элементов запрещены. А нафига они?
Re[2]: struct has an illegal zero-sized array
От: cppguy  
Дата: 06.01.10 16:28
Оценка: -2
Здравствуйте, Vamp, Вы писали:

А>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?

V>Массивы из нуля элементов запрещены. А нафига они?

стандартом они не запрещены, код из модуля ядра линукса
http://sourceforge.net/projects/linux-udf/
Re[3]: struct has an illegal zero-sized array
От: denisko http://sdeniskos.blogspot.com/
Дата: 06.01.10 16:35
Оценка:
Здравствуйте, cppguy, Вы писали:

C>Здравствуйте, Vamp, Вы писали:


А>>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?

V>>Массивы из нуля элементов запрещены. А нафига они?

C>стандартом они не запрещены, код из модуля ядра линукса

C>http://sourceforge.net/projects/linux-udf/
Емнип, если просто массив нулевой длинны -- он должен быть 1 и последним элементом в структуре. Используй boost::array<T,0> Если тебе эти поля дороги как память.
<Подпись удалена модератором>
Re[4]: struct has an illegal zero-sized array
От: cppguy  
Дата: 06.01.10 16:41
Оценка: :)
не знаю на сколько то хорошо, но проблема компиляции решилась помещением массивов нулевой длинны в union.
Re: struct has an illegal zero-sized array
От: IROV..  
Дата: 06.01.10 18:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?


А>
А>/** Logical Volume Integrity Descriptor (ECMA 167r3 3/10.10) */
А>struct logvol_integrity_desc_s
А>{
А>  udf_tag_t       tag;
А>  udf_timestamp_t recording_time;
А>  udf_Uint32_t    integrity_type;
А>  udf_extent_ad_t next_integrity_ext;
А>  udf_Uint8_t     logvol_contents_use[32];
А>  udf_Uint32_t    i_partitions;
А>  udf_Uint32_t    imp_use_len;
А>  udf_Uint32_t    freespace_table[0];
А>  udf_Uint32_t    size_table[0];
А>  udf_Uint8_t     imp_use[0]; 
А>} GNUC_PACKED;
А>


imp_use[0] используется как указание начала масива, а масив располагается дальше по стеку/памяти, встречал в проектах как "оптимизация"
я не волшебник, я только учусь!
Re: struct has an illegal zero-sized array
От: Кодт Россия  
Дата: 06.01.10 19:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?


Не знаю, как победить нахаляву, а как победить некоторым рефакторингом — так это просто
А>
А>struct logvol_integrity_desc_header_s /* выделяем заголовок пакета в отдельную структуру */
А>{
А>  udf_tag_t       tag;
А>  udf_timestamp_t recording_time;
А>  udf_Uint32_t    integrity_type;
А>  udf_extent_ad_t next_integrity_ext;
А>  udf_Uint8_t     logvol_contents_use[32];
А>  udf_Uint32_t    i_partitions;
А>  udf_Uint32_t    imp_use_len;
  };

  struct logvol_integrity_desc_fictive /* фиктивная структура, описывающая пакет целиком */
  {
    struct logvol_integrity_desc_header_s header; /* а если это С++ - то проще унаследовать */
    union
    {
А>    udf_Uint32_t    freespace_table[1];
А>    udf_Uint32_t    size_table[1];
А>    udf_Uint8_t     imp_use[1];
    }; 
А>};
А>

Правда, рефакторинг выйдет кровавый... (а впрочем, это и хорошо, ибо все ошибки будут пойманы на стадии компиляции).

Возможно, что достаточно просто обрамить три последних поля (фиктивные массивы) в юнион, и указать им длину в 1, а не в 0.
И затем обязательно отследить по всей программе, что размер структуры берётся правильно — без учёта этого фиктивного хвостика размером в 4 байта.
Перекуём баги на фичи!
Re[2]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 08.01.10 08:15
Оценка:
Здравствуйте, Кодт, Вы писали:

А>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?


К>Не знаю, как победить нахаляву, а как победить некоторым рефакторингом — так это просто


Хммм... А почему просто не добавить union:

struct logvol_integrity_desc_s
{
  udf_tag_t       tag;
  udf_timestamp_t recording_time;
  udf_Uint32_t    integrity_type;
  udf_extent_ad_t next_integrity_ext;
  udf_Uint8_t     logvol_contents_use[32];
  udf_Uint32_t    i_partitions;
  udf_Uint32_t    imp_use_len;
  union {
  udf_Uint32_t    freespace_table[0];
  udf_Uint32_t    size_table[0];
  udf_Uint8_t     imp_use[0]; 
  };
} GNUC_PACKED;


Тут проблема не в массиве нулевой длины — студия их есть, а в том, что массив нулевой длины не последний в структуре.
Вариант с union студия должна съесть.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: struct has an illegal zero-sized array
От: Кодт Россия  
Дата: 14.01.10 20:57
Оценка:
Здравствуйте, remark, Вы писали:

R>Тут проблема не в массиве нулевой длины — студия их есть, а в том, что массив нулевой длины не последний в структуре.

R>Вариант с union студия должна съесть.

Ааа, ну если студия съест, то супер. Я было решил, что дело в размере.
Перекуём баги на фичи!
Re[2]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 07:42
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Массивы из нуля элементов запрещены. А нафига они?


Это расширение gcc, активно используемое в ядре линукса. Не знаю зачем их несколько может понадобится в структуре, но вот один последний такой элемент часто используется для обращения к данным,записанным за конец структуры.
gcc [0]
Re[4]: struct has an illegal zero-sized array
От: Кодт Россия  
Дата: 15.01.10 09:11
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Ааа, ну если студия съест, то супер. Я было решил, что дело в размере.


Нифига не супер. Съесть-то она съест, только посчитает [1] вместо [0].
struct Foo
{
    int x;
    union
    {
        int y[0];
        char z[0];
    };
};

struct FooBar
{
    char data[sizeof(Foo) + sizeof(int)*3];
    Foo* foo() { return (Foo*)data; }
    int* yyy() { return (int*)(data + sizeof(Foo)); }
};

int main()
{
    FooBar fb;
    Foo& f = *fb.foo();
    int* y =  fb.yyy();
    
    f.y[0] = 123456789;
    f.y[1] = 987654321;
    f.y[1] = 555555555;
    printf("%d : %d %d", sizeof(Foo), y[0], y[1]);
    // VC  --> 8 : 987654321 555555555
    // gcc --> 4 : 123456789 987654321
}

То есть, для интерпретации уже готового пакета как заголовок+хвост это пригодно, а для построения такого пакета — увы.
Перекуём баги на фичи!
Re[3]: struct has an illegal zero-sized array
От: Кодт Россия  
Дата: 15.01.10 09:27
Оценка:
Здравствуйте, Skorodum, Вы писали:

S>Это расширение gcc, активно используемое в ядре линукса. Не знаю зачем их несколько может понадобится в структуре, но вот один последний такой элемент часто используется для обращения к данным,записанным за конец структуры.


Очевидно, зачем. Если данные за концом структуры могут иметь разный тип (видимо, в зависимости от содержания данной структуры).
Например, у битмапа есть общий заголовок, после которого идут 8-, 16-, 24- или 32-битные пикселы.
Перекуём баги на фичи!
Re[4]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 13:00
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Skorodum, Вы писали:


S>>Это расширение gcc, активно используемое в ядре линукса. Не знаю зачем их несколько может понадобится в структуре, но вот один последний такой элемент часто используется для обращения к данным,записанным за конец структуры.


К>Очевидно, зачем. Если данные за концом структуры могут иметь разный тип (видимо, в зависимости от содержания данной структуры).

К>Например, у битмапа есть общий заголовок, после которого идут 8-, 16-, 24- или 32-битные пикселы.

Как я понимаю
stract foo
{
    int a;
    int b[0];
    short c[0];
};


и b и с — это ведь просто адрес прямо за концом структуры:

foo f;
f.b == f.c;
f.b == int(&f) + sizeof(foo);


Поясните, пожалуйста, подробнее зачем таких переменных больше одной?
[0]
Re[5]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 13:14
Оценка: 34 (2)
Здравствуйте, Skorodum, Вы писали:

S>и b и с — это ведь просто адрес прямо за концом структуры:


Синтаксический сахар за борт, полагаю, что типы нулевых массивов влияют на выравнивание. Во-первых, это должен быть не просто "адрес за концом структуры", а адрес, зависящий от типа нулевого массива.
Т.е. в таком коде адреса bar и baz могут быть разными:
struct X
{
  char foo [1];
  char bar [0];
  int  baz [0];
};


Во-вторых, типы нулевых массивов должны влиять и на размер структуры. Это необходимо для работы идиомы выделения таких объектов — "malloc(sizeof(X) + sizeof(Y) * N)".
Т.е. в таком коде, включив или bar или baz, ты получишь разный sizeof(X):
struct X
{
  char foo [1];
  //char bar [0];
  //int  baz [0];
};


Т.о. если за структрурой могут лежать массивы действительно разных типов, то помещение нескольких нулевых массивов в структуру необходимо. В противном случае придётся жёстко заморачиваться с max_align_t.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 13:31
Оценка:
Здравствуйте, remark, Вы писали:

R>Синтаксический сахар за борт, полагаю, что типы нулевых массивов влияют на выравнивание. Во-первых, это должен быть не просто "адрес за концом структуры", а адрес, зависящий от типа нулевого массива.

R>Т.е. в таком коде адреса bar и baz могут быть разными:
R>
R>struct X
R>{
R>  char foo [1];
R>  char bar [0];
R>  int  baz [0];
R>};
R>


gcc показывает что не зависит. И bar и baz — всего лишь адрес, в структуре такой переменной нет:

struct Foo
{
    int a;
    long long k[0];
    int b[0];
    short c[0];
    char d[0];
};

struct Bar
{
    int a;
};


int main()
{
    Foo f;
    if((int)&f + sizeof(Foo) == int(f.k) &&
       (int)&f + sizeof(Foo) == int(f.b) &&
       (int)&f + sizeof(Foo) == int(f.c) &&
       (int)&f + sizeof(Foo) == int(f.d) &&
       sizeof(Bar) == sizeof(Foo))
        std::cout << "no difference" << std::endl;
    return 0;
}



R>Во-вторых, типы нулевых массивов должны влиять и на размер структуры. Это необходимо для работы идиомы выделения таких объектов — "malloc(sizeof(X) + sizeof(Y) * N)".

R>Т.е. в таком коде, включив или bar или baz, ты получишь разный sizeof(X):
R>
R>struct X
R>{
R>  char foo [1];
R>  //char bar [0];
R>  //int  baz [0];
R>};
R>


То же самое, gcc показывает что не зависит. Нулевые массивы не добавляют к структуре ничего.

R>Т.о. если за структрурой могут лежать массивы действительно разных типов, то помещение нескольких нулевых массивов в структуру необходимо. В противном случае придётся жёстко заморачиваться с max_align_t.


Вот это правда, с выравниванием заморачиваются.

R>

[0] gcc
Re[7]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 13:46
Оценка:
Здравствуйте, Skorodum, Вы писали:

R>>Во-вторых, типы нулевых массивов должны влиять и на размер структуры. Это необходимо для работы идиомы выделения таких объектов — "malloc(sizeof(X) + sizeof(Y) * N)".

R>>Т.е. в таком коде, включив или bar или baz, ты получишь разный sizeof(X):
R>>
R>>struct X
R>>{
R>>  char foo [1];
R>>  //char bar [0];
R>>  //int  baz [0];
R>>};
R>>


S>То же самое, gcc показывает что не зависит. Нулевые массивы не добавляют к структуре ничего.


Хммм... что-то я не уверен. Как так может быть? Тогда "malloc(sizeof(X) + sizeof(Y) * N)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 13:47
Оценка:
Здравствуйте, Skorodum, Вы писали:

S>gcc показывает что не зависит. И bar и baz — всего лишь адрес, в структуре такой переменной нет:


S>
S>struct Foo
S>{
S>    int a;
S>    long long k[0];
S>    int b[0];
S>    short c[0];
S>    char d[0];
S>};

S>struct Bar
S>{
S>    int a;
S>};


S>int main()
S>{
S>    Foo f;
S>    if((int)&f + sizeof(Foo) == int(f.k) &&
S>       (int)&f + sizeof(Foo) == int(f.b) &&
S>       (int)&f + sizeof(Foo) == int(f.c) &&
S>       (int)&f + sizeof(Foo) == int(f.d) &&
S>       sizeof(Bar) == sizeof(Foo))
S>        std::cout << "no difference" << std::endl;
S>    return 0;
S>}
S>


А если а объявить как char, а не как int?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 13:52
Оценка:
Здравствуйте, remark, Вы писали:

R>А если а объявить как char, а не как int?


no difference



gcc version 3.4.5
Re[9]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 14:02
Оценка:
Здравствуйте, Skorodum, Вы писали:

S>Здравствуйте, remark, Вы писали:


R>>А если а объявить как char, а не как int?


S>no difference


S>gcc version 3.4.5


Не может так быть.

#include <stdio.h>
#include <stdint.h>

struct Y
{
  char ch;
};

struct X
{
  char ch;
  uint64_t arr [0];
};

int main()
{
  printf("sizeof(Y)=%u\n", sizeof(Y));
  printf("sizeof(X)=%u\n", sizeof(X));
}


g++ -v
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

sizeof(Y)=1
sizeof(X)=4


Просто баг в gcc 3.4.5. Проапдейть до более новой версии.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 14:05
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Skorodum, Вы писали:


R>>>Во-вторых, типы нулевых массивов должны влиять и на размер структуры. Это необходимо для работы идиомы выделения таких объектов — "malloc(sizeof(X) + sizeof(Y) * N)".

R>>>Т.е. в таком коде, включив или bar или baz, ты получишь разный sizeof(X):
R>>>
R>>>struct X
R>>>{
R>>>  char foo [1];
R>>>  //char bar [0];
R>>>  //int  baz [0];
R>>>};
R>>>


S>>То же самое, gcc показывает что не зависит. Нулевые массивы не добавляют к структуре ничего.


R>Хммм... что-то я не уверен. Как так может быть? Тогда "malloc(sizeof(X) + sizeof(Y) * N)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало...

Вы же сами написали: надо заморачиваться с выравниванием. В линухе используют макросы для этого.

Я вот не понимаю зачем несколько таких нулевых массивов может понадобиться
Re[9]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 14:28
Оценка:
Здравствуйте, Skorodum, Вы писали:

R>>Хммм... что-то я не уверен. Как так может быть? Тогда "malloc(sizeof(X) + sizeof(Y) * N)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало...

S>Вы же сами написали: надо заморачиваться с выравниванием. В линухе используют макросы для этого.

S>Я вот не понимаю зачем несколько таких нулевых массивов может понадобиться


Потому что они влияют и на адрес и на размер структруры. Не наводите, пожалуйста, тень на плетень со старым компилятором.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>

struct Y
{
  char ch;
};

struct X
{
  char     ch;
  char     arr1 [0];
  int      arr2 [0];
  double   arr3 [0];
};

typedef struct X X_t;

int main()
{
  printf("sizeof(Y)=%u\n", sizeof(struct Y));
  printf("sizeof(X)=%u\n", sizeof(struct X));
  printf("offsetof(arr1)=%u\n", offsetof(X_t, arr1));
  printf("offsetof(arr2)=%u\n", offsetof(X_t, arr2));
  printf("offsetof(arr3)=%u\n", offsetof(X_t, arr3));
  return 0;
}


[test]$ gcc -v
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
[test]$ gcc test.c -o test -malign-double
[test]$ ./test
sizeof(Y)=1
sizeof(X)=8
offsetof(arr1)=1
offsetof(arr2)=4
offsetof(arr3)=8




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: struct has an illegal zero-sized array
От: Кодт Россия  
Дата: 15.01.10 14:28
Оценка:
Здравствуйте, Skorodum, Вы писали:

S>Поясните, пожалуйста, подробнее зачем таких переменных больше одной?


Ну, как бы, на примере
struct rgb555  { unsigned char r:5, g:6, b:5; }; // 16-bit
struct rgb888  { unsigned char r, g, b; };
struct rgba888 { unsigned char r, g, b, a; };

struct my_bitmap_header
{
  unsigned short signature;
  enum { monochrome, palette, hicolor, truecolor, alphatruecolor } type;
  int width, height;

  // union {
    unsigned short bits[0]; // в монохромной картинке пикселы сгруппированы по 2 байта
    unsigned char  pixels_pal[0];
    rgb565         pixels_hc[0];
    rgb888         pixels_tc[0];
    rgba888        pixels_tca[0];
  // };
};

Без union — VC не скомпилирует, с union — допишет в конец структуры один лишний пиксел самого большого размера.
В общем, спасибо, что под линуксом один "главный" компилятор, а не разброд и шатания, как в мире закрытых окон.

А пользуются этим добром вот так:
unsigned char *raw_bmp;
// грузим его из файла

my_bitmap_header* bmp = (my_bitmap_header*)raw_bmp;
switch(bmp->type)
{
case truecolor:
   // работаем с bmp->pixels_tc[]
}
Перекуём баги на фичи!
Re[6]: struct has an illegal zero-sized array
От: gear nuke  
Дата: 15.01.10 14:31
Оценка:
Здравствуйте, remark, Вы писали:

R>Синтаксический сахар за борт, полагаю, что типы нулевых массивов влияют на выравнивание.


Не знаю как у *nix, но в ядре Винды все выравнивания обычно делаются за счёт явных dummy полей (и вообще тщательно выбирается место для полей разного размера).

Структуру с несколькими типами в конце сходу не вспомню, но для доступа к таким полям используют:
#define MmGetMdlPfnArray(Mdl) ((PPFN_NUMBER)(Mdl + 1))

Многие структуры в доке описаны как opaque + макросы для доступа:
#define NDIS_PACKET_EXTENSION_FROM_PACKET(_P)       ((PNDIS_PACKET_EXTENSION)((PUCHAR)(_P) + (_P)->Private.NdisPacketOobOffset + sizeof(NDIS_PACKET_OOB_DATA)))
#define NDIS_PER_PACKET_INFO_FROM_PACKET(_P, _Id)   ((PNDIS_PACKET_EXTENSION)((PUCHAR)(_P) + (_P)->Private.NdisPacketOobOffset + sizeof(NDIS_PACKET_OOB_DATA)))->NdisPacketInfo[(_Id)]
#define NDIS_GET_ORIGINAL_PACKET(_P)                NDIS_PER_PACKET_INFO_FROM_PACKET(_P, OriginalPacketInfo)
#define NDIS_SET_ORIGINAL_PACKET(_P, _OP)           NDIS_PER_PACKET_INFO_FROM_PACKET(_P, OriginalPacketInfo) = _OP
#define NDIS_GET_PACKET_CANCEL_ID(_P)               NDIS_PER_PACKET_INFO_FROM_PACKET(_P, PacketCancelId)
#define NDIS_SET_PACKET_CANCEL_ID(_P, _cId)         NDIS_PER_PACKET_INFO_FROM_PACKET(_P, PacketCancelId) = _cId
наверное, private в C нет...
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[10]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 14:33
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Skorodum, Вы писали:


S>>Здравствуйте, remark, Вы писали:


R>>>А если а объявить как char, а не как int?


S>>no difference


S>>gcc version 3.4.5


R>Не может так быть.


R>
R>#include <stdio.h>
R>#include <stdint.h>

R>struct Y
R>{
R>  char ch;
R>};

R>struct X
R>{
R>  char ch;
R>  uint64_t arr [0];
R>};

R>int main()
R>{
R>  printf("sizeof(Y)=%u\n", sizeof(Y));
R>  printf("sizeof(X)=%u\n", sizeof(X));
R>}
R>


R>

R>g++ -v
R>gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

R>sizeof(Y)=1
R>sizeof(X)=4


R>Просто баг в gcc 3.4.5. Проапдейть до более новой версии.


Все верно, если первый и единственный член — char, то разница есть. Но, 4 != sizeof(char) + sizeof(uint64_t*). Более того, если добавить еще нулевых указателей, размер не изменится. Наверное, изменение размера связано с необходимостью выравнивания.
Re[11]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 14:35
Оценка:
Здравствуйте, Skorodum, Вы писали:

R>>Просто баг в gcc 3.4.5. Проапдейть до более новой версии.


S>Все верно, если первый и единственный член — char, то разница есть. Но, 4 != sizeof(char) + sizeof(uint64_t*). Более того, если добавить еще нулевых указателей, размер не изменится. Наверное, изменение размера связано с необходимостью выравнивания.


Именно.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: struct has an illegal zero-sized array
От: Кодт Россия  
Дата: 15.01.10 14:37
Оценка:
Здравствуйте, remark, Вы писали:

R>Потому что они влияют и на адрес и на размер структруры. Не наводите, пожалуйста, тень на плетень со старым компилятором.


R>gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

R>[test]$ gcc test.c -o test -malign-double
R>[test]$ ./test
R>sizeof(Y)=1
R>sizeof(X)=8
R>offsetof(arr1)=1
R>offsetof(arr2)=4
R>offsetof(arr3)=8

Тот же самый результат, gcc 3.4.4 (cygwin), без -malign-double
Перекуём баги на фичи!
Re[11]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 14:38
Оценка:
Здравствуйте, Skorodum, Вы писали:
R>>Просто баг в gcc 3.4.5. Проапдейть до более новой версии.

S>Все верно, если первый и единственный член — char, то разница есть. Но, 4 != sizeof(char) + sizeof(uint64_t*). Более того, если добавить еще нулевых указателей, размер не изменится.


Изменится. И не только размер структуры, но и адреса этих самых нулевых массивов.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: struct has an illegal zero-sized array
От: gear nuke  
Дата: 15.01.10 14:42
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Нифига не супер. Съесть-то она съест, только посчитает [1] вместо [0].


Я уже проверить не могу, но это возможно от версии компилятора, или каких-то ключей зависит. По крайней мере раньше работал такой код:
class type_info
{
// ...
  private:
    mutable void* data;
    char    mname[1];
};

а потом пришлось изменить на:
class type_info
{
// ...
  private:
    mutable void* data;
    const char* mname() const { return reinterpret_cast<const char*>(this + 1); }
};
#if defined(_MSC_VER) && !defined(__ICL)
///\warning break this to get `Unresolved external : const type_info::'vftable' (??_7type_info@@6B@)`
static_assert(sizeof _TypeDescriptor == sizeof type_info, "broken type");
#endif

К>То есть, для интерпретации уже готового пакета как заголовок+хвост это пригодно, а для построения такого пакета — увы.

Да, опасная штука.
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[10]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 14:56
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Skorodum, Вы писали:


R>>>Хммм... что-то я не уверен. Как так может быть? Тогда "malloc(sizeof(X) + sizeof(Y) * N)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало...

S>>Вы же сами написали: надо заморачиваться с выравниванием. В линухе используют макросы для этого.

S>>Я вот не понимаю зачем несколько таких нулевых массивов может понадобиться


R>Потому что они влияют и на адрес и на размер структруры. Не наводите, пожалуйста, тень на плетень со старым компилятором.


gcc version 3.4.5

sizeof(Y)=1
sizeof(X)=4
offsetof(arr1)=1
offsetof(arr2)=4
offsetof(arr3)=4


...но еще нулевых массивов и результат не меняется, где же память под новые указатели?...

struct X
{
  char     ch;
  char     arr1 [0];
  int      arr2 [0];
  double   arr3 [0];
  int      arr4 [0];
  char     arr5 [0];
};

typedef struct X X_t;

int main()
{
  printf("sizeof(Y)=%u\n", sizeof(struct Y));
  printf("sizeof(X)=%u\n", sizeof(struct X));
  printf("offsetof(arr1)=%u\n", offsetof(X_t, arr1));
  printf("offsetof(arr2)=%u\n", offsetof(X_t, arr2));
  printf("offsetof(arr3)=%u\n", offsetof(X_t, arr3));
  printf("offsetof(arr3)=%u\n", offsetof(X_t, arr4));
  printf("offsetof(arr3)=%u\n", offsetof(X_t, arr5));
  return 0;
}


sizeof(Y)=1
sizeof(X)=8
offsetof(arr1)=1
offsetof(arr2)=4
offsetof(arr3)=8
offsetof(arr4)=8
offsetof(arr5)=8

Re[11]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 14:59
Оценка:
Здравствуйте, Skorodum, Вы писали:

S>...но еще нулевых массивов и результат не меняется, где же память под новые указатели?...


А почему ты думаешь, что они должны занимать память?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 15:00
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Skorodum, Вы писали:


R>>>Просто баг в gcc 3.4.5. Проапдейть до более новой версии.


S>>Все верно, если первый и единственный член — char, то разница есть. Но, 4 != sizeof(char) + sizeof(uint64_t*). Более того, если добавить еще нулевых указателей, размер не изменится. Наверное, изменение размера связано с необходимостью выравнивания.


R>Именно.


Т.е.

struct Foo
{
   char ch;
   char a[0]; //будет содержать адрес куда можно записывать char
   int b[0]; //будет содержать адрес куда можно записывать int
   double c[0]; //будет содержать адрес куда можно записывать double
   ...
};


R>
Re[13]: struct has an illegal zero-sized array
От: remark Россия http://www.1024cores.net/
Дата: 15.01.10 15:04
Оценка:
Здравствуйте, Skorodum, Вы писали:

S>Т.е.

S>

S>struct Foo
S>{
S>   char ch;
S>   char a[0]; //будет содержать адрес куда можно записывать char
S>   int b[0]; //будет содержать адрес куда можно записывать int
S>   double c[0]; //будет содержать адрес куда можно записывать double
S>   ...
S>};
S>


Если это был вопрос, то — да. Адрес 'a' подходит для записи/чтения чаров, 'b' — интов, 'c' — даблов. Очевидно, что адрес, который подходит для записи/чтения чаров, может не подходить для записи/чтения даблов.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 15:05
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Skorodum, Вы писали:


S>>...но еще нулевых массивов и результат не меняется, где же память под новые указатели?...


R>А почему ты думаешь, что они должны занимать память?


Не должны. Тогда и на размер структуры не должно влиять их количество, размер увеличивается на выравнивания, необходимое для записи наибольшего типа.

R>
Re[14]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 15.01.10 15:10
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Skorodum, Вы писали:


S>>Т.е.

S>>

S>>struct Foo
S>>{
S>>   char ch;
S>>   char a[0]; //будет содержать адрес куда можно записывать char
S>>   int b[0]; //будет содержать адрес куда можно записывать int
S>>   double c[0]; //будет содержать адрес куда можно записывать double
S>>   ...
S>>};
S>>


R>Если это был вопрос, то — да. Адрес 'a' подходит для записи/чтения чаров, 'b' — интов, 'c' — даблов. Очевидно, что адрес, который подходит для записи/чтения чаров, может не подходить для записи/чтения даблов.


и размер структуры будет выравнен на double, хоть после ch ничего полезного и не записано.

R>
Re[6]: struct has an illegal zero-sized array
От: Skorodum Россия  
Дата: 16.01.10 05:02
Оценка:
Здравствуйте, Кодт, Вы писали:

Спасибо, разжевали.

Мне приходилось сталкиваться только со случаем, когда в качестве данных — набор элементов неизвестной и переменной длины. Естественно, все выравнено по максимуму и нулевые массивы любых типов указывают на один и тот же адрес, вот до меня долго и доходило зачем их может несколько понадобиться. Век живи — век учись!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.