Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Котуинко

Пн ноя 04, 2019 17:01:43

УВЫ...
иначе я б тем садомазохизмом не занимался...
:(
ни в случае со "скобочной" формой, ни через тип, объявленный как typedef
extern не уживается...
Вот кусманчик из mino_3 (общий файлик dhsct.h)

Код:
.........
 typedef void (*ptr_fn)();
...........
extern byte te0;
extern void fe0();
extern byte te1;
extern void fe1();
extern void fn2();
// extern ptr_fn ptr_fn_var;// в данном месте не выполняется компилятором
// ptr_fn ptr_fn_var;// в данном месте не выполняется компилятором

:dont_know:
В случае однофайловика особо на такие "выкрутасы" и надобности не возникает.
Да и чаще "передачу параметрами" выполняют.
:roll:

Re: Котуинко

Пн ноя 04, 2019 17:14:43

В данном месте не выполняется?! Вы можете говорить не загадками, аинаписать, что именно сообщил "на это место" компилятор?

typedef ничем не отличается от, предположим, int. С чего это у вас "не выполняется"?!

Re: Котуинко

Вт ноя 05, 2019 02:23:23

Код:
extern void fe0();
...
extern void fe1();
extern void fn2();

штотыделоешьдемонприкрати. extern - для переменных, а не функций. Не, есть extern "C" и прочие, но это не сейчас.

попытайтесь объявить extern переменную, тип которой
определяется ранее выполненным typedef


func.h
Спойлер
Код:
#ifndef __FUNC_H
#define __FUNC_H

typedef void (*ptr_fn)(void);

extern ptr_fn ptr_fn_var;

#endif

main.c
Спойлер
Код:
#include "func.h"

int main(){
   ptr_fn_var();
}

func.c
Спойлер
Код:
#include "func.h"
#include <stdio.h>

void tst(){
   puts("PREVED");
}

ptr_fn ptr_fn_var=&tst;



собираем, запускаем
Спойлер
Код:
arkhnchul@arkhost-scow:/tmp/fptest$ gcc -O0 -Wall -Wextra -c func.c
arkhnchul@arkhost-scow:/tmp/fptest$ gcc -O0 -Wall -Wextra -c main.c
arkhnchul@arkhost-scow:/tmp/fptest$ gcc -O0 -Wall -Wextra main.o func.o -o externtst
arkhnchul@arkhost-scow:/tmp/fptest$ ./externtst
PREVED
arkhnchul@arkhost-scow:/tmp/fptest$

Re: Котуинко

Вт ноя 05, 2019 03:22:14

...
void tst(){
puts("PREVED");
}

ptr_fn ptr_fn_var=&tst;
...

Разве для получения указателя на функцию нужен символ '&'? Насколько я помню, как и для массивов, для функций само имя и есть указатель.

Re: Котуинко

Вт ноя 05, 2019 04:56:32

необязательно. Но имхо лучше явно писать, чтобы было сразу видно "здесь в переменную мы пишем адрес вот этой вот штуки". И для массивов тоже.

Re: Котуинко

Вт ноя 05, 2019 10:06:25

arkhnchul
КАК ЭТО НЕ ДЛЯ ФУНКЦИЙ??
"....
СпойлерПриведем небольшой законченный пример, в котором строка определяется в одном файле, а
печатается в другом. В файле header.h определяются нужные типы:
// header.h

extern char * prog_name;
extern void f();
Файл main.c является основной программой:
// main.c

#include "header.h"
char * prog_name = "примитивный, но законченный пример";
int main ()
{
f();
}
а строка печатается функцией из файла f.c:
// f.c
#include <stream.h>
#include "header.h"
void f ()
{
cout << prog_name << '\n';
}

..."

это кусманчик из Страуструпа...
:dont_know:

ARV
Я из-за тех "матюков" и развел сей прикладной "садомазохизм" (собственно по причине непоняток с extern)...
Закомментированы те варианты, что в данном примере (mino_3) вызывают матюки у адурино IDE (как в "чистопрордном GCC"- Х/З - я его пока не использую).
Там два заголовочника с объявлением типа "указатель на функцию" -
один в общем файле dhsct.h (закомментирован), а второй в заголовочнике mino.h.
Если открыть тот, что в dhsct.h и закомментировать соответственно в mino.h
получим следующий матюк:

Спойлер
Код:
C:\DOCUME~1\BORIS\LOCALS~1\Temp\ccDwyKZy.ltrans0.ltrans.o: In function `setup':

C:\Documents and Settings\BORIS\Рабочий стол\aktual_projekts_2019\mino_3/mino_3.ino:27: undefined reference to `ptr_fn_var'

C:\Documents and Settings\BORIS\Рабочий стол\aktual_projekts_2019\mino_3/mino_3.ino:27: undefined reference to `ptr_fn_var'

C:\Documents and Settings\BORIS\Рабочий стол\aktual_projekts_2019\mino_3/mino_3.ino:29: undefined reference to `ptr_fn_var'

C:\Documents and Settings\BORIS\Рабочий стол\aktual_projekts_2019\mino_3/mino_3.ino:29: undefined reference to `ptr_fn_var'

C:\Documents and Settings\BORIS\Рабочий стол\aktual_projekts_2019\mino_3/mino_3.ino:31: undefined reference to `ptr_fn_var'

C:\DOCUME~1\BORIS\LOCALS~1\Temp\ccDwyKZy.ltrans0.ltrans.o:C:\Documents and Settings\BORIS\Рабочий стол\aktual_projekts_2019\mino_2/mino_2.ino:31: more undefined references to `ptr_fn_var' follow

collect2.exe: error: ld returned 1 exit status

exit status 1
Ошибка компиляции для платы Arduino Nano.


а ежели обратно возвернуть будет выдано:
"...
Скетч использует 1778 байт (5%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 236 байт (11%) динамической памяти, оставляя 1812 байт для локальных переменных. Максимум: 2048 байт.
..."

Воть таки делы...
:roll:
Посему и изголяж над "с потолка взятыми" наборами исходника - просматриваю чего и как отрабатывает "на заметку".
Надо ж возможности компилятора для "многофайловиков" уточнить. Вдруг пригодится...
8)

Re: Котуинко

Вт ноя 05, 2019 11:34:07

Надо ж возможности компилятора для "многофайловиков" уточнить. Вдруг пригодится...
8)
Надо следовать стандартам языка, потому что компиляторы им тоже следуют. Так жизнь намного проще станет.

Re: Котуинко

Вт ноя 05, 2019 13:05:55

Стандарты без практики мертвы.
Тем более, если возникает необходимость чего-нить интересненького замутить.
У ассемблера таки возможности побогаче оказываются.
8)
Ну и как вариант - возможности самой IDE проверить. Ибо там таки "сборна солянка".
:?
Да тех, кто со стандартным Си дело имел по вопросам примеров послушать.
:beer:

Кстати... вероятно таки АДУРИНА ЧУДАСЕЕТ...
:roll:
оставил незакомментированное определение
ptr_fn ptr_fn_var;
в заголовочнике главного файла
и
extern ptr_fn ptr_fn_var;
в заголовочнике, подключаемом ко всем "заинтересованным" - и...
собрался БЕЗ МАТЮКОВ
:shock:
Мало того еще и массив таким образом extern пропустил (а где матюк на "двойное определение"??)...
mino_4.zip
(5.72 KiB) Скачиваний: 248

Дома под макетку подгоню - гляну делает ли заданное в реале...
:facepalm:
Последний раз редактировалось BOB51 Вт ноя 05, 2019 13:33:16, всего редактировалось 1 раз.

Re: Котуинко

Вт ноя 05, 2019 13:08:08

BOB51, никто не пишет extern для функций! Их объявления в этом не нуждаются.
Другое дело - переменные, потому что объявление переменной без extern будет автоматически считаться определением с дефолтной инициализацией нулем!

Re: Котуинко

Вт ноя 05, 2019 13:36:56

Мне интересен случай, когда можно обойтись без "передачи указателя/ссылки на функцию параметрами функции".
При объявлении в одном файле, а использовании внутри какой-либо функции другого файла.
8)

УПСЬ...
а таки работает прожка...
(mino_4)
во железе...
:?
Надо будет чуток поотдыхашись сформулировать чего и как получилось...
(ТРОХ-ТИБИДОХ тому Си!!)
:evil:
:write:

Re: Котуинко

Вт ноя 05, 2019 18:04:47

BOB51 писал(а):"передачи указателя/ссылки на функцию параметрами функции"
переведите кто-нибудь мне: это о чем речь?

Re: Котуинко

Вт ноя 05, 2019 18:15:14

это кусманчик из Страуструпа
в оригинале я такого у него не наблюдаю :dont_know:

переведите кто-нибудь мне: это о чем речь?

Код:
typedef void (*ptr_fn)(void);

void semirandom_fun(){
    // чего-то тут есть
}

void toplevel_fun(ptr_fn nested_fun){
    nested_fun();
}

toplevel_fun(&semirandom_fun);
чот типа того

Re: Котуинко

Вт ноя 05, 2019 18:21:13

arkhnchul писал(а):чот типа того
я просто никак не могу понять, о чем тут можно СПРАШИВАТЬ? но вопрос был - а я не пойму, в чем он... файлы какие-то...

Re: Котуинко

Ср ноя 06, 2019 11:45:07

Ладно...
изначально (ino.h +ino.cpp) имеем
typedef void (*ptrf)(); // указатель на функцию
ptrf xptr[3][8]; // указатель на массив указателей на функцию
помимо основного файла есть еще минимум один файл (test.h +test.cpp), где внутри функции проводится модификация содержимого массива
void test()
{
xptr[1][3]=xfunc; // сама та xfunc может быть и в главном файле проекта и в текущем
}

ну и где-то в третьем файле (test2.h +test2.cpp) встречаем
void test2()
{
xptr[1][3](); // по задаче это применение функции xfunc, только задано позиционными номерами массива,
// а что конкретно там сидит в данный момент определяет test.h +test.cpp
}

дык вот...
Для такой ситуации надо сделать массив видимым во всех файлах (или передавать его параметрами)...
делаю общий для всех файлов проекта файлик dub.h
и включаю в него
typedef void (*ptrf)();
а далее
extern ptrf y_ptrf; // объявляю переменную указатель на функцию
extern ptrf xptr[3][8]; // объявляю двумерный массив
НО... extern ptrf xptr[3][8] это ж вроде не только объявление но и определение для массива?? (хоть и с префиксом extern)...
самое интересное дальше...
в файле ino.h (или в другом заголовочнике комплекта файлов проекта) нужно еще раз указать
ptrf y_ptrf; // объявление переменной указателя на функцию
ptrf xptr[3][8]; // объявление массива
вот тут меня и .... ибо иначе проект не компилируется, а повторное объявление ладно уж указателя...
но для массива?...
Однако ФАКЫТ....
т.е. компилятор считает
extern ptrf y_ptrf; // объявляю переменную указатель на функцию
extern ptrf xptr[3][8]; // объявляю двумерный массив
исключительно объявлениями, которые должны быть позже подкреплены определением данных переменных...
:roll:

Re: Котуинко

Ср ноя 06, 2019 11:54:52

В чем проблема то? Сначала выдумал, что объявление массива с extern почему-то должно быть и определением, потом опытным путем пришел к тому, что это таки просто объявление, что еще нужно?

Re: Котуинко

Ср ноя 06, 2019 12:05:32

Как-то уж...
extern заменяет определение на объявление для переменных тип которых ранее задан при помощи typedef?...
:dont_know:
Садизьм...
:(

Re: Котуинко

Ср ноя 06, 2019 12:30:59

Садизьм...

Всего-то нужно уяснить, что тип определенный при помощи typedef ничем не отличается от какого-нибудь int, о чем тут уже писали.
Последний раз редактировалось Reflector Ср ноя 06, 2019 12:40:08, всего редактировалось 1 раз.

Re: Котуинко

Ср ноя 06, 2019 12:38:21

extern никогда ничего не определяет!

Попробую по-русски и рабочекрестьянски пояснить.

typedef ааа это "есть такой тип ааа"

ааа var это "выделить память под переменную var типа ааа"

extern aaa var это "где-то выделена память под переменную var типа ааа"

Теперь эти "переводы с Си на русский" просто используйте для своих файлов.

Если компилятор видит extern, он не выделяет память, а готовит "место", куда линкер потом занесет реальный адрес выделенной памяти. Если ни в одном файле память не выделялась (т.е. все исходники видели только строчки со словом extern), компилятор прожует, но линкер подавится!

Re: Котуинко

Ср ноя 06, 2019 14:26:21

Надоть однако капушек... валерианково-спиртючих тяпнуть...
:beer:

Re: Котуинко

Сб ноя 09, 2019 19:01:43

Надоть однако капушек... валерианково-спиртючих тяпнуть...
:beer:

Может прекратишь поясничать и изображать шута и начнешь читать?
Ответить