Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Нехватает памяти под массив
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Xenom0rph
На МК, ATtiny 2313 есть массив:
char *mas[15] = {"000000","000001","000010" ... "111111"}

Так вот массив вылезает за пределы допустимой памяти.
Дальше идёт сравнение строки. Котрую получила функция.
Впринципе я подумал а почему бы, не сделать так: если допустим первая строка массива равна входной строке, мы выходим из функции, если нет заменяем 1 элемент массива другой строкой, и так далее, памяти в разы будет меньше расходоваться!
Только вот у меня постаянная несовместимость типов.
Т.е я делаю так:
mass[i] = "111000";
и получаю ошибку типа нада бы использовать flash unsigned char, а если этот тип использовать, то функция strcmp не работает.
Вот два дня бьюсь, ничего невыходит.
Думал может в eeprom определить этот массив, определяю, strcmp не работает.
Может кто подскажет что нить?

P.S. использую Code VisionAVR;
MrYuran
Для начала, char - это 1 байт.
Как туда можно затолкать mass[i] = "111000"; - может, объясните?
char *mas[15] = {"000000","000001","000010" ... "111111"} - вообще бред
ReAl
Цитата(MrYuran @ Oct 6 2008, 14:50) *
Для начала, char - это 1 байт.
Как туда можно затолкать mass[i] = "111000"; - может, объясните?
char *mas[15] = {"000000","000001","000010" ... "111111"} - вообще бред
Ну ведь даже в Вашем сообщении не
Код
char mas[]

а
Код
char *mas[]

так что с этой точки зрения всё нормально, в массив ложатся указатели на строки, а сами строки лежат отдельно.
Проблема только в том, что и строки, и массив указателей на них лежат в ОЗУ (копируются из флеша в ОЗУ на старте программы), поэтому и не влазят.
VladimirYU
Цитата(MrYuran @ Oct 6 2008, 15:50) *
Для начала, char - это 1 байт.
Как туда можно затолкать mass[i] = "111000"; - может, объясните?
char *mas[15] = {"000000","000001","000010" ... "111111"} - вообще бред

Это не бред, а просто массив указателей. Но задача все равно не понятна. А первая строчка sad.gif
Xenom0rph
Может как то подругому реалтзовать,
суть в функцию приходит сточка типа "xxxxxx", где x либо 1 либо 0, мы эту строчку сравниваем с имеющимися строками и если есть совпадения, то в переменную записываем порядковый номер?

Цитата(ReAl @ Oct 6 2008, 16:15) *
Проблема только в том, что и строки, и массив указателей на них лежат в ОЗУ (копируются из флеша в ОЗУ на старте программы), поэтому и не влазят.

Ну а можно это как нить решить?
VladimirYU
Цитата(Xenom0rph @ Oct 6 2008, 15:41) *
На МК, ATtiny 2313 есть массив:
char *mas[15] = {"000000","000001","000010" ... "111111"}

......
Дальше идёт сравнение строки. Котрую получила функция.
.......

Не проще ли получаемую строку преобразовать в обычный char и искать его уже в массиве не из 15 строк, а как максимум из 15 char. Или из 15 элементов структуры (15*6=80 10 байт).
ReAl
Цитата(Xenom0rph @ Oct 6 2008, 14:41) *
нада бы использовать flash unsigned char, а если этот тип использовать, то функция strcmp не работает.
Вот два дня бьюсь, ничего невыходит.
У avr-gcc для этого есть strcmp_P (и все остальные str-функции) - одна строка в ОЗУ, вторая во флеше.

Цитата(Xenom0rph @ Oct 6 2008, 14:41) *
P.S. использую Code VisionAVR;
Ну как-то же и у него это должно делаться...
Хотя в общем и целом - "бросьте каку" и перейдите на IAR или avr-gcc (WinAVR).
MrYuran
Цитата(VladimirYU @ Oct 6 2008, 16:16) *
Это не бред, а просто массив указателей.

Тогда интересно, как можно инициализировать массив указателей значениями типа "000001"?

Я так полагаю, надо символьное представление двоичного числа преобразовать в число. Так?
По-моему, намного проще посимвольно проанализировать входящую строку и вычислить число.

Например, так:
Код
char ConvertFunction(char* string)
{
    char result=0;
    for (int i=0;i<5;i++)
    {
        if(string[i]=="1") result += 1<<i;
    }
    return(result);
}

ну чё-то в этом роде
ReAl
Цитата(Xenom0rph @ Oct 6 2008, 15:26) *
суть в функцию приходит сточка типа "xxxxxx", где x либо 1 либо 0, мы эту строчку сравниваем с имеющимися строками и если есть совпадения, то в переменную записываем порядковый номер?
Ну а можно это как нить решить?
В общем случае - строки во флеше и strcmp_P(), в данном конкретном - проще преобразовывать запись двоичного числа в символьном виде в байт и таким образом получать код.

Код
unsigned char get_code(const char *str)
{
    unsigned char u = 0;
    char ch;
    while( (ch = *str++) != 0 ) {
        u <<= 1;
        if( ch == '1') ++u;
    }
    return u;
}
VladimirYU
[quote name='MrYuran' date='Oct 6 2008, 16:31' post='481254']
Тогда интересно, как можно инициализировать массив указателей значениями типа "000001"?
[/quote]

Указатель инициализировать строкой нельзя, а строку на которую он указывает пожалуйста
там надо только
char __flash* mass[]={"str1", "srt2"....} (синтаксис IAR)

[/quote]
Я так полагаю, надо символьное представление двоичного числа преобразовать в число. Так?
По-моему, намного проще посимвольно проанализировать входящую строку и вычислить число.
[/quote]

Да мы задачи то толком не знаем.
aaarrr
Цитата(MrYuran @ Oct 6 2008, 16:31) *
Тогда интересно, как можно инициализировать массив указателей значениями типа "000001"?

Очень даже можно, стандарт позволяет. Только это не значение указателя, а объект, на который он указывает.
ReAl
Цитата(MrYuran @ Oct 6 2008, 15:31) *
Тогда интересно, как можно инициализировать массив указателей значениями типа "000001"?
Запросто. Строковый литерал имеет тип char*, поэтому им можно инициализировать как указатель, так и массив указателей.
Некоторые проблемы возникают у avr-gcc, но только при размещении строк во флеше и потому, что у него нет ключевого слова flash, означающего другой тип памяти, а есть только атрибут размещения переменной в секции, помещаемой во флеш. Атрибут применим к переменной, а не к литералу, только поэтому приходится заводить промежуточный массив char[].
При размещении массива указателей в ОЗУ инициализация их строковыми литераламаи - стандартная для С операция со времён создания языка.

Цитата(MrYuran @ Oct 6 2008, 15:31) *
Я так полагаю, надо символьное представление двоичного числа преобразовать в число. Так?
По-моему, намного проще посимвольно проанализировать входящую строку и вычислить число.

Несомненно.
VladimirYU
Цитата(ReAl @ Oct 6 2008, 16:46) *
Запросто. Строковый литерал имеет тип char*, поэтому им можно инициализировать как указатель, так и массив указателей.
Некоторые проблемы возникают у avr-gcc, но только при размещении строк во флеше и потому, что у него нет ключевого слова flash, означающего другой тип памяти, а есть только атрибут размещения переменной в секции, помещаемой во флеш. Атрибут применим к переменной, а не к литералу, только поэтому приходится заводить промежуточный массив char[].
При размещении массива указателей в ОЗУ инициализация их строковыми литераламаи - стандартная для С операция со времён создания языка.
Несомненно.

Дык, что товарищу тогда делать то при недостатке памяти и при этой особенности GCC кроме, как перейти на другой компилятор? Я просто предлогаю путь уменьшения расхода памяти.
Xenom0rph
Попробуем по другому
задача:
есть кодировка
000001 = 'A';
000010 = 'B';
100000 = 'C';
и так далее.
Так вот нужна такая функция, в которую входило допустим "000001";
мы сравнивали с имеющимися у нас строками, и присваивали переменной типа char наш символ.
Вот идея проекта.
Моя задумка была, реализовать все 15 кодов в массив, сравнить с прешедшей строчкой, получить номер элемента массива, и с помощью switch присвоить переменной значение.
Может есть какие более правильные или удобные решения?
VladimirYU
Цитата(Xenom0rph @ Oct 6 2008, 17:02) *
Попробуем по другому
задача:
есть кодировка
000001 = 'A';
000010 = 'B';
100000 = 'C';
и так далее.
Так вот нужна такая функция, в которую входило допустим "000001";
мы сравнивали с имеющимися у нас строками, и присваивали переменной типа char наш символ.
Вот идея проекта.
Моя задумка была, реализовать все 15 кодов в массив, сравнить с прешедшей строчкой, получить номер элемента массива, и с помощью switch присвоить переменной значение.
Может есть какие более правильные или удобные решения?

Получили строку, преобразовали в число, далее Ваш switch и массив вообще не нужен. ИМХО.
MrYuran
Если кодировку менять не предполагается, предлагаю дерево условий if-else. По-моему, самый простой и наименее затратный вариант. Во всех отношениях.

ReAl - спасибо за науку.
Век живи - век учись (с)
Xenom0rph
Цитата(VladimirYU @ Oct 6 2008, 17:06) *
Получили строку, преобразовали в число, далее Ваш switch и массив вообще не нужен. ИМХО.

А как 000001 преобразовать в число? а допустим 010000 это не одно и тоже получится, я вот плохо это представляю?


Цитата(MrYuran @ Oct 6 2008, 17:08) *
Если кодировку менять не предполагается, предлагаю дерево условий if-else. По-моему, самый простой и наименее затратный вариант. Во всех отношениях.

думал над этим только вот, беда
сравниваю допустим strcmpf("000001", string)
где string, это пришедшая строка
, а компилятор говорит мол тип надо поменять, я тут якобы использую flash unsigned char* , а надо просто unsigned char* вот!
MrYuran
Цитата(Xenom0rph @ Oct 6 2008, 17:16) *
думал над этим только вот, беда
сравниваю допустим strcmpf("000001", string)

Я предлагаю строку анализировать посимвольно.
if(string[0]=="1")
{ if(string[1]=="1")
{ if(string[2]=="1")
{...}
...
}
else {}
}
else {}
}
else {}

получается дерево условий. 6 сравнений - и на выходе готовый результат в каком хотите виде.
Сергей Борщ
Цитата(MrYuran @ Oct 6 2008, 16:24) *
получается дерево условий. 6 сравнений - и на выходе готовый результат в каком хотите виде.
Массив не нужен, зато теперь в процессор начинает не влезать код smile.gif Там не 6, а 6! условий получится.


Цитата(Xenom0rph @ Oct 6 2008, 16:16) *
А как 000001 преобразовать в число? а допустим 010000 это не одно и тоже получится, я вот плохо это представляю?
Вам дали уже 2 примера в сообщениях №8 и №9. Более подробно www.google.com->"двоичная система счисления"
Xenom0rph
Цитата(MrYuran @ Oct 6 2008, 17:24) *
Я предлагаю строку анализировать посимвольно.
if(string[0]=="1")
{ if(string[1]=="1")
{ if(string[2]=="1")
{...}
...
}
else {}
}
else {}
}
else {}

получается дерево условий. 6 сравнений - и на выходе готовый результат в каком хотите виде.


не не то... запутаешься нафиг, на краний случай оставлю, у верен другой выход есть!!!
MrYuran
Всё. Допёр.
Преобразуете вашу строку в число (как писалось ранее), а потом - switch-case.
Огурцов
Цитата(Xenom0rph @ Oct 6 2008, 11:41) *
char *mas[15] = {"000000","000001","000010" ... "111111"}

Так вот массив вылезает за пределы допустимой памяти.

Интересно, а строк всего сколько ? Из шести бит по логике д.б. 64 строки, а массив всего на 15.
Про остальное уже написали.
Xenom0rph
Цитата(MrYuran @ Oct 6 2008, 17:35) *
Всё. Допёр.
Преобразуете вашу строку в число (как писалось ранее), а потом - switch-case.

да это будет правильно, тоже доперло, всем огромное спасибо wink.gif

Цитата(Огурцов @ Oct 6 2008, 17:47) *
Интересно, а строк всего сколько ? Из шести бит по логике д.б. 64 строки, а массив всего на 15.
Про остальное уже написали.

сдесь не по логике, в кодировке всего 15 символ, вот...
NicSm
Не понятно зачем у вас явное присвоение массиву указателей на переменные типа чар. Даже если вы заранее распределили где и какие переменные находятся в памяти, помните где начинается ОЗУ? А у вас mas[0]=0. Да и строка инициализации содержит десятичные числа. У вас есть ячейка ОЗУ с адресом 111111? Это что у тини ОЗУ более100кбайт?

Выложите полный текст а там можно думать.
ReAl
Цитата(VladimirYU @ Oct 6 2008, 16:01) *
Дык, что товарищу тогда делать то при недостатке памяти и при этой особенности GCC кроме, как перейти на другой компилятор? Я просто предлогаю путь уменьшения расхода памяти.
Не понял вопроса.
У товарища CV, а не GCC, как ему бороться с его особенностями, я не знаю.
В конкретном случае товарища я уже написал в сообщении 9 фрагмент кода, как из ASCII записи двочиного числа получить код коротким циклом без массивов вообще.
В общем случае нужен массив указателей на строки char *array[] во флеше (при строках одинаковой длины можно массив строк char array[][] ).

А особенность GCC из-за его непонимания разных пространств памяти всего лишь вынуждает вместо
Код
const flash char * const flash array[] = { "00000", "00001", ... };

писать
Код
const prog_char str0[] = "00000";
const prog_char str1[] = "00001";
...
const prog_char *array[] PROGMEM = { str1, str2, ... };



Цитата(Xenom0rph @ Oct 6 2008, 16:02) *
Попробуем по другому
задача:
есть кодировка
000001 = 'A';
000010 = 'B';
100000 = 'C';
и так далее.
Так вот нужна такая функция, в которую входило допустим "000001";
мы сравнивали с имеющимися у нас строками, и присваивали переменной типа char наш символ.

Функция get_code() берётся из сообщения 9 (или 8, но её тогда лучше переписать так:
Код
char ConvertFunction(const char *string)
{
    char result=0;
    for (unsigned char mask=0x01; mask < (1<<5); mask <<= 1)
        if( *string++ == '1' ) result += mask;

    return(result);
}


Дальше если бы все сиволы в кодировке сидели "плотно" (т.е. при 6-битовом коде есть "ну почти все" 64 символа", то так (чтобы не затенять суть, пишу НЕ как для GCC, у него нужно несколько морочливее, если я правильно помню IAR, то им это должно скомпилироваться):
Код
const flash char code_table[64] = {
    0, /* например, это неиспользуемый код */
    'A', 'B', 'Z', /* используемые */
    ...
};

char decode_char( const char *str) {
    // вменяемый компилятор подставит get_table() inline
        // желательно get_table() объявить как static
    return code_table[ get_char(str) ];
}


Для разреженной таблицы кодов (исползуется 15 кодов из 64 и "врассыпку") посложнее, но всё равно должно занять во флеше меньше памяти, чем switch (хотя в среднем может работать дольше, тут надо выбирать):
Код
typedef struct {
    unsigned char code;
    char ch;
} code_map_entry;
const flash code_map_entry code_map[] = {
    { 0x01, 'A'},
    { 0x02, 'B'},
    { 0x20, 'C'}
};

char decode_char( const char *str) {
    unsigned char code = get_code(str);
    const flash code_map_entry *ptr = code_map;
    unsigned char i;
    for( i = 0; i < sizeof( code_map ) / sizeof( code_map_entry); ++i, ++ptr)
        if( code == ptr->code)
            return ptr->ch;
    return 0; // не нашлось такого кода
}
NicSm
Цитата(NicSm @ Oct 6 2008, 23:22) *
Не понятно зачем у вас явное присвоение массиву указателей на переменные типа чар. Даже если вы заранее распределили где и какие переменные находятся в памяти, помните где начинается ОЗУ? А у вас mas[0]=0. Да и строка инициализации содержит десятичные числа. У вас есть ячейка ОЗУ с адресом 111111? Это что у тини ОЗУ более100кбайт?

Выложите полный текст а там можно думать.


Извиняюсь написал не в тему. Понял когда просмотрел все посты.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.