Это потому что sh_pulse вызывается в коде раньше, чем объявляется - отсюда и проблема implicit declaration.
А необъявленные функции вроде как считаются по умолчанию возвращающими int, отсюда и "починка" помогает.
Либо выстраивайте последовательность функций так, чтобы "верхние" никогда не использовали "нижние", либо, что правильнее, для каждой функции в начале файла их дополнительно объявляйте. В идеале - как static, если они не вызываются из других модулей.
[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()
И еще вопрос: пытался делать это под линуксом (debian 10 x64), там AVR-GCC (установленный через APT) выдает типа:
Скорее всего в опциях компиляции не указали модель МК ключиком -mmcu
Ну нынче если вы определяете (не путать с объявлением, о котором я выше написал) функцию, то f() { ... } = f(void) { ... }. А вот с объявлением ( f(); ) могут быть нюансы, если потом определение не void. Я что-то сразу об этом не подумал. Если привыкли писать f(void) то и фиг с ним, проблема не в этом )
И вот мне захотелось, чтобы int* variable иногда являлся адресом void функции без параметров, которую я хочу запустить на выполнение.
как написать функцию, которой если передать int *variable, вызвала бы на выполнение функцию по адресу этой variable?
uldemir, через typedef (void *) лучше, что хотя бы если вы перепутаете и передадите указатель не на такой тип, то хотя бы warning компилятор сделает. А то передадите так int i; ... &i и капец ) А WiseLord более правильное решение подсказал, когда если по указателю ссылка может передаваться и на переменную и на функцию - то надо дополнительно передавать тип.
А вообще это по сути callback получается.
когда если по указателю ссылка может передаваться и на переменную и на функцию - то надо дополнительно передавать тип.
Можно сделать функтор (ну или лямбду, которая им и является по сути), который будет хранить указатель на int и возвращать его при вызове. И другие функторы, которые ничего хранить не будут, а будут при вызове делать свою работу и возвращать, например, NULL. Но тогда нужен будет уже C++, а тут C. Впрочем, это уже из разряда извращений в данном случае.
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;
}
А разные типы char, int итд, пока не нужно, так как эти переменные хранятся в конфигурационной EEPROM и для облегчения жизни они все одного размера. "Исполняемую" типу я захотел, так как у меня есть еще одна функция, которая вызывает разные процедуры в процессе работы. Так вот оно меня перестало удовлетворять, так как там я не могу с малой болью переставить элементы меню местами (а в этом я могу) и поэтому чтобы не делать ту же работу снова захотел расширить возможности этого меню, а то - выбросить (уф, сам не понял, что написал).
Зато хорошая идея использовать безымянный тип *void если переменная может исполнять разные роли. Опасался, что нужно будет править все места, где у меня идёт обработка, где они должны указывать на целые числа, но оказалось, что там я всё делал через указатель int *str_ptr, а присваивание этому указателю этого *void даже предупреждения не выдало и не нужно было делать cast.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
я в случаях, когда надо одним указателем работать с разными типами данных, использую внутри структур юнионы анонимные (а без структур - обычные), GCC позволяет так делать:
в параметрах функций или где надо, работаю с переменной этого типа, просто разыменовывая её так, как надо по символьным именам, без принудительного typecast-а, например var.str - это будет строка, *var.ptr32 - это будет 32-битное число, а вызвать функцию можно так var.function(12)... очень удобно, и при автоподстановке не ошибешься. все остальное делает компилятор.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
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},
И вот сейчас не могу вспомнить кто, но кто-то очень жаловался на анонимные юнионы и поэтому я их стал редко использовать - стал кастить указателями. Эти 32-битные данные в EEPROM пишу, ведь, как байты...
Эээээ... В данный момент MSP432P401R, но этот же код применяется и в STM32f051 и CY8C5268. Первых двух пользую в Keil, а последнего в PSoC Creator. Первого я раньше пользовал в Code Compose Studio, но быстро с него слез, так как на нетбук я не могу поставить 9-ю версию (нетбук 32-битный), а стационарный комп нельзя загнать в гибернацию, если остался студио запущен - в течение минуты комп включается снова сам.
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;
тфу, последовательность то не совпадает. Ну это и было целью отвязать группировку параметров на экране от расположения в конфигурационном ПЗУ, потому как если я ввёл еще один параметр для работы мотора - пусть на экране он будет у моторов, но в ПЗУ просто на следующем свободном месте, чтобы остальные конфигурационные параметры не потерялись. Так что loop и pathlength они тоже есть в этом списке. Но это ничего, Ваш вариант с void* меня вполне устраивает. Уже переправил код, всё работает. Осталось убрать неиспользуемый больше код и всё будет здорово!
А люди посмотрят и скажут: "Собаки летят. Вот и осень."