А вообще это по сути callback получается.
Вопросы по С/С++ (СИ)
- Сообщения: 1978
- Зарегистрирован: Ср июл 17, 2013 13:55:57
uldemir, через typedef (void *) лучше, что хотя бы если вы перепутаете и передадите указатель не на такой тип, то хотя бы warning компилятор сделает. А то передадите так int i; ... &i и капец ) А WiseLord более правильное решение подсказал, когда если по указателю ссылка может передаваться и на переменную и на функцию - то надо дополнительно передавать тип.
А вообще это по сути callback получается.
А вообще это по сути callback получается.
- Реклама
Можно сделать функтор (ну или лямбду, которая им и является по сути), который будет хранить указатель на int и возвращать его при вызове. И другие функторы, которые ничего хранить не будут, а будут при вызове делать свою работу и возвращать, например, NULL. Но тогда нужен будет уже C++, а тут C. Впрочем, это уже из разряда извращений в данном случае.когда если по указателю ссылка может передаваться и на переменную и на функцию - то надо дополнительно передавать тип.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
У меня примерно так и сделано было:
А разные типы char, int итд, пока не нужно, так как эти переменные хранятся в конфигурационной EEPROM и для облегчения жизни они все одного размера. "Исполняемую" типу я захотел, так как у меня есть еще одна функция, которая вызывает разные процедуры в процессе работы. Так вот оно меня перестало удовлетворять, так как там я не могу с малой болью переставить элементы меню местами (а в этом я могу) и поэтому чтобы не делать ту же работу снова захотел расширить возможности этого меню, а то - выбросить (уф, сам не понял, что написал).
Зато хорошая идея использовать безымянный тип *void если переменная может исполнять разные роли. Опасался, что нужно будет править все места, где у меня идёт обработка, где они должны указывать на целые числа, но оказалось, что там я всё делал через указатель int *str_ptr, а присваивание этому указателю этого *void даже предупреждения не выдало и не нужно было делать cast.
Код: Выделить всё
switch (item[select].datatype) {
case decimal:
mode = edit_mode;
editnum = 5; break;
case hex:
mode = edit_mode;
editnum = 4; break;
case hex32:
mode = edit_mode;
editnum = 8; break;
case execute:
((func_ptr)item[select].variable)();
break;
case none:
return;
}
Зато хорошая идея использовать безымянный тип *void если переменная может исполнять разные роли. Опасался, что нужно будет править все места, где у меня идёт обработка, где они должны указывать на целые числа, но оказалось, что там я всё делал через указатель int *str_ptr, а присваивание этому указателю этого *void даже предупреждения не выдало и не нужно было делать cast.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
я в случаях, когда надо одним указателем работать с разными типами данных, использую внутри структур юнионы анонимные (а без структур - обычные), GCC позволяет так делать:в параметрах функций или где надо, работаю с переменной этого типа, просто разыменовывая её так, как надо по символьным именам, без принудительного typecast-а, например var.str - это будет строка, *var.ptr32 - это будет 32-битное число, а вызвать функцию можно так var.function(12)... очень удобно, и при автоподстановке не ошибешься. все остальное делает компилятор.
Код: Выделить всё
typedef union{
void(*function)(int*);
uint32_t *ptr32;
char *str;
} my_ptr_t;
my_ptr_t var;если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Ну да. Обычно так и делается - структура, в которой два поля - 1) enum типа и 2) union разных типов.
Оно и при сериализации можно использовать, когда нужно разнородные данные уметь отправлять по какой-нибудь шине в другой МК, например.
Оно и при сериализации можно использовать, когда нужно разнородные данные уметь отправлять по какой-нибудь шине в другой МК, например.
- Реклама
Пока работаю с Keil, и что-то не получается:
выдал ошибки. Похоже, оно ожидало только первый формат void(*function)(void). На строчку {"Free Run ", FreeRun, execute} возражений не было.
И вот сейчас не могу вспомнить кто, но кто-то очень жаловался на анонимные юнионы и поэтому я их стал редко использовать - стал кастить указателями. Эти 32-битные данные в EEPROM пишу, ведь, как байты...
Код: Выделить всё
typedef union{
void(*function)(void);
int *ptr32;
} my_ptr_t;
typedef struct {
unsigned char todisplay[16];
my_ptr_t variable;
datatype_t datatype;
} menuitem_t;
const menuitem_t menu_item[] = {
{"PathLength xxxxx", &data.pathlength, decimal},
{"Loop Num xxxxx", &data.loop, decimal},
...
{"Free Run ", FreeRun, execute},
Код: Выделить всё
main.c(146): error: #144: a value of type "int *" cannot be used to initialize an entity of type "void (*)(void)"
{"PathLength xxxxx", &data.pathlength, decimal},
main.c(147): error: #144: a value of type "int *" cannot be used to initialize an entity of type "void (*)(void)"
{"Loop Num xxxxx", &data.loop, decimal},Код: Выделить всё
pData = (unsigned char*)(&data);
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
А что у вас за контроллер?
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
uldemir, по коду непонятно.
Во-первых, отступы так пляшут, что непонятно, как Вы с этим разбираетесь.
Во-вторых, из этого кусочка неизвестно, что такое data.pathlength, data.loop
Во-первых, отступы так пляшут, что непонятно, как Вы с этим разбираетесь.
Во-вторых, из этого кусочка неизвестно, что такое data.pathlength, data.loop
Эээээ... В данный момент MSP432P401R, но этот же код применяется и в STM32f051 и CY8C5268. Первых двух пользую в Keil, а последнего в PSoC Creator. Первого я раньше пользовал в Code Compose Studio, но быстро с него слез, так как на нетбук я не могу поставить 9-ю версию (нетбук 32-битный), а стационарный комп нельзя загнать в гибернацию, если остался студио запущен - в течение минуты комп включается снова сам.
WiseLord, data.xxxxxxx - это как раз и есть набор переменных типа int (32-битные). А то что "пляшут", так исходники правятся постоянно в разных средах, кто-то ставит табуляцию, кто-то ставит пробелы вместо них... Ну а потом в этом редакторе еще пытаюсь выравнять и получается еще хуже. извините.тфу, последовательность то не совпадает. Ну это и было целью отвязать группировку параметров на экране от расположения в конфигурационном ПЗУ, потому как если я ввёл еще один параметр для работы мотора - пусть на экране он будет у моторов, но в ПЗУ просто на следующем свободном месте, чтобы остальные конфигурационные параметры не потерялись. Так что loop и pathlength они тоже есть в этом списке. Но это ничего, Ваш вариант с void* меня вполне устраивает. Уже переправил код, всё работает. Осталось убрать неиспользуемый больше код и всё будет здорово!
WiseLord, data.xxxxxxx - это как раз и есть набор переменных типа int (32-битные). А то что "пляшут", так исходники правятся постоянно в разных средах, кто-то ставит табуляцию, кто-то ставит пробелы вместо них... Ну а потом в этом редакторе еще пытаюсь выравнять и получается еще хуже. извините.
Спойлер
Код: Выделить всё
typedef struct {
int threshold;
int maxspeed;
int turnspeed;
int minspeed;
int acceleration;
int k_error;
int k_diff;
int div_sigma;
int on_way;
int timetorun;
...итд
} eedata_t ;
extern eedata_t data;А люди посмотрят и скажут: "Собаки летят. Вот и осень."
очень советую использовать инициализацию с структур с указанием полей, тогда проблем не должно быть:uldemir писал(а):что-то не получается:
Код: Выделить всё
typedef typedef struct {
unsigned char todisplay[16];
union{ // для структур лучше использоать анонимный юнион, а не отдельный тип - я ж писал об этом
void(*function)(void);
int *ptr;
};
datatype_t datatype;
} menuitem_t;
const menuitem_t menu_item[] = {
{.todisplay = "PathLength xxxxx", .ptr = &data.pathlength, .datatype = decimal},
{.todisplay = "Loop Num xxxxx", .ptr = &data.loop, .datatype = decimal},
...
{.todisplay = "Free Run ", .function = FreeRun, .datatype = execute}
};
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Keil не хочет анонимные юнионы:А я не знаю, хочу ли я их включать...
Код: Выделить всё
configure.h(12): error: #3092: anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unionsА люди посмотрят и скажут: "Собаки летят. Вот и осень."
а вы заставьте! включите ему режим С99... я по кейлу не спец, но не поверю, что он не поддерживает!uldemir писал(а):Keil не хочет анонимные юнионы:
Добавлено after 1 minute 4 seconds:
блин, только сейчас усмотрел: вам же компилятор сам написал, что надо сделать!
uldemir писал(а):anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unions
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 275
- Зарегистрирован: Вс окт 20, 2019 13:03:56
Добрый день.
Столкнулся с такой ошибкой в подпрограмме setup():
сама подпрограмма:
Ощущается состояние обутости в лыжи. Ну вот что тут может быть не так?
Столкнулся с такой ошибкой в подпрограмме setup():
Код: Выделить всё
D:\avr\hc164.c:17:2: error: stray '\302' in program
PORT┬ |= (1 << PB0);
^Код: Выделить всё
void setup(void)
{
DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2);
DDRD &= ~(1 << PD7);
DDRD |= (1 << PD6);
PORTВ |= (1 << PB0);
}
- Сообщения: 1978
- Зарегистрирован: Ср июл 17, 2013 13:55:57
*фэйспалм.джпг*
Вам же в ошибке явно написано в чем проблема. Не PORTB у вас там, а PORTВ написано. Не видите разницы? А она есть. Не надо кириллицей пытаться замещать латинские буквы с таким же написанием.
Вам же в ошибке явно написано в чем проблема. Не PORTB у вас там, а PORTВ написано. Не видите разницы? А она есть. Не надо кириллицей пытаться замещать латинские буквы с таким же написанием.
- Сообщения: 275
- Зарегистрирован: Вс окт 20, 2019 13:03:56
Упс...Извините. Ну я это не специально.
Часто avr-gcc указывает на ошибки там где их нету, или их описание настолько лапидарно, что в целом, ни о чем. Уже привык.
Часто avr-gcc указывает на ошибки там где их нету, или их описание настолько лапидарно, что в целом, ни о чем. Уже привык.
- Сообщения: 1978
- Зарегистрирован: Ср июл 17, 2013 13:55:57
Ну видно же, что вместо PORTB в выводе комилятора уже написано "PORT┬". И выше текст о недопустимом символе. Это и должно было на мысль натолкнуть.
с роду такого не было! примеры в студиюShuspano писал(а):Часто avr-gcc указывает на ошибки там где их нету
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 275
- Зарегистрирован: Вс окт 20, 2019 13:03:56
[uquote="ARV",url="/forum/viewtopic.php?p=3838320#p3838320"]
Ну вот например:
Строка 99 = закрывающая скобка подпрограммы main()
весь код:
если это не компилятор выделывается, то что это?
с роду такого не было! примеры в студию[/uquote]Shuspano писал(а):Часто avr-gcc указывает на ошибки там где их нету
Ну вот например:
Код: Выделить всё
D:\comp\avr8-gnu-toolchain\bin>avr-gcc -Os -mmcu=attiny13a -o d:\avr\hc164-13a.e
lf d:\avr\hc164.c
d:\avr\hc164.c: In function 'hc595latch':
d:\avr\hc164.c:99:2: error: expected declaration or statement at end of input
}
^
весь код:
Спойлер
Код: Выделить всё
#define F_CPU 8000000UL
#define sclock PB2
#define sdata PB0
#define latch PB4
#define rdata PB3
#include <avr/io.h>
#include <util/delay.h>
void setup(void)
{
DDRB |= (1 << sdata)|(1 << sclock)|(1 << latch);
DDRB &= ~(1 << rdata);
}
void sh_pulse(void)
{
PORTB |= (1 << sclock);
PORTB &= ~(1 << sclock);
}
void hc165latch(void)
{
PORTB &= ~(1 << latch);
PORTB |= (1 << latch);
}
void hc595latch(void)
{
PORTB |= (1 << latch);
PORTB &= ~(1 << latch);
void hc595send(unsigned char hc595data)
{
PORTB |= (1 << latch);
int i;
for (i=0; i<8; i++)
{
if (hc595data & 0x80)
{
PORTB |= (1 << sdata);
}
else
{
PORTB &= ~(1 << sdata);
}
hc595data = hc595data << 1;
sh_pulse();
}
hc595latch();
}
unsigned char hc165read()
{
PORTB &= ~(1 << latch);
unsigned char hc165data;
int y;
hc165latch();
for (y=0; y<8; y++)
{
hc165data = hc165data << 1;
if (PINB & (1 << rdata))
{
hc165data |= (1 << 0);
}
else
{
hc165data &= ~(1 << 0);
}
sh_pulse();
}
return(hc165data);
}
/*
void ledflash(void)
{
PORTD |= (1 << ledpin);
_delay_ms (5);
PORTD &= ~(1 << ledpin);
_delay_ms (5);
}
*/
void main(void)
{
setup();
while(1)
{
unsigned char j;
j = ~hc165read();
hc595send(j);
ledflash();
_delay_ms(50);
}
}
- Сообщения: 1978
- Зарегистрирован: Ср июл 17, 2013 13:55:57
Shuspano, ошибка состоит из 2х строк, а не одной. Над сторокой со строкой ошибки, есть еще одна строка =/
d:\avr\hc164.c: In function 'hc595latch':
Сразу должно смутить, что функция hc595latch у нас идет до 99ой строки. Смотрим - и у функции пропущена закрывающая }. И конечно же компилятор считает, что эта функция продолжается до конца файла и резко обрывается, не закрываясь должным образом. Потому что компилятор прежде чем разбирать саму функцию, ищет её начало и конец по { }. И не находит в вашем случае.
На самом деле ошибка вполне очевидная, если понимать это.
d:\avr\hc164.c: In function 'hc595latch':
Сразу должно смутить, что функция hc595latch у нас идет до 99ой строки. Смотрим - и у функции пропущена закрывающая }. И конечно же компилятор считает, что эта функция продолжается до конца файла и резко обрывается, не закрываясь должным образом. Потому что компилятор прежде чем разбирать саму функцию, ищет её начало и конец по { }. И не находит в вашем случае.
На самом деле ошибка вполне очевидная, если понимать это.
Мало того, ещё и ledflash закоменчен. Хотя пытаются его вызвать 
Добавлено after 1 minute 30 seconds:
[uquote="Shuspano",url="/forum/viewtopic.php?p=3839044#p3839044"]если это не компилятор выделывается, то что это?[/uquote]Руки, сударь, руки ...
PS: Всегда удивляли вот такие компиляторвиноват'оры. Конечно, а ктож ещё, не они же сами
Добавлено after 1 minute 30 seconds:
[uquote="Shuspano",url="/forum/viewtopic.php?p=3839044#p3839044"]если это не компилятор выделывается, то что это?[/uquote]Руки, сударь, руки ...
PS: Всегда удивляли вот такие компиляторвиноват'оры. Конечно, а ктож ещё, не они же сами


