Страница 198 из 386

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 10:11:39
Pink-Pank
ругается потому, что Вы объявляете массив целых чисел, а запихиваете туда указатели.
А в Code Vision, если не ошибаюсь, const = flash

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 11:30:51
uk8amk
Это я понимаю, что имеется несоответствие типов данных, оттого и ругается.
Просто я не могу понять, как привести тип функции void к константному значению, понятному для flash uint16_t.

Как я рассуждаю:
(1)Функция func1() находится во флеш по физическому 16-битному адресу N.
(2)Этот адрес мы заносим(точнее заносит компилятор) в ячейку flash массива func_adress[].
(3)Далее в самой программе в переменную uint16_t adr читается адрес из массива adr = func_adress[x];
(4)Приводитя к типу указателя на функцию:
void (*p_func)(void);
p_func = (void(*)(void))adr;
(5)Переход:
p_func();

Как раз на этапе (2) у меня проблема.

ЗЫ. В codevision const=flash если включить соответсвующую опцию компилятора. А так кладет в RAM.

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 11:39:40
ARV
для сложных типов данных я всегда применяю описание собственных типов, тогда получается гораздо проще описать именно то, что желаешь, и не запутаться

Код: Выделить всё

typedef void (*menu_finc_ptr)(void); // определили тип днных "указатель на функцию"

flash menu_func_ptr func_array[] = {func1, func2, func3, ...}; // определили массив во flash этих самых указателей
потом, кстати, и приведение типов легче делать - не многоэтажная запись, а одноэтажная :)))

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 11:40:29
Аlex
Просто я не могу понять, как привести тип функции void к константному значению, понятному для flash uint16_t
А для чего все эти извращения-приведения ? Почему сразу не сделать массив указателей ?

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 11:58:53
uk8amk
Указатель - есть по сути переменная. А переменная кладётся в RAM.
Когда 2-3 функции, то разницы по сути нет где хранить. Когда десятки функций и есть некоторый дефицит RAM, то начинаешь задумываться об оптимизации.

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 12:39:26
Аlex
uk8amk писал(а):Указатель - есть по сути переменная.
Я имел ввиду тип массива - указатель на функцию (void (*ptr)(void)), а не целое (uint16_t). Для чего все эти лишние приведения типов :dont_know:

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 12:50:21
uk8amk
Ха!
То, что описал ARV разместилось в Flash, как раз что надо, спасибо.

Только не могу понять, почему объявление
flash void(*mnu_func_ptr[11])(void) ={ // menu functions pointer
menu_main,
menu_time,
menu_date,
у меня вызывало ошибку Storage modifier not allowed in this context.
Вроде аналогичное объявление.

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 15:59:15
uk8amk
С предыдущим вопросом кое-как разобрался. Теперь возник следующий и тоже про указатели.
Значит есть в моей менюшке строки:

Код: Выделить всё

flash uint8_t str_time[]  ="ВРЕМЯ";
flash uint8_t str_date[]  ="ДАТА";
и т.д.
Если я создам массив указателей

Код: Выделить всё

flash uint8_t *mnu_main_str_ptr[]={ str_time, str_date, ...
То они(указатели) опять попадают в SRAM, строк много, памяти жалко.
Тогда я делаю такой массив:

Код: Выделить всё

flash uint16_t mnu_ptr[] = { // массив адресов строк меню во флеш
(uint16_t) &str_time, // вычисление адреса строки и приведение к 16-бит 
(uint16_t) &str_date,
... };
Использование:

Код: Выделить всё

copymem_load_fstr( (flash uint8_t*)mnu_ptr[mnu_item_index], str_buf_RAM ); //загрузить flash строку в RAM
Прототип функции копирования:

Код: Выделить всё

copymem_load_fstr( flash uint8_t *str, uint8_t *dest ); // *источник flash, *буфер RAM 
В принципе всё нормально работает, но выглядит как-то монстрообразно.
Можно ли привести это в нормальный, человеческий вид?

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 18:10:50
ARV
Во-первых, зачем постоянно преобразовывать указатель к uint16_t и обратно? Глупо же.
Во-вторых, сделайте, как в прошлый раз через новые типы. Только не забудьте, что у вас указатель во флэш на символ во флэш...
В-третьих, зачем копировать строку в ОЗУ? Не проще ли выводить её сразу из флэш?

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 19:26:41
uk8amk
(1) Так иначе компилятор матерится.
Или вы о чём то другом. Если да то можно пример?
(3) Там небольшая прослойка API, принимает строку из ОЗУ. Дело в том, что показ строк меню - это далеко не самая главная задача устройства.

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 20:25:04
ARV

Код: Выделить всё

typedef void(*func_ptr)(void);

static void func1(void){
}

static void func2(void){
}

flash func_ptr func_array[] = {func1, func2};

func_ptr exec;

exec = func_array[1];
exec();
разве в таком коде будет ругня компилятора? в нем нет никаких преобразований типов.

Код: Выделить всё

flash char str1[] = "привет!"
flash char str2[] = "пока!";

typedef flash char * flash_str;

flash flash_str str_array[] = {str1, str2};

char ram_str[20];

copymem_load_fstr(str_array[1], ram_str);
а в этом коде? тоже без всяких преобразований...

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 20:42:10
uk8amk
Так работает нормально, спасибо.

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 20:46:36
ARV
если поддержка flash компилятром сделана качественно, то промежуточные переменные могут вообще не понадобиться:

Код: Выделить всё

typedef void(*func_ptr)(void);

flash func_ptr func_array[] = {func1, func2};

func_array[1](); // просто выполняем функцию из массива

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 20:55:55
uk8amk
Если распутать данное определение, то получается

Код: Выделить всё

flash flash char* str_array[] = {str1, str2};
Я правильно понял?

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 21:16:52
ARV
Лично я не настолько влюблен в Си, чтобы колупаться в его ребусах. Я делаю, как мне проще, а как оно разворачивается, мне не интересно.

С моей точки зрения корректно сделанный новый тип намного практичнее и удобнее (и понятнее) развернутой записи.

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 21:34:02
uk8amk
И тем не немее, вы написали код, который корректно работает.

Мне же пока до конца не ясны некоторые нюансы вроде этого. Книга K&R и ряд статей интернета не дали ответа по данному направлению. Может посоветуете что почитать, чтобы окончательно разобраться в указателе на указатели и в каких случаях в какую память они помещаются.

Re: Вопросы по С/С++ (СИ)

Добавлено: Ср авг 06, 2014 21:59:24
ARV
Написать корректный код мне помог здравый смысл. K&R я читал бегло и понял, что там слишком много лишнего написано. В частности там описан миллион способов сделать непонятными простые вещи...например, записать в "развернутом" виде указатель на функцию, возвращающую указатель на структуру и имеющую в качестве параметра указатель на функцию с тремя параметрами и возвратом указателя...

Хотя гуру это пишут и читают походя, меня это не привлекает, и я делаю то же самое простыми способами.

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

Я никогда не объявляю переменные-структуры без предварительного определения соответствующего типа-структуры... и так во всем: если можно написать проще - я так и делаю.

Си разрешает слишком многое, но,имхо, можно не означает нужно...

Re: Вопросы по С/С++ (СИ)

Добавлено: Вс авг 17, 2014 20:20:07
FreshMan
кто-либо осведомлен, почему элементы массива нумеруются с нуля а не с единицы ? :)

Re: Вопросы по С/С++ (СИ)

Добавлено: Вс авг 17, 2014 22:33:07
WiseLord
Потому что это естественно. 0b00000000 - минимальное число, которое можно представить в двоичном виде. И как-то логично, чтобы считать 0b00000000 нулём, а не единицей.

(естественно, 0b10000000 (char), 0b10000000 00000000 (int), 0b10000000 00000000 00000000 00000000 (long) - эти минимальные в своих границах (байт, два байта, четыре байта) числа как бы много меньше нуля, но это в некоторой мере искусственная условность).

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

Re: Вопросы по С/С++ (СИ)

Добавлено: Пн авг 18, 2014 07:11:57
ARV
WiseLord писал(а):А с единицы массивы нумеруются в каком-нибудь Паскале, т.к. в большей мере этот язык для обучения программированию, нежели что-то действительно серьёзное. Ну вроде как малых детей учат считать с единицы, т.к. ноль - это более недоступная их пониманию категория.
в паскале массивы индексируются в пределах, какие заданы программистом - хоть с нуля, хоть с 312, хоть с -257 - в зависимости от того, как более удобно описать имитируемые объекты реального мира. в реальном мире никто никогда нигде не считает, например, автомобили с нуля :)))