реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> WinAVR(Ну или C) + Массивы в структуре, Массивы в структуре.
Quasar
сообщение Jul 30 2007, 11:33
Сообщение #1


Местный
***

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



При таком определении компилятор ругается:
Код
typedef struct {  
    const char  Engl[];
    const char  Russ[];
} LangStruct PROGMEM;


Мол переменной длинны, массив не в конце.

Собственно вопрос, а возможно ли вообще в С размещать таким образом два массива?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jul 30 2007, 11:43
Сообщение #2


Гуру
******

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



Цитата(Quasar @ Jul 30 2007, 19:33) *
При таком определении компилятор ругается:
Код
typedef struct {  
    const char  Engl[];
    const char  Russ[];
} LangStruct PROGMEM;


Мол переменной длинны, массив не в конце.

Собственно вопрос, а возможно ли вообще в С размещать таким образом два массива?
Нет конечно! Ни один, ни два и не десять массивов (в структуре или нет) так определять нельзя. И компилятор ругается справедливо, ибо размеры массивов не заданы, соответственно, компилятор не знает, сколько памяти надо для размещения переменной такого типа.


--------------------
Go to the top of the page
 
+Quote Post
Quasar
сообщение Jul 30 2007, 11:48
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jul 30 2007, 11:53
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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??? Зеро байт? smile.gif Или миллион?


--------------------
Go to the top of the page
 
+Quote Post
Quasar
сообщение Jul 30 2007, 12:00
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 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??? Зеро байт? smile.gif Или миллион?


А ни какой, это примерно аналогично extern char Mass[], то есть происходит определение, а память выделяется при создании экземпляра.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jul 30 2007, 12:04
Сообщение #6


Гуру
******

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



Цитата(Quasar @ Jul 30 2007, 20:00) *
А ни какой, это примерно аналогично extern char Mass[], то есть происходит определение, а память выделяется при создании экземпляра.
ИМХО это очччень не хорошо, если это на самом деле работает. Ни когда не известно, какого размера структура 07.gif


--------------------
Go to the top of the page
 
+Quote Post
umup
сообщение Jul 30 2007, 12:06
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Quasar
сообщение Jul 30 2007, 12:19
Сообщение #8


Местный
***

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



Цитата
ИМХО это очччень не хорошо, если это на самом деле работает. Ни когда не известно, какого размера структура


Ну почему не известно, длинна всех типов в структуре, плюс длинна массива, полученная при инициализации, так получается. Кстати именно поэтому видимо и требование такое, что бы массив был в конце структуры, вот два и не получится разместить crying.gif .

Код
В определении типа не нужно указывать атрибутов (PROGMEM), они указываются при обьявлении переменных этого типа :


Ну почему же не нужно, смотря для чего, в данном случае надо что бы всё было во флеш, зачем же тогда по сто раз PROGMEM писать. smile.gif

Сообщение отредактировал Quasar - Jul 30 2007, 12:20
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jul 30 2007, 12:51
Сообщение #9


Гуру
******

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



Цитата(Quasar @ Jul 30 2007, 20:19) *
Ну почему не известно, длинна всех типов в структуре, плюс длинна массива, полученная при инициализации, так получается. Кстати именно поэтому видимо и требование такое, что бы массив был в конце структуры, вот два и не получится разместить crying.gif .
Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но как, допустим, определить массив Ваших структур??? И как, допустим, в цикле их перебирать если все структуры разной длины???

Кстати, можете показать код инициализации члена Text[] структуры Menu_Item? Что то у меня не получилось smile.gif


--------------------
Go to the top of the page
 
+Quote Post
Quasar
сообщение Jul 30 2007, 13:03
Сообщение #10


Местный
***

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



Цитата(prottoss @ Jul 30 2007, 16:51) *
И как, допустим, в цикле их перебирать если все структуры разной длины???


Да, с перебором в цикле - проблема smile.gif . Но как Вы могли догадаться, в массиве Text[] храниться текст smile.gif , и вообщем-то данный приём только для текста-то и полезен, ибо в цикле чаще всего стоит условие 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
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 30 2007, 14:21
Сообщение #11


Нечётный пользователь.
******

Группа: Свой
Сообщений: 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? Что то у меня не получилось smile.gif

Без проблем.
Код
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);



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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jul 30 2007, 14:24
Сообщение #12


Гуру
******

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



Цитата(ReAl @ Jul 30 2007, 22:20) *
[code]typedef struct {
int i;
char c[];
} s;

s s1 = { 1, "abc" };
s s2 = { 1, "qwerty" };
В IAR (по крайней мере в версии 4.10, что у меня) это не работает.



И ИМХО - это правильно (что не работает smile.gif ).


--------------------
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 30 2007, 17:04
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(prottoss @ Jul 30 2007, 17:24) *
И ИМХО - это правильно (что не работает smile.gif ).

И не может работать в принципе. Все правильно.
Такие структуры используются для наложения на уже сущестующую память.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Quasar
сообщение Jul 30 2007, 18:53
Сообщение #14


Местный
***

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



Цитата(zltigo @ Jul 30 2007, 21:04) *
И не может работать в принципе. Все правильно.


В смысле не может, всё работает, если использовать только один массив (ну во всяком случае в gcc), вот с двумя уже нет.

А что значит, наложение на уже существующую память?
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jul 30 2007, 19:01
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(prottoss @ Jul 30 2007, 15:51) *
Хм... Я, конечно, не знаю, как Вы там в программе работаете с этими структурами, но как, допустим, определить массив Ваших структур??? И как, допустим, в цикле их перебирать если все структуры разной длины???

Кстати, можете показать код инициализации члена Text[] структуры Menu_Item? Что то у меня не получилось smile.gif


А я так работаю. И ни единого глюка нет, хотя код сейчас 56к. У меня правда определён один массив в конце структуры. Работаю я через кучу и указатели. То есть при создании экземпляра создаётся указатель на структуру. При вызове используется данный указатель. Использую и массивы структур и сортировку. Никаких проблем. Структуры имеют разные поля и разные массивы. Создаются и удаляются.

Единственное, что я упростил диспетчер кучи. Поленился. Надо будет попробовать последовать совету zltigo и написать свой.

Что особенно хочется отметить, это отличную работу отладчика (пользую IAR_C-AVR_Studio) со всем этим барахлом. Я думал будет намного хуже. Не смотри что указатели. Полный доступ к полям.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 15:22
Рейтинг@Mail.ru


Страница сгенерированна за 0.0149 секунд с 7
ELECTRONIX ©2004-2016