УВЫ... иначе я б тем садомазохизмом не занимался... ни в случае со "скобочной" формой, ни через тип, объявленный как 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;// в данном месте не выполняется компилятором
В случае однофайловика особо на такие "выкрутасы" и надобности не возникает. Да и чаще "передачу параметрами" выполняют.
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'; } ..."
это кусманчик из Страуструпа...
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 байт. ..."
Воть таки делы... Посему и изголяж над "с потолка взятыми" наборами исходника - просматриваю чего и как отрабатывает "на заметку". Надо ж возможности компилятора для "многофайловиков" уточнить. Вдруг пригодится...
Стандарты без практики мертвы. Тем более, если возникает необходимость чего-нить интересненького замутить. У ассемблера таки возможности побогаче оказываются. Ну и как вариант - возможности самой IDE проверить. Ибо там таки "сборна солянка". Да тех, кто со стандартным Си дело имел по вопросам примеров послушать.
Кстати... вероятно таки АДУРИНА ЧУДАСЕЕТ... оставил незакомментированное определение ptr_fn ptr_fn_var; в заголовочнике главного файла и extern ptr_fn ptr_fn_var; в заголовочнике, подключаемом ко всем "заинтересованным" - и... собрался БЕЗ МАТЮКОВ Мало того еще и массив таким образом extern пропустил (а где матюк на "двойное определение"??)...
BOB51, никто не пишет extern для функций! Их объявления в этом не нуждаются. Другое дело - переменные, потому что объявление переменной без extern будет автоматически считаться определением с дефолтной инициализацией нулем!
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Мне интересен случай, когда можно обойтись без "передачи указателя/ссылки на функцию параметрами функции". При объявлении в одном файле, а использовании внутри какой-либо функции другого файла.
УПСЬ... а таки работает прожка... (mino_4) во железе... Надо будет чуток поотдыхашись сформулировать чего и как получилось... (ТРОХ-ТИБИДОХ тому Си!!)
Ладно... изначально (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]; // объявляю двумерный массив исключительно объявлениями, которые должны быть позже подкреплены определением данных переменных...
В чем проблема то? Сначала выдумал, что объявление массива с extern почему-то должно быть и определением, потом опытным путем пришел к тому, что это таки просто объявление, что еще нужно?
ааа var это "выделить память под переменную var типа ааа"
extern aaa var это "где-то выделена память под переменную var типа ааа"
Теперь эти "переводы с Си на русский" просто используйте для своих файлов.
Если компилятор видит extern, он не выделяет память, а готовит "место", куда линкер потом занесет реальный адрес выделенной памяти. Если ни в одном файле память не выделялась (т.е. все исходники видели только строчки со словом extern), компилятор прожует, но линкер подавится!
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения