Вопросы по С/С++ (СИ)
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Это потому что sh_pulse вызывается в коде раньше, чем объявляется - отсюда и проблема implicit declaration.
А необъявленные функции вроде как считаются по умолчанию возвращающими int, отсюда и "починка" помогает.
Либо выстраивайте последовательность функций так, чтобы "верхние" никогда не использовали "нижние", либо, что правильнее, для каждой функции в начале файла их дополнительно объявляйте. В идеале - как static, если они не вызываются из других модулей.
А необъявленные функции вроде как считаются по умолчанию возвращающими int, отсюда и "починка" помогает.
Либо выстраивайте последовательность функций так, чтобы "верхние" никогда не использовали "нижние", либо, что правильнее, для каждой функции в начале файла их дополнительно объявляйте. В идеале - как static, если они не вызываются из других модулей.
Re: Вопросы по С/С++ (СИ)
[uquote="Shuspano",url="/forum/viewtopic.php?p=3835922#p3835922"]d:\avr\hc164.c:30:3: note: previous implicit declaration of 'sh_pulse' was here
sh_pulse();
^[/uquote]
Уже ответили, но если не понятно, после #include'ов напишите строку void sh_pulse(void); именно с ; в конце, без самого тела функции и заработает всё. Кстати void в скобках можно не писать везде. void sh_pulse()
sh_pulse();
^[/uquote]
Уже ответили, но если не понятно, после #include'ов напишите строку void sh_pulse(void); именно с ; в конце, без самого тела функции и заработает всё. Кстати void в скобках можно не писать везде. void sh_pulse()
Скорее всего в опциях компиляции не указали модель МК ключиком -mmcuИ еще вопрос: пытался делать это под линуксом (debian 10 x64), там AVR-GCC (установленный через APT) выдает типа:
Re: Вопросы по С/С++ (СИ)
[uquote="WiseLord",url="/forum/viewtopic.php?p=3835924#p3835924"]Это потому что sh_pulse вызывается в коде раньше, чем объявляется.[/uquote]
Когда-то достаточно давно, пытался ковырятся с Borland C 3.1, помню он очень ревностно относился к синтаксису.
Спасибо, буду знать.NStorm писал(а):Кстати void в скобках можно не писать везде. void sh_pulse()
Когда-то достаточно давно, пытался ковырятся с Borland C 3.1, помню он очень ревностно относился к синтаксису.
Re: Вопросы по С/С++ (СИ)
Ну нынче если вы определяете (не путать с объявлением, о котором я выше написал) функцию, то f() { ... } = f(void) { ... }. А вот с объявлением ( f(); ) могут быть нюансы, если потом определение не void. Я что-то сразу об этом не подумал. Если привыкли писать f(void) то и фиг с ним, проблема не в этом )
Re: Вопросы по С/С++ (СИ)
Подскажите как сделать. Тоже рисую велосипед меню. И у меня есть такая структура:
И вот мне захотелось, чтобы int* variable иногда являлся адресом void функции без параметров, которую я хочу запустить на выполнение.
как написать функцию, которой если передать int *variable, вызвала бы на выполнение функцию по адресу этой variable?
Код: Выделить всё
typedef struct {
unsigned char todisplay[16];
int *variable;
datatype_t datatype;
} menuitem_t;как написать функцию, которой если передать int *variable, вызвала бы на выполнение функцию по адресу этой variable?
Код: Выделить всё
void FreeRun(void);
menuitem_t menu[] = {
...
{"Free Run", (int*)FreeRun, execute},
...
}А люди посмотрят и скажут: "Собаки летят. Вот и осень."
- da-nie
- Говорящий с текстолитом
- Сообщения: 1590
- Зарегистрирован: Вс июн 24, 2012 16:07:00
- Откуда: Лен.Обл.
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Можно запустить на выполнение, например, так:как написать функцию, которой если передать int *variable, вызвала бы на выполнение функцию по адресу этой variable?
void Test(void)
{
};
menuitem_t menuitem;
menuitem.variable=(int*)Test;
typedef void (*func_ptr)(void);
((func_ptr)menuitem.variable)();
И день и ночь в пути...
Мои программки: 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
Re: Вопросы по С/С++ (СИ)
Написал так:
Вррроде работает... сейчас попробую через typedef.
О, так даже проще! Спасибо.
Код: Выделить всё
void do_execute(int* addr) {
void (*Task)(void);
Task = (void (*)(void))addr;
(*Task)();
}О, так даже проще! Спасибо.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Вот такой пример:
Выводит:
Спойлер
Код: Выделить всё
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
typedef enum {
var_int,
var_char,
execute,
} datatype_t;
typedef struct {
unsigned char todisplay[16];
void *variable;
datatype_t datatype;
} menuitem_t;
void FreeRun(void)
{
printf("Hello FreeRun\n");
}
int height = 3;
char hour = 10;
typedef enum {
HEIGHT,
FREE_RUN,
HOUR,
} menuidx_t;
menuitem_t menu[] = {
[HEIGHT] = {"Height", &height, var_int},
[FREE_RUN] = {"Free Run", FreeRun, execute},
[HOUR] = {"Hour", &hour, var_char},
};
typedef void (*execute_func)(void);
void handleMenu(menuidx_t idx)
{
switch (menu[idx].datatype) {
case var_int: {
int *var = (int *)(menu[idx].variable);
(*var)++;
}
break;
case var_char: {
char *var = (char *)(menu[idx].variable);
(*var)--;
}
break;
case execute: {
execute_func func = (execute_func)(menu[idx].variable);
func();
}
break;
}
}
int main()
{
printf("----Before:\n");
printf("Height: %d\n", height);
printf("Hour: %d\n", hour);
handleMenu(HEIGHT);
handleMenu(FREE_RUN);
handleMenu(HOUR);
printf("----After:\n");
printf("Height: %d\n", height);
printf("Hour: %d\n", hour);
return 0;
}
Спойлер
Код: Выделить всё
----Before:
Height: 3
Hour: 10
Hello FreeRun
----After:
Height: 4
Hour: 9Re: Вопросы по С/С++ (СИ)
uldemir, через typedef (void *) лучше, что хотя бы если вы перепутаете и передадите указатель не на такой тип, то хотя бы warning компилятор сделает. А то передадите так int i; ... &i и капец ) А WiseLord более правильное решение подсказал, когда если по указателю ссылка может передаваться и на переменную и на функцию - то надо дополнительно передавать тип.
А вообще это по сути callback получается.
А вообще это по сути callback получается.
- da-nie
- Говорящий с текстолитом
- Сообщения: 1590
- Зарегистрирован: Вс июн 24, 2012 16:07:00
- Откуда: Лен.Обл.
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Можно сделать функтор (ну или лямбду, которая им и является по сути), который будет хранить указатель на 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
Re: Вопросы по С/С++ (СИ)
У меня примерно так и сделано было:
А разные типы 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.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
я в случаях, когда надо одним указателем работать с разными типами данных, использую внутри структур юнионы анонимные (а без структур - обычные), 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;если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Ну да. Обычно так и делается - структура, в которой два поля - 1) enum типа и 2) union разных типов.
Оно и при сериализации можно использовать, когда нужно разнородные данные уметь отправлять по какой-нибудь шине в другой МК, например.
Оно и при сериализации можно использовать, когда нужно разнородные данные уметь отправлять по какой-нибудь шине в другой МК, например.
Re: Вопросы по С/С++ (СИ)
Пока работаю с 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);
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
- da-nie
- Говорящий с текстолитом
- Сообщения: 1590
- Зарегистрирован: Вс июн 24, 2012 16:07:00
- Откуда: Лен.Обл.
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
А что у вас за контроллер?
И день и ночь в пути...
Мои программки: 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
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
uldemir, по коду непонятно.
Во-первых, отступы так пляшут, что непонятно, как Вы с этим разбираетесь.
Во-вторых, из этого кусочка неизвестно, что такое data.pathlength, data.loop
Во-первых, отступы так пляшут, что непонятно, как Вы с этим разбираетесь.
Во-вторых, из этого кусочка неизвестно, что такое data.pathlength, data.loop
Re: Вопросы по С/С++ (СИ)
Эээээ... В данный момент 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;А люди посмотрят и скажут: "Собаки летят. Вот и осень."
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
очень советую использовать инициализацию с структур с указанием полей, тогда проблем не должно быть: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}
};
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Вопросы по С/С++ (СИ)
Keil не хочет анонимные юнионы:А я не знаю, хочу ли я их включать...
Код: Выделить всё
configure.h(12): error: #3092: anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unionsА люди посмотрят и скажут: "Собаки летят. Вот и осень."
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
а вы заставьте! включите ему режим С99... я по кейлу не спец, но не поверю, что он не поддерживает!uldemir писал(а):Keil не хочет анонимные юнионы:
Добавлено after 1 minute 4 seconds:
блин, только сейчас усмотрел: вам же компилятор сам написал, что надо сделать!
uldemir писал(а):anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unions
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!