Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос скорее по Си
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
_Артём_
В программе объявлен такой тип данных
Код
#define MAX_DATA_SIZE 128
struct TStructure {
    unsigned char DataSize;// размер данных
    unsigned char Data[MAX_DATA_SIZE];
};


Соответственно есть переменные такого типа:
Код
struct TStructure st1={
    3,
    {1,2,3}
};
struct TStructure st1={
    1,
    {1}
};


Структуры должны хранится в программной памяти и загружаться в ОЗУ соответственно ситуации.
Проблема в том, что Data может быть разной длины (от 1 до 128), то есть программная память зря расходуется.
Как определить структуру, чтобы поле Data имела размер не больше чем требуется?
rezident
ИМХО, забейте на эту структуру! wink.gif Объявите одномерный массив
Код
unsigned char Data[MAX_DATA_SIZE+1];

И интерпретируйте его первый элемент (Data[0]) как валидный размер текущего массива. Соответственно ваши данные располагайте, начиная со второго элемента массива (Data[1]).
P.S. я понимаю, когда в структуру объединяют разнотипные данные, но зачем для однотипных структуру-то создавать? Если только для того чтобы "красиво" в тексте исходника выглядело, дык дефайны для этого имеются, типа
Код
#define DataSize Data[0]
_Артём_
Цитата(rezident @ Jun 1 2007, 18:28) *
P.S. я понимаю, когда в структуру объединяют разнотипные данные, но зачем для однотипных структуру-то создавать? Если только для того чтобы "красиво" в тексте исходника выглядело, дык дефайны для этого имеются, типа
Код
#define DataSize Data[0]

Данные разнотипные (пример неудачный).
В Паскале я бы написал так:
Код
type Tstructure=record
    A: Byte;
    B: array of TDateTime;// TDateTime для примера
end;


На Си что-то не придумывается (хотя преложенный вариант в принципе подходит).
_artem_
первый элемент структуры (для всех структур) можно записать как тип и использовать его как предложил Резидент. Так и овцы цели и волки сыты )

Наверно Страуструп с этого и начинал)
defunct
Как вариант - использовать "open array" и динамическое выделение памяти:

Код
typedef struct tagMY_STRUCT
{
    U8 size;
    U8 payload[1];
} TMY_STRUCT, *PMY_STRUCT;


{
   PMY_STRUCT pStruct;

   pStruct = (PMY_STRUCT)malloc(...); // столько памяти сколько надо..
   pStruct->size = ...;
..
}
sensor_ua
IMHO, лучше массивы не пытаться укладывать в структуры, ибо их размер должен быть определен. Лучше уж примерно так:

typedef struct TStructure {
unsigned char DataSize;// размер данных
unsigned char * pData; //указатель на начало массива
}TStructure;


unsigned char Data[]={1,2,3,4};
unsigned char Data1[]={1,2,3,4,5,6,7};


TStructure mystr = {sizeof(Data), &Data[0])};
TStructure mystr1 = {sizeof(Data1), &Data1[0])};
rezident
Цитата(_Артём_ @ Jun 1 2007, 21:44) *
Данные разнотипные (пример неудачный).

Вы сами такой пример написали wink.gif Откуда я могу предполагать что у вас на уме использовать другой тип данных для хранения размера буфера?
Цитата(_Артём_ @ Jun 1 2007, 21:44) *
На Си что-то не придумывается (хотя преложенный вариант в принципе подходит).

Для вас ведь важно выделить массив памяти, требуемого размера. А как вы там будете интерпертировать данные в нем это дело десятое - компилятор Си не особо вас здесь ограничивает. В этой части у него явное преимущество перед Паскалем. Правда и напортачить в данных при этом он вам позволит на порядок больше, нежли Паскаль. smile.gif
_Артём_
Цитата(rezident @ Jun 1 2007, 19:30) *
Вы сами такой пример написали wink.gif Откуда я могу предполагать что у вас на уме использовать другой тип данных для хранения размера буфера?

Для вас ведь важно выделить массив памяти, требуемого размера. А как вы там будете интерпертировать данные в нем это дело десятое - компилятор Си не особо вас здесь ограничивает. В этой части у него явное преимущество перед Паскалем. Правда и напортачить в данных при этом он вам позволит на порядок больше, нежли Паскаль. smile.gif


Пожалуй остановлюсь на массиве.
defunct
Цитата(sensor_ua @ Jun 1 2007, 19:23) *
IMHO, лучше массивы не пытаться укладывать в структуры, ибо их размер должен быть определен.
Не обязательно. Для IP стека как раз наоборот очень удобно использовать структуры с open array.
zltigo
Цитата(rezident @ Jun 1 2007, 18:28) *
ИМХО, забейте на эту структуру! wink.gif

Совершенно неразумный совет.
Цитата
И интерпретируйте его первый элемент (Data[0]) как валидный размер текущего массива.

Ну зачем, о Господи! Если совершенно естественно именуется поле структуры а уж его "интерпретацией" должен заниматься компилятор. Зачем забивать себе и другим лишними знаниями, соглашениями и потенциальными ошибками.

Цитата(_Артём_ @ Jun 1 2007, 19:49) *
Пожалуй остановлюсь на массиве.

И, простите, как, это поможет проблеме???
Внимательно читайте пост defunct - Ваш вариант это динамическое выделение памяти.
SasaVitebsk
Наверное присоединюсь к defunct и zltigo. И структура здесь не мешает. Хотя я бы всёже в структуру вводил ссылку на массив и его длину. Со строками пример приведу, а массив ничем по сути не отличается.

Код
struct AddrKom_e
{
uint8_t            Name;                    // Имя команды
uint16_t             TimeStart;                // Время начала исполнения команды
uint8_t             TimeRealH;                 // Время реальное часы
uint8_t             TimeRealM;                 // Время реальное минуты
} *Kom_e;

struct AddrKomT
{
uint8_t            Name;                    // Имя команды
uint16_t             TimeStart;                // Время начала исполнения команды
uint8_t             TimeMashtabTek,            // Текущее значение масштаба для времени исполнения
                    TimeMashtab;            // Масштаб для времени исполнения
uint16_t            TimeLife;                // Время исполнения команды с учётом масштаба
int16_t             BegX,BegY;                // Начало объекта (X,Y)
int8_t                VecX,VecY;                // вектор перемещения объекта (X,Y)
uint8_t            text[10];                // Текст сообщения
} *KomT;

struct AddrKomR
{
uint8_t            Name;                    // Имя команды
uint16_t             TimeStart;                // Время начала исполнения команды
uint8_t            TimeMashtab;            // Изменение масштаба для времени исполнения
uint16_t            TimeLife;                // Изменение времени исполнения команды с учётом масштаба
int16_t             BegX,BegY,                // Изменение начала объекта (X,Y)
                    SizeX,SizeY;            // Изменение размеров объекта (X,Y)
int8_t                VecX,VecY;                // Изменение вектора перемещения объекта (X,Y)
uint8_t            NAktive;                // Номер изменяемого объекта
} *KomR;

.....


А применяю так

Код
  KomXx    = (struct AddrKomXx*) AdrActiveKom[i];            // Прочитать адрес текущей активной    команды
  if(KomXx->TimeStart>Status.TekTime) continue;            // Если    не подошло время для исполнения    команды, то    пропустить данную команду
  switch (KomXx->Name) {
  /* Команда "END" - "Ролик    завершить" */
  case 'E':
......
  case 'e':
             Kom_e = (struct AddrKom_e*) AdrActiveKom[i];//    Прочитать адрес    текущей    активной    команды
             if((Kom_e->TimeRealH>Status.Hour)&&(Kom_e->TimeRealM>Status.Minute)){
.....
Сергей Борщ
Цитата(defunct @ Jun 1 2007, 18:48) *
Как вариант - использовать "open array" и динамическое выделение памяти:
Вот только с выделением облом - автор хотел эти структуры во флеше хранить. Т.е. если использовать "incomplete arrays" (в терминологии стандарта), то должно получиться:
Код
typedef struct
{
   uint8_t size;
   uint8_t data[]
} my_struct_type;
my_struct_type const __flash Struct =
{
   2,
  { 1, 2}
};
Только надо помнить четыре вещи:
1)такой массив может располагаться только в конце структуры
2)sizeof() будет выдавать размер такой структуры без учета массива, т.е. в данном случае 1 и сделать массив из таких структур уже не получится, а также арифметика указателей на этих структурах будет работать некорректно.
3) не все компиляторы поддерживают incomplete arrays (ИАР поддерживает)
4) В С++ такое уже не прокатит.
rezident
Цитата(zltigo @ Jun 1 2007, 23:17) *
Совершенно неразумный совет.

Вы как всегда категоричны smile.gif Чем же он неразумен в применении к структуре однотипных переменных? Структура это всего лишь абстракция, предназначенная для удобства человека. Чтобы человек-программист мог на привычном для него объектном уровне изложить компилятору свою точку зрения на вид, размерность и порядок расположения переменных. Данные в памяти будут все равно в виде байтов, 16-ти или 32-разрядных слов располагаться, в соответствии со способом организации типа памяти конкретного МК.
Цитата(zltigo @ Jun 1 2007, 23:17) *
Ну зачем, о Господи! Если совершенно естественно именуется поле структуры а уж его "интерпретацией" должен заниматься компилятор.

Собственно я об этом же, только без обращения к Творцу smile.gif Только зачем она в приведенном автором топика примере?
Цитата(zltigo @ Jun 1 2007, 23:17) *
Зачем забивать себе и другим лишними знаниями, соглашениями и потенциальными ошибками.

Тогда нужно на Паскале писать, а не на Си. Делов-то!
Цитата(zltigo @ Jun 1 2007, 23:17) *
Внимательно читайте пост defunct - Ваш вариант это динамическое выделение памяти.

Читайте пост Сергея Борщ о том, какие проблемы бывают с незавершенными массивами.
zltigo
Цитата(rezident @ Jun 1 2007, 21:43) *
Структура это всего лишь абстракция, предназначенная для удобства человека.

Да! И зачем советовать делать не удобно???
defunct
Цитата(rezident @ Jun 1 2007, 21:43) *
Читайте пост Сергея Борщ о том, какие проблемы бывают с незавершенными массивами.

Вам бы тоже не помешало прочитать его пост и сравнить два термина "open array" и "incomplete array".
Проблемы перечисленные Сергеем не распространяются на open array, кроме одной -
Цитата
1)такой массив может располагаться только в конце структуры


Ну а то что нельзя разместить во флеш - да.. Но в контексте AVR - флеша ведь в разы больше чем RAM'а, для чего могла потребоваться такая экономия?!

Цитата(Сергей Борщ @ Jun 1 2007, 21:20) *
Вот только с выделением облом - автор хотел эти структуры во флеше хранить.


Во флеш можно хранить в удобном и нормальном для этого виде, также как у автора ветки - структуры фиксированной длинны. Экономия на мой взгляд может потребоваться во второй части задачи -
"загружаться в ОЗУ соответственно ситуации."
Вот тут как раз сэкономить поможет способ с дин. выделением памяти.
singlskv
Цитата(_Артём_ @ Jun 1 2007, 19:17) *
Структуры должны хранится в программной памяти и загружаться в ОЗУ соответственно ситуации.
Проблема в том, что Data может быть разной длины (от 1 до 128), то есть программная память зря расходуется.

Может быть я конечно не все понял, но в чем вобще проблема ?
Копирование из флеш в рам в вашей ситуации все равно придется делать "ручками"
Ну дык и кто мешает просто забить в памяти кусок максимального объема типа
Код
#define MAX_DATA_SIZE 128
struct {
    unsigned char DataSize;// размер данных
    unsigned char Data[MAX_DATA_SIZE];
} currStruct;

и по необходимости переносить в нее из флеш.
Ну или просто, если уж у Вас структуры хранятся в флеш то это наверное константы ?
тогда просто организуйте доступ к ним без копирования в память
_Артём_
Цитата(singlskv @ Jun 2 2007, 01:15) *
Может быть я конечно не все понял, но в чем вобще проблема ?
Копирование из флеш в рам в вашей ситуации все равно придется делать "ручками"
Ну дык и кто мешает просто забить в памяти кусок максимального объема типа
Код
#define MAX_DATA_SIZE 128
struct {
    unsigned char DataSize;// размер данных
    unsigned char Data[MAX_DATA_SIZE];
} currStruct;

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


Проблема в том, что программной памяти жалко (и так не хватает), это обстоятельство и не позволяет "просто забить в памяти кусок максимального объема типа".
Сергей Борщ
Цитата(defunct @ Jun 2 2007, 00:24) *
сравнить два термина "open array" и "incomplete array".
Стоп. Термин "incomplete array" приведен в стандарте С. Термина open array там нет, поэтому я решил что rezident ошибся в термине и поправил его, чтобы интересующийся ответом мог дальше искать информацию по правильным ключевым словам. Ваша фраза наталкивает на мысль, что open array это совершенно иная (хоть и похожая) конструкция. Но ладно стандарт, даже гугля на первых двух страницах не дает ни одной тематической ссылки на запрос "c open array" (дальше не искал). Поэтому объясните, что же такое "open array". Судя по вашей реплике, они есть в С++, с ними дружит sizeof и из них можно делать массивы?

Цитата(defunct @ Jun 2 2007, 00:24) *
Ну а то что нельзя разместить во флеш - да.. Но в контексте AVR - флеша ведь в разы больше чем RAM'а, для чего могла потребоваться такая экономия?!
Как раз для размещения во флеш в этой задаче incomplete arrays подходят как нельзя лучше. А вот при работе в ОЗУ - да, динамическое выделение памяти выглядит красиво, но не в каждой задаче имеет смысл его использовать. Тогда можно по ситуации - или дин. память или присваивать указателю на такую структуру адрес заранее выделенного буфера и дальше работать с буфером как со структурой этого типа.
defunct
Цитата(Сергей Борщ @ Jun 2 2007, 11:43) *
Стоп. Термин "incomplete array" приведен в стандарте С. Термина open array там нет, поэтому я решил что rezident ошибся в термине и поправил его

Вы поправляли меня.
Под open array, я привел конструкцию:
char A[1];
а не
char A[]
т.е. это обычный массив объявленный с количеством элементов = 1.
Но ничто не мешает нам обращаться к элементам A[1], A[2] и т.д., необходимо лишь быть уверенным, что обращаясь к этим элементам мы не затрем ничего лишнего. При дин. выделении памяти - мы определяем границу массива количеством выделенной под него памяти.

Цитата
, чтобы интересующийся ответом мог дальше искать информацию по правильным ключевым словам.

По ключевому слову incomplete он бы нашел не то, что я имел в виду.

Цитата
Поэтому объясните, что же такое "open array". Судя по вашей реплике, они есть в С++, с ними дружит sizeof и из них можно делать массивы?

Отличие выше, с sizeof он конечно же тоже не дружит, т.к. будет возвращена длина 1. Но sizeof не был перечислен в Вашем списке проблем, либо я невнимательно смотрел. В C++ нично не препятствует использованию таких конструкций.

Цитата
Как раз для размещения во флеш в этой задаче incomplete arrays подходят как нельзя лучше.

Согласен.
sensor_ua
Цитата
присваивать указателю на такую структуру адрес заранее выделенного буфера и дальше работать с буфером как со структурой этого типа

А что, преобразование типа через void * не годится или имеется в виду то же? Если массивы есть, то кто им мешает располагаться во FLASH? Вроде этого и хотели. Добавить модификаторы const __flash ко всем элементам (кроме typedef), т.е. к массивам и структурам,
в вариант http://electronix.ru/forum/index.php?showt...32479&st=0# и свободно пользоваться - массивы нужной длины во FLASH, структуры для работы с ними - тоже, "лишнего" места - аж по одному указателю на 1 массив. Просто не очень понятно, зачем для const массивов создавать что-то динамическое? Если нужно копировать, то всё-равно будет нужно куда-то положить. Если не обязательно, то можно взять по указателю в любое время.
ReAl
Цитата(defunct @ Jun 2 2007, 15:40) *
Под open array, я привел конструкцию:
char A[1];
а не
char A[];
т.е. это обычный массив объявленный с количеством элементов = 1.
...
Отличие выше, с sizeof он конечно же тоже не дружит, т.к. будет возвращена длина 1. Но sizeof не был перечислен в Вашем списке проблем, либо я невнимательно смотрел.

Не вижу принципиальных отличий.
К
char A[]
с тем же успехом можно обращаться через A[1], A[2] и так далее, "необходимо лишь быть уверенным" и далее по тексту.
Точно так же не дружит с sizeof(), только для char A[1] надо
ptr = malloc( sizeof(struct header) + data_len - 1);
а для char A[] надо
ptr = malloc( sizeof(struct header) + data_len);
что несколько более логично.

Т.е. разницы с точки зрения применения - нет.

Фактически,
char A[1]; - это старый добрый программистский трюк, основанный на том, что поля структуры расположены в памяти в том же порядке, в котором записаны в структуре (кстати, в C++ это не гарантируется, если я правильно помню).
char A[]; - это стандартизованный способ.

Кстати, GNU-тое расширение позволяло писать
char A[0];
sensor_ua
Если нужно, то указателем вполне пожно пользоваться практически как read-only массивом
const char array[]="Preved!";
const char * ptr = &array[0];//это тот указатель, который предлагалось положить в структуру

...
char ptmp = ptr;
char x;
...
x = ptmp[5] ; //x = *(ptmp+5); или x = 'd';

Спрашивается, зачем массив, если размер нельзя узнать? Разве указателя недостаточно?
defunct
Цитата(ReAl @ Jun 2 2007, 16:52) *
Т.е. разницы с точки зрения применения - нет.

В контексте вопроса этой ветки разница есть, и очень существенная.
Так как
struct
{
char A[];
}

просто не воспримится многими компиляторами.
SasaVitebsk
Честно говоря я уже в рассуждениях несколько потерял вопрос-первопричину. Пускай автор всётаки уточнит поподробнее что он хочет сделать и для чего. В этом случае будут грамотнее и конкретнее ответы.

Я поступал подобным образом именно для ОЗУ и динамического распределения. А для определения начала структуры создавал специальный указатель. На удивление получилось наглядно и красиво(для меня) и очень удобно при отладке(всё поддержено отладчиком).

Для размещения во флэш я просто использовал сами массивы и массив ссылок (к примеру). Также можно разместить ссылку и в структуре. Зачем создавать открытый массив во флэш мне несколько не понятно, в том случае если всё равно массив создаётся на этапе компиляции. Если же он создаётся на этапе исполнения, тогда всё правильно, но достаточно сложно работать будет.

Я это к чему? Возможно Вам предложат совершенно иной подход.
rezident
Цитата(Сергей Борщ @ Jun 2 2007, 00:20) *
3) не все компиляторы поддерживают incomplete arrays (ИАР поддерживает)

Кстати, Сергей, откуда ты взял, что ИАР поддерживает? Помнится у меня была подобная проблема, когда в зависимости от конкретной прикладной задачи прибора, нужно было хранить в сегменте INFO MSP430 наряду с определенным количеством констант еще произвольное описание масок для данных. Так вот предлагаемый тобой способ с incompete array не прокатил. Хотя я располагал массив как и положено в конце структуры констант. Пришлось определять его отдельно как константный байтовый массив с одновременной инициализацией его. А в самой программе писать свою функцию, разбирающую этот массив на данные нужной размерности.
Код
//описание масок для обработки буфера данных, сетевых и локальных
// кол-во байт описания - смещение для переменной в буфере - маска1[, маска2, маска3, ...]; 0 - завершение описания
#pragma pack(1)
#pragma location=(0x1000+sizeof(InfoSeg))
const unsigned char MaskLedOut[]=
  { 0,                                            //описание для LED1
    0,                                            //описание для LED2
    0,                                            //описание для LED3
    0,                                            //описание для LED4
    1, MAIN_LOC_BUF_OFF, 0x10, 0,                 //описание для LED5
    1, MAIN_LOC_BUF_OFF, 0x20, 0,                 //описание для LED6
    1, MAIN_LOC_BUF_OFF, 0x40, 0,                 //описание для LED7
    1, MAIN_LOC_BUF_OFF, 0x80, 0,                 //описание для LED8
    1, MAIN_LOC_BUF_OFF+1, 0x01, 0,               //описание для LED9
    1, MAIN_LOC_BUF_OFF+1, 0x02, 0,               //описание для LED10
    1, MAIN_LOC_BUF_OFF+1, 0x04, 0,               //описание для LED11
    1, MAIN_LOC_BUF_OFF+1, 0x08, 0,               //описание для LED12
    0,                                            //описание для LED13
    1, MAIN_NET_BUF_OFF(5)+3, 0x80, 0,            //описание для LED14
    4, MAIN_NET_BUF_OFF(5),   0x5E, 0x60, 0x00, 0x03, 0,//описание для LED15
    1, MAIN_NET_BUF_OFF(6),   0x06, 0             //описание для LED16
  };
#pragma pack()

Ах да! Пользовался я ИАР ЕВ430 3.30А.
defunct
Цитата(ReAl @ Jun 2 2007, 16:52) *
(кстати, в C++ это не гарантируется, если я правильно помню).

в случае структур - гарантируется с атрибутом __packed
zltigo
Цитата(rezident @ Jun 2 2007, 21:24) *
Кстати, Сергей, откуда ты взял, что ИАР поддерживает?

Поддерживает. Практически используется, ну и родной документ по IAR EW430:
Код
Incomplete arrays at end of structs
The last element of a struct may be an incomplete array. This is useful because one
chunk of memory can be allocated for the struct itself and for the array, regardless of
the size of the array.

Цитата
Так вот предлагаемый тобой способ с incompete array не прокатил

Невероятно, разве только если не пытались совсем грубо:
Код
The array may not be the only member of the struct. If that was the case, then
the size of the struct would be zero, which is not allowed in ISO/ANSI C.
rezident
Цитата(zltigo @ Jun 3 2007, 01:00) *
The array may not be the only member of the struct. If that was the case, then
the size of the struct would be zero, which is not allowed in ISO/ANSI C.

Эта цитата означает что структура не может состоять только из одного incomplete array, я правильно понял? Нет, у меня была структура из разных переменных в конце которой я пытался вставить этот incomplete array. Не получилось. ИАР выдавал ошибку.
Кстати, могла ли быть эта ошибка вызвана тем, что объявлял я структуру с одновременной инициализацией ее в одном модуле, а использовал еще и в двух других. Естественно, что в других модулях был описан ее прототип с квалификатором extern.
zltigo
Цитата
Эта цитата означает что...

Да.
Цитата(rezident @ Jun 2 2007, 22:16) *
Не получилось. ИАР выдавал ошибку.

Подтверждаю, что использую без всяких проблем.
Сергей Борщ
Цитата(rezident @ Jun 2 2007, 21:24) *
Кстати, Сергей, откуда ты взял, что ИАР поддерживает?
Из хелпа. Да и тут вопрос задавал, когда в плюсах попробовал использовать и не прошло. Мне тут ответили, что все работает. Переключил в режим С, действительно скомпилилось. А в плюсах - никак. Долго думал. Потом понял, что сама идеология классов (и структур как частных случаев классов) из-за полиформизма такое не допускает. Меня интересовало именно в ОЗУ. Сделал через динамическое выделение байтового массива и накладывание структуры. Кстати (!) структуру описал как open array. Насчет использования incomplete array в разных файлах - тоже наталкивался, но не на ошибку а на варнинг, но сейчас не вспомню какой точно. Если есть интерес - могу попытаться воспроизвести. Если я правильно понял ваш исходник, вы пытались сделать массив из структур, содержащих incomplete array. А поскольку размер такой структуры неизвестен, то и массив из нее сделать никак.

P.S. вот читаешь всякие умные книжки, и так у них красиво все получается. Массив нужен из таких структур - пожалуйста: получите массив указателей на такие структуры. И писать можно data = Mystruct[1].data[3]. А вдумаешься - для этой "красоты" на каждую структуру лишний указатель. Выглядит красиво, но в нашей области в бОльшей части реальных задач неприменимо. Или динамическое выделение памяти - с ним задача из примера решается легко и естественно. А оно мне на меге8 с 1К ОЗУ как серпом по... И так практически с каждым примером. Снова порой ощущаю себя как когда с ассемблера на С переползал - "блин, какой тупой компилятор, здесь можно было команду сэкономить, здесь регистр, здесь такт". Может это пройдет, а может в этом есть и положительное - заставляет мозгами активнее шевелить.
zltigo
Цитата(Сергей Борщ @ Jun 2 2007, 22:52) *
Или динамическое выделение памяти - с ним задача из примера решается легко и естественно. А оно мне на меге8 с 1К ОЗУ как серпом по...

А какие проблемы? Для простейшего менеджера памяти накладные расходы можно свести к паре-тройке байтов на блок. А без освобождения памяти вообще без затрат. Под heap, естественно, отдавать все оставшееся ОЗУ а не тупо выделять заранее. Все красиво.
rezident
Цитата(Сергей Борщ)
Или динамическое выделение памяти - с ним задача из примера решается легко и естественно. А оно мне на меге8 с 1К ОЗУ как серпом по...

Гы smile.gif А я вообще это для MSP430F133 писал у которого 256 байт ОЗУ. Потом правда в связи с расширением функциональности (д.б. в 4 раза больше сетевых устройств подключено к прибору) MSP430F135 поставили с 512 байт RAM.
Сергей Борщ
Цитата(zltigo @ Jun 2 2007, 23:11) *
А какие проблемы? Для простейшего менеджера памяти накладные расходы можно свести к паре-тройке байтов на блок.
А кто тут пугал всех ужасами фрагментации в "простейших менеджерах памяти"? wink.gif
Как там было в классике? "Настоящий программист экономит 30 тактов в цикле, который выполняется один раз при запуске программы". Жаба душит заводить кучу чтобы попользоваться ей только один раз. А насчет менеджера памяти надо пообщаться - актуально. Нужны две кучи - в "набортном" быстром ОЗУ для объектов и во внешнем для данных. Насколько я разобрался в ИАРе - он умеет только одну. По вашим сообщениям я понял, что у вас есть наработки на эту тему.

P.S. Хотя, насчет кучи у меня действительно предубеждение, надо его побороть. На ARMах уже использую, но еще не "почувствовал" настолько, чтобы и в мелких контроллерах применять не задумываясь. Все время гложет вопрос - что делать, если память кончится. Оператора ведь нет, некому плакаться.
zltigo
Цитата(Сергей Борщ @ Jun 2 2007, 23:37) *
А кто тут пугал всех ужасами фрагментации в "простейших менеджерах памяти"? wink.gif

Я пугал, но в большинстве микроконтроллерных случаев от менеджера достаточно получить экономное распределение памяти в зависимости от текущей конфигурации и возможность хотя-бы последовательного выделения-освобождения-выделения-....
Цитата
А насчет менеджера памяти надо пообщаться - актуально. Нужны две кучи - в "набортном" быстром ОЗУ для объектов и во внешнем для данных.

Естественное желание.
Цитата
Насколько я разобрался в ИАРе - он умеет только одну.

Даже не разбирался smile.gif
Цитата
По вашим сообщениям я понял, что у вас есть наработки на эту тему.

Ага, менеджер слегка навороченный - вызывается инициализация c указанием подконтрольного блока памяти. Количество вызовов не ограничено smile.gif, что позволяет иметь любое количество областей. Я его использую в том числе и для создания внутри выделенного блока памяти еще одного менеджируемого набора блоков фиксированного размера для беспорядочного использования без побочных проблем с дефрагментацией.
Цитата
P.S. Хотя, насчет кучи у меня действительно предубеждение, надо его побороть

Обязательно.
Цитата
Все время гложет вопрос - что делать, если память кончится. Оператора ведь нет, некому плакаться.

Разбираться и прибивать нежизненноважные задачи.
tag
Цитата(_Артём_ @ Jun 2 2007, 01:33) *
Проблема в том, что программной памяти жалко (и так не хватает), это обстоятельство и не позволяет "просто забить в памяти кусок максимального объема типа".

...непонятно, предполагается что структура размещается в ОЗУ, а не в программной памяти и данные в нее заносятся из flash... у вас нехватка какой памяти программ или ОЗУ данных?
_Артём_
Цитата(tag @ Jun 4 2007, 11:03) *
...непонятно, предполагается что структура размещается в ОЗУ, а не в программной памяти и данные в нее заносятся из flash... у вас нехватка какой памяти программ или ОЗУ данных?


Нехватка у меня памяти программ(это к слову).
Вариант Сергея Борща почему-то в С++ глючит (то работает, то нет).
Наверное буду использовать другие варианты (скорее всего двоичный массив нужной длины).

Пожалуй, тему пора закрывать - сказано более, чем достаточно...
Всем спасибо.
zltigo
Цитата(_Артём_ @ Jun 5 2007, 00:14) *
Вариант Сергея Борща почему-то в С++ глючит (то работает, то нет).

Ой! Очем это? "Глючит" smile.gif. Поросто не компилится в принципе. Что однако не мешает его использовать, поскольку никто не обязывает весь проект на С++ писать.
Сергей Борщ
А про С++ в вопросе не было!
Цитата(_Артём_ @ Jun 5 2007, 00:14) *
Вариант Сергея Борща почему-то в С++ глючит (то работает, то нет).
Как заставить Американца прыгнуть с моста? Встретить его на мосту и убедить, что он разорен. Как заставить француза прыгнуть с моста? Встретить его на мосту и убедить, что жена ему изменяет. Как заставить русского прыгнуть с моста? Встретить его на мосту и сказать "А вы знаете, здесь прыгать с моста запрещено!"
Цитата(Сергей Борщ @ Jun 1 2007, 21:20) *
4) В С++ такое уже не прокатит.
В С++ такое не работает по простой причине: при наследовании данные производной структуры (которая в С++ есть частный случай класса) располагаются вслед за данными родителя. А если размер родителя неизвестен, компилятор не сможет иметь доступ к данным производного класса. А сказать "от этого класса наследников не будет никогда" возможности нет. Как сделать на С++ то, что вы хотите, да еще с инициализацией через {} - не знаю sad.gif Могу предложить два варианта - 1) массив структур сам по себе, структура из размера и указателя на массив. Да, лишний указатель, зато можно писать a = pArray[n].member; 2) не указывать размер, а в конце масива добавлять элемент с каким-либо признаком конца структуры (например если одно из полей - указатель, то он равен нулю.
Код
class terminal_t
{
public:
    terminal_t() {};
    static void process();
private:
    static bool read_input(char c);
public:

private:
    ................
    struct dictionary_t
    {
        char Name[10];
        void (*Action)(void);
        uint8_t StackRequired;
    } static const __flash Dictionary[];
} static Terminal;

#define    TERMINAL_DICTIONARY                      \
terminal_t::dictionary_t const __flash terminal_t::Dictionary[] =   \
{                                                                    \
    { "HEX",        ns_terminal::SetHex,     0},             \
    { "DECIMAL",    ns_terminal::DECIMAL,    0},             \
    { ".",          ns_terminal::UDOT,       1},             \
    { "@",          ns_terminal::Reference,  1},             \
    { "!",          ns_terminal::Dereference, 2},            \
    {"DUMP",        ns_terminal::DUMP,       2},             \

#define    TERMINAL_DICTIONARY_END                  \
    {0,        0 }                                    \
};


TERMINAL_DICTIONARY
    {"v",    readADC, 0},
    {"IDUMP",   RAM_DUMP, 2},
    {"RDUMP",   XROM_DUMP, 3},
    {"XDUMP",   XRAM_DUMP, 2},
    {"X!",      writeRAM, 2},
    {"X@",      readRAM, 1},
    {"RB!",     writeROM_byte, 3},
    {"R!",      writeROM, 3},
    {"R@",      readROM, 2},
    {"SN",      SN, 0},
TERMINAL_DICTIONARY_END
Да, на каждую структуру лишний элемент, но не нужно вручную перед компиляцией считать количество элементов, а значит и ошибиться невозможно. И те же самые Dictionary[n].Action();
ReAl
Цитата(Сергей Борщ @ Jun 5 2007, 10:14) *
В С++ такое не работает по простой причине: при наследовании данные производной структуры (которая в С++ есть частный случай класса) располагаются вслед за данными родителя. А если размер родителя неизвестен, компилятор не сможет иметь доступ к данным производного класса.

Более того, даже без учёта incomplete array порядок размещения полей гарантируется только если у класса нет чередования модификаторов доступа (public/protected/private), нет виртуальных функций и базовых классов.

Т.е. тут порядок в памяти будет как написано
class foo {
int i;
int j;
int k;
};

а тут уже "не гарантируется", хотя и, вероятнее всего, будет всё нормально.
struct moo {
int i;
protected:
int j;
public:
int k;
};

gcc без ключа полного соответствия стандарту (--pedantic) пропускает incomplete arrays и вроде бы всё нормально компилирует... Но при этом не ругается даже если вывести потомка.

На мой взгляд, если уж припёрло, лучше бы такое выделить в отдельный чисто-С-шный модуль и обернуть в вызовы (чтобы сами структуры наружу даже не блестели). Или таки разориться на указатели в структурах а массивы держать отдельно.
Oldring
Цитата(ReAl @ Jun 5 2007, 14:17) *
На мой взгляд, если уж припёрло, лучше бы такое выделить в отдельный чисто-С-шный модуль и обернуть в вызовы (чтобы сами структуры наружу даже не блестели). Или таки разориться на указатели в структурах а массивы держать отдельно.


Если уж совершенно приперло с памятью - хранить все в одномерном байтовом массиве, и разориться на написание программы - упаковщика, порождающего сишный исходник с этим байтовым массивом. При наличии особого упорства и энтузиазма такой упаковщик можно породить даже на системе сишных макросов.
rezident
Цитата(Oldring @ Jun 5 2007, 17:06) *
Если уж совершенно приперло с памятью - хранить все в одномерном байтовом массиве, и разориться на написание программы - упаковщика, порождающего сишный исходник с этим байтовым массивом.

Я это предлагал в самом начале, но меня обругали за такое предложение sad.gif
Oldring
Цитата(rezident @ Jun 5 2007, 15:09) *
Я это предлагал в самом начале, но меня обругали за такое предложение sad.gif


Не переживайте - собеседники просто знают толк в извращениях biggrin.gif
_Артём_
Цитата(zltigo @ Jun 5 2007, 00:27) *
Ой! Очем это? "Глючит" smile.gif. Поросто не компилится в принципе. Что однако не мешает его использовать, поскольку никто не обязывает весь проект на С++ писать.


Привожу код:
Код
struct my_struct_type
{
    unsigned long TL;
    unsigned short Tmp;
    unsigned char size;
    unsigned char data[5];
};

my_struct_type const __flash Struct =
{
    100,
    10,
    3,
    { 1, 2, 5, 7}
};

struct TTT {
    volatile unsigned char A;
    void SomeFunc(unsigned char b);
};

struct TTT TT;

void TTT::SomeFunc(unsigned char b)
{
    A+=b;
}

typedef const __flash my_struct_type *my_struct_type_p;
void TestStruct(unsigned char *ptr)
{
    FlashPointer ff;
    my_struct_type_p pp;

    //ff=&Struct.data[0];
    //unsigned char i, k=Struct.size+Struct.Tmp;
    unsigned long i, k=Struct.size+Struct.Tmp+Struct.TL;
    unsigned char b;
    
    //pp=&Struct;
    
    for (i=0; i<k; i++)  {
        b=*ptr;
        TT.SomeFunc(b);
        *ptr++=*ff++;
    }
}


Использую IAR3.10С.
zltigo
Цитата(_Артём_ @ Jun 5 2007, 23:20) *
Привожу код:
Код
struct my_struct_type
{
    unsigned long TL;
    unsigned short Tmp;
    unsigned char size;
    unsigned char data[5];
};

Ну и причем здесь Ваши слова:
Цитата
Вариант Сергея Борща почему-то в С++ глючит (то работает, то нет).

Когда у Сергея речь шла о:
Код
struct my_struct_type
{
    unsigned long TL;
    unsigned short Tmp;
    unsigned char size;
    unsigned char data[];
};
_Артём_
Цитата(zltigo @ Jun 5 2007, 23:30) *
Ну и причем здесь Ваши слова:

Когда у Сергея речь шла о:
Код
struct my_struct_type
{
    unsigned long TL;
    unsigned short Tmp;
    unsigned char size;
    unsigned char data[];
};


Беру свои слова обратно...
Видно под вечер глаз замылился.. слона не заметил.

В ходе экспериментов наверное заменил data[] на data[5] и забыл.
Сейчас вижу: Вы правы - такой вариант компилятором не компилируется.
Спасибо что поправили.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.