|
WinAVR(Ну или C) + Массивы в структуре, Массивы в структуре. |
|
|
|
Jul 30 2007, 11:33
|

Местный
  
Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021

|
При таком определении компилятор ругается: Код typedef struct { const char Engl[]; const char Russ[]; } LangStruct PROGMEM; Мол переменной длинны, массив не в конце. Собственно вопрос, а возможно ли вообще в С размещать таким образом два массива?
|
|
|
|
|
Jul 30 2007, 11:43
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(Quasar @ Jul 30 2007, 19:33)  При таком определении компилятор ругается: Код typedef struct { const char Engl[]; const char Russ[]; } LangStruct PROGMEM; Мол переменной длинны, массив не в конце. Собственно вопрос, а возможно ли вообще в С размещать таким образом два массива? Нет конечно! Ни один, ни два и не десять массивов (в структуре или нет) так определять нельзя. И компилятор ругается справедливо, ибо размеры массивов не заданы, соответственно, компилятор не знает, сколько памяти надо для размещения переменной такого типа.
--------------------
|
|
|
|
|
Jul 30 2007, 11:48
|

Местный
  
Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021

|
Цитата(prottoss @ Jul 30 2007, 15:43)  Нет конечно! Ни один, ни два и не десять массивов (в структуре или нет) так определять нельзя. И компилятор ругается справедливо, ибо размеры массивов не заданы, соответственно, компилятор не знает, сколько памяти надо для размещения переменной такого типа. Почему это ни одного? Код typedef struct { void *Next; void *Previous; void *Parent; void *Sibling; FuncPtr SelectFunc; FuncPtr EnterFunc; const char Text[]; } Menu_Item PROGMEM; Прекрасно компилится и работает. (Это из MicroMenu взято). Проблема именно в двух таких массивах. Да, и к тому же опеределение типа extern char mass[]; тоже вполне работает, но это уже отдельный разговор...
Сообщение отредактировал Quasar - Jul 30 2007, 11:51
|
|
|
|
|
Jul 30 2007, 11:53
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Можно сделать немного по другому, если Вы не знаете точно, какой длины массивы будут Код typedef struct { const char *pEngl; /* указатель на массив Engl */ const char pRuss; /* указатель на массив Russ */
} LangStruct PROGMEM; А далее в конструкторе (функции инициализации) указателям присваивать конкретные адреса массивов... Еще бы я добавил, в таком случае, в структуру размеры массивов. [/quote] Цитата(Quasar @ Jul 30 2007, 19:48)  Почему это ни одного? Код 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??? Зеро байт?  Или миллион?
--------------------
|
|
|
|
|
Jul 30 2007, 12:00
|

Местный
  
Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021

|
Цитата(prottoss @ Jul 30 2007, 15:53)  Можно сделать немного по другому, если Вы не знаете точно, какой длины массивы будут Код typedef struct { const char *pEngl; /* указатель на массив Engl */ const char pRuss; /* указатель на массив Russ */
} LangStruct PROGMEM; А далее в конструкторе (функции инициализации) указателям присваивать конкретные адреса массивов... Еще бы я добавил, в таком случае, в структуру размеры массивов. Ну да, видимо так и сделаю. Цитата Интересно, а какой размер массива Text??? Зеро байт?  Или миллион? А ни какой, это примерно аналогично extern char Mass[], то есть происходит определение, а память выделяется при создании экземпляра.
|
|
|
|
|
Jul 30 2007, 12:06
|

Местный
  
Группа: Свой
Сообщений: 226
Регистрация: 2-06-06
Пользователь №: 17 720

|
В определении типа не нужно указывать атрибутов (PROGMEM), они указываются при обьявлении переменных этого типа : Код typedef struct { const char Engl[size1]; const char Russ[size2]; } LangStruct;
LangStruct PROGMEM str1; LangStruct EEPROM str2; в данном случае str1 будет размещена в программной памяти, str2 - в eeprom. size1, size2 должны быть определены перед обьявлением типа...
Сообщение отредактировал umup - Jul 30 2007, 12:09
|
|
|
|
|
Jul 30 2007, 12:19
|

Местный
  
Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021

|
Цитата ИМХО это очччень не хорошо, если это на самом деле работает. Ни когда не известно, какого размера структура Ну почему не известно, длинна всех типов в структуре, плюс длинна массива, полученная при инициализации, так получается. Кстати именно поэтому видимо и требование такое, что бы массив был в конце структуры, вот два и не получится разместить  . Код В определении типа не нужно указывать атрибутов (PROGMEM), они указываются при обьявлении переменных этого типа : Ну почему же не нужно, смотря для чего, в данном случае надо что бы всё было во флеш, зачем же тогда по сто раз PROGMEM писать.
Сообщение отредактировал Quasar - Jul 30 2007, 12:20
|
|
|
|
|
Jul 30 2007, 12:51
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(Quasar @ Jul 30 2007, 20:19)  Ну почему не известно, длинна всех типов в структуре, плюс длинна массива, полученная при инициализации, так получается. Кстати именно поэтому видимо и требование такое, что бы массив был в конце структуры, вот два и не получится разместить  . Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но как, допустим, определить массив Ваших структур??? И как, допустим, в цикле их перебирать если все структуры разной длины??? Кстати, можете показать код инициализации члена Text[] структуры Menu_Item? Что то у меня не получилось
--------------------
|
|
|
|
|
Jul 30 2007, 13:03
|

Местный
  
Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021

|
Цитата(prottoss @ Jul 30 2007, 16:51)  И как, допустим, в цикле их перебирать если все структуры разной длины??? Да, с перебором в цикле - проблема  . Но как Вы могли догадаться, в массиве 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
|
|
|
|
|
Jul 30 2007, 14:21
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(prottoss @ Jul 30 2007, 14:51)  Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но Обычно в таких случаях либо концевой массив содержит нечто "самоограниченное" (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 CODE .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); Но проблемой этих выкрутасов было в том числе то, что компилятор не запрещал создать массив таких структур. А теперь может выдать ошибку.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 30 2007, 18:53
|

Местный
  
Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021

|
Цитата(zltigo @ Jul 30 2007, 21:04)  И не может работать в принципе. Все правильно. В смысле не может, всё работает, если использовать только один массив (ну во всяком случае в gcc), вот с двумя уже нет. А что значит, наложение на уже существующую память?
|
|
|
|
|
Jul 30 2007, 19:01
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(prottoss @ Jul 30 2007, 15:51)  Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но как, допустим, определить массив Ваших структур??? И как, допустим, в цикле их перебирать если все структуры разной длины??? Кстати, можете показать код инициализации члена Text[] структуры Menu_Item? Что то у меня не получилось  А я так работаю. И ни единого глюка нет, хотя код сейчас 56к. У меня правда определён один массив в конце структуры. Работаю я через кучу и указатели. То есть при создании экземпляра создаётся указатель на структуру. При вызове используется данный указатель. Использую и массивы структур и сортировку. Никаких проблем. Структуры имеют разные поля и разные массивы. Создаются и удаляются. Единственное, что я упростил диспетчер кучи. Поленился. Надо будет попробовать последовать совету zltigo и написать свой. Что особенно хочется отметить, это отличную работу отладчика (пользую IAR_C-AVR_Studio) со всем этим барахлом. Я думал будет намного хуже. Не смотри что указатели. Полный доступ к полям.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|