Здравствуйте, Vamp, Вы писали:
А>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229? V>Массивы из нуля элементов запрещены. А нафига они?
Здравствуйте, Vamp, Вы писали:
А>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229? V>Массивы из нуля элементов запрещены. А нафига они?
Здравствуйте, cppguy, Вы писали:
C>Здравствуйте, Vamp, Вы писали:
А>>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229? V>>Массивы из нуля элементов запрещены. А нафига они?
C>стандартом они не запрещены, код из модуля ядра линукса C>http://sourceforge.net/projects/linux-udf/
Емнип, если просто массив нулевой длинны -- он должен быть 1 и последним элементом в структуре. Используй boost::array<T,0> Если тебе эти поля дороги как память.
Здравствуйте, Аноним, Вы писали:
А>Пытаюсь скомпилять код из 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 байта.
Здравствуйте, Кодт, Вы писали:
А>>Пытаюсь скомпилять код из linux на msvc, как убороть проблему ошибки C2229?
К>Не знаю, как победить нахаляву, а как победить некоторым рефакторингом — так это просто
Тут проблема не в массиве нулевой длины — студия их есть, а в том, что массив нулевой длины не последний в структуре.
Вариант с union студия должна съесть.
Здравствуйте, remark, Вы писали:
R>Тут проблема не в массиве нулевой длины — студия их есть, а в том, что массив нулевой длины не последний в структуре. R>Вариант с union студия должна съесть.
Ааа, ну если студия съест, то супер. Я было решил, что дело в размере.
Здравствуйте, Vamp, Вы писали:
V>Массивы из нуля элементов запрещены. А нафига они?
Это расширение gcc, активно используемое в ядре линукса. Не знаю зачем их несколько может понадобится в структуре, но вот один последний такой элемент часто используется для обращения к данным,записанным за конец структуры.
Здравствуйте, Skorodum, Вы писали:
S>Это расширение gcc, активно используемое в ядре линукса. Не знаю зачем их несколько может понадобится в структуре, но вот один последний такой элемент часто используется для обращения к данным,записанным за конец структуры.
Очевидно, зачем. Если данные за концом структуры могут иметь разный тип (видимо, в зависимости от содержания данной структуры).
Например, у битмапа есть общий заголовок, после которого идут 8-, 16-, 24- или 32-битные пикселы.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, 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);
Поясните, пожалуйста, подробнее зачем таких переменных больше одной?
Здравствуйте, 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.
Здравствуйте, 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>
Здравствуйте, 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)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало...
Здравствуйте, 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)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало...
Вы же сами написали: надо заморачиваться с выравниванием. В линухе используют макросы для этого.
Я вот не понимаю зачем несколько таких нулевых массивов может понадобиться
Здравствуйте, Skorodum, Вы писали:
R>>Хммм... что-то я не уверен. Как так может быть? Тогда "malloc(sizeof(X) + sizeof(Y) * N)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало... S>Вы же сами написали: надо заморачиваться с выравниванием. В линухе используют макросы для этого.
S>Я вот не понимаю зачем несколько таких нулевых массивов может понадобиться
Потому что они влияют и на адрес и на размер структруры. Не наводите, пожалуйста, тень на плетень со старым компилятором.
Без union — VC не скомпилирует, с union — допишет в конец структуры один лишний пиксел самого большого размера.
В общем, спасибо, что под линуксом один "главный" компилятор, а не разброд и шатания, как в мире закрытых окон.
А пользуются этим добром вот так:
unsigned char *raw_bmp;
// грузим его из файла
my_bitmap_header* bmp = (my_bitmap_header*)raw_bmp;
switch(bmp->type)
{
case truecolor:
// работаем с bmp->pixels_tc[]
}
Здравствуйте, remark, Вы писали:
R>Синтаксический сахар за борт, полагаю, что типы нулевых массивов влияют на выравнивание.
Не знаю как у *nix, но в ядре Винды все выравнивания обычно делаются за счёт явных dummy полей (и вообще тщательно выбирается место для полей разного размера).
Структуру с несколькими типами в конце сходу не вспомню, но для доступа к таким полям используют:
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
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Skorodum, Вы писали:
S>>Здравствуйте, remark, Вы писали:
R>>>А если а объявить как char, а не как int?
S>>no difference
S>>gcc version 3.4.5
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*). Более того, если добавить еще нулевых указателей, размер не изменится. Наверное, изменение размера связано с необходимостью выравнивания.
Здравствуйте, Skorodum, Вы писали:
R>>Просто баг в gcc 3.4.5. Проапдейть до более новой версии.
S>Все верно, если первый и единственный член — char, то разница есть. Но, 4 != sizeof(char) + sizeof(uint64_t*). Более того, если добавить еще нулевых указателей, размер не изменится. Наверное, изменение размера связано с необходимостью выравнивания.
Здравствуйте, 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
Здравствуйте, Skorodum, Вы писали: R>>Просто баг в gcc 3.4.5. Проапдейть до более новой версии.
S>Все верно, если первый и единственный член — char, то разница есть. Но, 4 != sizeof(char) + sizeof(uint64_t*). Более того, если добавить еще нулевых указателей, размер не изменится.
Изменится. И не только размер структуры, но и адреса этих самых нулевых массивов.
К>То есть, для интерпретации уже готового пакета как заголовок+хвост это пригодно, а для построения такого пакета — увы.
Да, опасная штука.
.
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
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Skorodum, Вы писали:
R>>>Хммм... что-то я не уверен. Как так может быть? Тогда "malloc(sizeof(X) + sizeof(Y) * N)" не будет работать, а именно так все и пишут. Смысла тогда добавлять такую поддержку нулевых массивов мало... S>>Вы же сами написали: надо заморачиваться с выравниванием. В линухе используют макросы для этого.
S>>Я вот не понимаю зачем несколько таких нулевых массивов может понадобиться
R>Потому что они влияют и на адрес и на размер структруры. Не наводите, пожалуйста, тень на плетень со старым компилятором.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Skorodum, Вы писали:
R>>>Просто баг в gcc 3.4.5. Проапдейть до более новой версии.
S>>Все верно, если первый и единственный член — char, то разница есть. Но, 4 != sizeof(char) + sizeof(uint64_t*). Более того, если добавить еще нулевых указателей, размер не изменится. Наверное, изменение размера связано с необходимостью выравнивания.
R>Именно.
Т.е.
struct Foo
{
char ch;
char a[0]; //будет содержать адрес куда можно записывать charint b[0]; //будет содержать адрес куда можно записывать intdouble c[0]; //будет содержать адрес куда можно записывать double
...
};
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' — даблов. Очевидно, что адрес, который подходит для записи/чтения чаров, может не подходить для записи/чтения даблов.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Skorodum, Вы писали:
S>>...но еще нулевых массивов и результат не меняется, где же память под новые указатели?...
R>А почему ты думаешь, что они должны занимать память?
Не должны. Тогда и на размер структуры не должно влиять их количество, размер увеличивается на выравнивания, необходимое для записи наибольшего типа.
R>
Здравствуйте, 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>
Мне приходилось сталкиваться только со случаем, когда в качестве данных — набор элементов неизвестной и переменной длины. Естественно, все выравнено по максимуму и нулевые массивы любых типов указывают на один и тот же адрес, вот до меня долго и доходило зачем их может несколько понадобиться. Век живи — век учись!