Quasar 20 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба При таком определении компилятор ругается: typedef struct { const char Engl[]; const char Russ[]; } LangStruct PROGMEM; Мол переменной длинны, массив не в конце. Собственно вопрос, а возможно ли вообще в С размещать таким образом два массива? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба При таком определении компилятор ругается: typedef struct { const char Engl[]; const char Russ[]; } LangStruct PROGMEM; Мол переменной длинны, массив не в конце. Собственно вопрос, а возможно ли вообще в С размещать таким образом два массива? Нет конечно! Ни один, ни два и не десять массивов (в структуре или нет) так определять нельзя. И компилятор ругается справедливо, ибо размеры массивов не заданы, соответственно, компилятор не знает, сколько памяти надо для размещения переменной такого типа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 30 июля, 2007 Опубликовано 30 июля, 2007 (изменено) · Жалоба Нет конечно! Ни один, ни два и не десять массивов (в структуре или нет) так определять нельзя. И компилятор ругается справедливо, ибо размеры массивов не заданы, соответственно, компилятор не знает, сколько памяти надо для размещения переменной такого типа. Почему это ни одного? typedef struct { void *Next; void *Previous; void *Parent; void *Sibling; FuncPtr SelectFunc; FuncPtr EnterFunc; const char Text[]; } Menu_Item PROGMEM; Прекрасно компилится и работает. (Это из MicroMenu взято). Проблема именно в двух таких массивах. Да, и к тому же опеределение типа extern char mass[]; тоже вполне работает, но это уже отдельный разговор... Изменено 30 июля, 2007 пользователем Quasar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба Можно сделать немного по другому, если Вы не знаете точно, какой длины массивы будут typedef struct { const char *pEngl; /* указатель на массив Engl */ const char pRuss; /* указатель на массив Russ */ } LangStruct PROGMEM; А далее в конструкторе (функции инициализации) указателям присваивать конкретные адреса массивов... Еще бы я добавил, в таком случае, в структуру размеры массивов. Почему это ни одного? typedef struct { void *Next; void *Previous; void *Parent; void *Sibling; FuncPtr SelectFunc; FuncPtr EnterFunc; const char Text[]; } Menu_Item PROGMEM; Прекрасно компилится и работает. (Это из MicroMenu взято). Проблема именно в двух таких массивах. Да, и к тому же опеределение типа extern char mass[]; тоже вполне работает, но это уже отдельный разговор... Интересно, а какой размер массива Text??? Зеро байт? :) Или миллион? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба Можно сделать немного по другому, если Вы не знаете точно, какой длины массивы будут typedef struct { const char *pEngl; /* указатель на массив Engl */ const char pRuss; /* указатель на массив Russ */ } LangStruct PROGMEM; А далее в конструкторе (функции инициализации) указателям присваивать конкретные адреса массивов... Еще бы я добавил, в таком случае, в структуру размеры массивов. Ну да, видимо так и сделаю. Интересно, а какой размер массива Text??? Зеро байт? :) Или миллион? А ни какой, это примерно аналогично extern char Mass[], то есть происходит определение, а память выделяется при создании экземпляра. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба А ни какой, это примерно аналогично extern char Mass[], то есть происходит определение, а память выделяется при создании экземпляра. ИМХО это очччень не хорошо, если это на самом деле работает. Ни когда не известно, какого размера структура :07: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
umup 0 30 июля, 2007 Опубликовано 30 июля, 2007 (изменено) · Жалоба В определении типа не нужно указывать атрибутов (PROGMEM), они указываются при обьявлении переменных этого типа : typedef struct { const char Engl[size1]; const char Russ[size2]; } LangStruct; LangStruct PROGMEM str1; LangStruct EEPROM str2; в данном случае str1 будет размещена в программной памяти, str2 - в eeprom. size1, size2 должны быть определены перед обьявлением типа... Изменено 30 июля, 2007 пользователем umup Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 30 июля, 2007 Опубликовано 30 июля, 2007 (изменено) · Жалоба ИМХО это очччень не хорошо, если это на самом деле работает. Ни когда не известно, какого размера структура Ну почему не известно, длинна всех типов в структуре, плюс длинна массива, полученная при инициализации, так получается. Кстати именно поэтому видимо и требование такое, что бы массив был в конце структуры, вот два и не получится разместить :crying: . В определении типа не нужно указывать атрибутов (PROGMEM), они указываются при обьявлении переменных этого типа : Ну почему же не нужно, смотря для чего, в данном случае надо что бы всё было во флеш, зачем же тогда по сто раз PROGMEM писать. :) Изменено 30 июля, 2007 пользователем Quasar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба Ну почему не известно, длинна всех типов в структуре, плюс длинна массива, полученная при инициализации, так получается. Кстати именно поэтому видимо и требование такое, что бы массив был в конце структуры, вот два и не получится разместить :crying: . Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но как, допустим, определить массив Ваших структур??? И как, допустим, в цикле их перебирать если все структуры разной длины??? Кстати, можете показать код инициализации члена Text[] структуры Menu_Item? Что то у меня не получилось :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба И как, допустим, в цикле их перебирать если все структуры разной длины??? Да, с перебором в цикле - проблема :) . Но как Вы могли догадаться, в массиве Text[] храниться текст :) , и вообщем-то данный приём только для текста-то и полезен, ибо в цикле чаще всего стоит условие while ( '\0' != Text[i++]) то есть перебираем весь массив, допустим для печати. Ну а в плане инициализации то: typedef struct { void *Next; void *Previous; void *Parent; void *Sibling; FuncPtr SelectFunc; FuncPtr EnterFunc; const char Text[]; } Menu_Item PROGMEM; Menu_Item MyStruct = {(void*)&SomePtr, (void*)&SomePtr, (void*)&SomePtr, (void*)&SomePtr, (FuncPtr)SomeFnc, (FuncPtr)SomeFnc, { "SomeTEXT" }}; Ну а полный код взят собственно здесь: http://electronix.ru/forum/index.php?act=A...st&id=10450 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но Обычно в таких случаях либо концевой массив содержит нечто "самоограниченное" (null-terminated string, массив указателей с NULL как ограничителем), либо его размер находится в самой структуре. Например, эта структура - заготовка для кольцевого буфера, делаем malloc( sizeof(этой_структуры) + buffer_len) и присваиваем нужному полю buffer_len. как, допустим, определить массив Ваших структур??? И как, допустим, в цикле их перебирать если все структуры разной длины??? А никак. Массив [] - это incomplete array, структура с ним в конце - incomplete type, по стандарту из них массивы не собираются. Естественно, массивы из указателей на них - запросто и в цикле перебирается :-) Кстати, можете показать код инициализации члена Text[] структуры Menu_Item? Что то у меня не получилось :) Без проблем. typedef struct { int i; char c[]; } s; s s1 = { 1, "abc" }; s s2 = { 1, "qwerty" }; struct { int i; int ii[]; } ss = { 1, {1, 2, 3} }; avr-gcc -S .file "f.c" .arch avr2 __SREG__ = 0x3f __SP_H__ = 0x3e __SP_L__ = 0x3d __tmp_reg__ = 0 __zero_reg__ = 1 .global __do_copy_data .global __do_clear_bss .global s1 .data .type s1, @object .size s1, 2 s1: .word 1 .string "abc" .global s2 .type s2, @object .size s2, 2 s2: .word 1 .string "qwerty" .global ss .type ss, @object .size ss, 2 ss: .word 1 .word 1 .word 2 .word 3 /* File "f.c": code 0 = 0x0000 ( 0), prologues 0, epilogues 0 */ Кстати, до введения этого в стандарт выкручивались, задавая размер 1. В некоторых компиляторах можно было задать 0, чтобы sizeof от типа не включал сам массив, т.е. чтобы в malloc можно было писать не неестественное malloc( sizeof(ring_buf_t) + buf_size - 1); // один элемент есть в структуре а нормальное malloc( sizeof(ring_buf_t) + buf_size); Но проблемой этих выкрутасов было в том числе то, что компилятор не запрещал создать массив таких структур. А теперь может выдать ошибку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба typedef struct { int i; char c[]; } s; s s1 = { 1, "abc" }; s s2 = { 1, "qwerty" }; В IAR (по крайней мере в версии 4.10, что у меня) это не работает. И ИМХО - это правильно (что не работает :) ). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба И ИМХО - это правильно (что не работает :) ). И не может работать в принципе. Все правильно. Такие структуры используются для наложения на уже сущестующую память. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба И не может работать в принципе. Все правильно. В смысле не может, всё работает, если использовать только один массив (ну во всяком случае в gcc), вот с двумя уже нет. А что значит, наложение на уже существующую память? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 30 июля, 2007 Опубликовано 30 июля, 2007 · Жалоба Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но как, допустим, определить массив Ваших структур??? И как, допустим, в цикле их перебирать если все структуры разной длины??? Кстати, можете показать код инициализации члена Text[] структуры Menu_Item? Что то у меня не получилось :) А я так работаю. И ни единого глюка нет, хотя код сейчас 56к. У меня правда определён один массив в конце структуры. Работаю я через кучу и указатели. То есть при создании экземпляра создаётся указатель на структуру. При вызове используется данный указатель. Использую и массивы структур и сортировку. Никаких проблем. Структуры имеют разные поля и разные массивы. Создаются и удаляются. Единственное, что я упростил диспетчер кучи. Поленился. Надо будет попробовать последовать совету zltigo и написать свой. Что особенно хочется отметить, это отличную работу отладчика (пользую IAR_C-AVR_Studio) со всем этим барахлом. Я думал будет намного хуже. Не смотри что указатели. Полный доступ к полям. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться