вопрос относительно построения программы по модульному принципу
допустим в моем проэкте есть два модуля main.c
module_1.c
по общепринятым правилам в main.c я должен прописать хидер #include "module_1.h" в котором я должен обозначить прототипы ф-ций
1)зачем в данном случае вообще нужен хидер ? ведь все файлы которые есть в проэкте с расширением с при компиляции все-равно сливаются воедино
2) почему бы тогда в хидере не писать сразу все ф-ции целиком ?
FreshMan писал(а):
по общепринятым правилам в main.c я должен прописать хидер #include "module_1.h" в котором я должен обозначить прототипы ф-ций
1)зачем в данном случае вообще нужен хидер ? ведь все файлы которые есть в проэкте с расширением с при компиляции все-равно сливаются воедино
2) почему бы тогда в хидере не писать сразу все ф-ции целиком ?
#include "module_1.h" выполняется препроцессором и вызывает вставку всего содержимого файла "module_1.h" в компилируемый файл. Если Вы опишите в "module_1.h" функции полностью, а не только прототипы, то файлы скомпилятся, однако при линковке Вы получите сообщение об ошибке (что-то типа "функция с именем бла-бла объявлена несколько раз"). Это, если хидер включен в несколько модулей программы.
Поэтому, делается так: пишем функции в отдельном модуле - файле xxx.c, затем создаем хидер (xxx.h), содержащий прототипы функций, которые мы хотим использовать в других модулях, а в самих модулях делаем включение #include "xxx.h".
Включение нужно для того, чтоб компилятор понял какие именно параметры будут в функции, которая позднее будет подлинкована из других модулей. Можно вместо хидера писать в каждом модуле описание прототипа функции, например extern int my_blackbox(int a);(extern можно не писать для большинства компиляторов).
Еще оди совет: в хидерах используйте условное объявление типа #ifndef _MODULE_H_ #define _MODULE_H_ ... содержимое хидера ... #endif
Пример:
#ifndef __FPGA_CONF_H
#define __FPGA_CONF_H
#include "stm32f4xx.h"
#define FPGA_INIT_CYCLE 50 /* extra DCLK cycles while initialization is in progress */
#define FPGA_RECONF_COUNT_MAX 5 /* #auto-reconfiguration when error found */
uint8_t fpga_load(void);
#endif /* __FPGA_CONF_H */
Это позволит избежать ошибок компиляции, если хидер включен в цепочку несколько раз. Такое бывает, если хидер включен в другие хидера... Короче используйте подобный скелет во всех хидерах, это сократит количество предупреждений и ошибок компиляции.
coredumped писал(а):Это, если хидер включен в несколько модулей программы.
а если он включен только в один модуль ?
если мой проэкт имеет только один модуль, ну окромя главного(main), то тогда можна прямо в хидере описывать полностью ф-ции ?
то тогда можна прямо в хидере описывать полностью ф-ции ?
Можно. Но не стоит так делать - кто знает, что Вы захотите с этими файлами сделать потом... Вообще обычно модули пишут в частности и для того, чтобы использовать код повторно.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
coredumped писал(а):Еще оди совет: в хидерах используйте условное объявление типа #ifndef _MODULE_H_ #define _MODULE_H_ ... содержимое хидера ... #endif
Это все правильно только чувак задал вопрос зачем они вообще нужны эти модули.
Вот ответ
YS писал(а):Вообще обычно модули пишут в частности и для того, чтобы использовать код повторно.
Так сказать для уменьшения времени разработки и тестирования программ. То есть если какая то полезная функция будет написана внутри основного файла будет очень трудно вынести данный код из общей массы. А так легко использовать модуль, который создан для выполнения одной конкретной задачи.
Так же создание отдельных файлов позволяет компилировать их отдельно, что так же позволяет сократить время разработки больших проектов. Не прибегая к полной компиляции.
Это было по первому вопросу вот еще в Вики статья
А по второму вопросу немного другая тема Вот статья
Здравствуйте коты, разбираюсь с подключением AVR по юсб, нашел отличный проект, но теперь не могу разобраться с программой на стороне компа, в проекте есть Dll библиотека и пользовательская программа в качестве примера, но они на Delphi, а я пишу на с++ и дельфи вообще не знаю. В проекте упоминается, что данную Dll можно использовать и для с++, подскажите пожалуйста как это делается.
Вот ссылка проекта http://www.gaw.ru/html.cgi/txt/app/micr ... AVR309.htm, там же в конце все файлы.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Спасибо, но тот, про который я говорю считаю лучшим, потому что там реализована сразу куча функций, не переделывая прошивки я могу делать на одном микроконтроллере конечное устройство и, самый главный плюс, здесь есть примеры всех этапов программирования от железячки до конечного пользователя. Просто я сейчас делаю курсовую, мне нужно разработать драйвер, драйвер я худо-бедно разобрал полностью, а вот dllку к нему освоить не получается никак, повторюсь в дельфи я полный 0.
http://forum.sources.ru/index.php?showtopic=248068
здесь находится h файл для загрузки этой длл.
Но на месте препода я бы это не принял - тема умерла лет так 10 назад. Ну скажем, утратила актуальность
Когда мега работает с юсб, она больше практически ни на что не отвлекается - да и делает это достаточно криво. Сейчас полно дешевых мк с аппаратным блоком юсб.
Большое спасибо! Я с вами не спорю, я все собираюсь начать осваивать stm32,там и юсб и сами они посовременнее, но постоянно что-то отвлекает. На счет принял бы или нет препод, то почему нет, ведь задача стоит научиться писать драйверы, а как работает все что выше или ниже его - без разницы, это уже просто моя личная любознательность. Просто Вы не представляете в каком отсталом месте я учусь и изначально мне давали задание написать драйвер консоли для дос на ассемблере, я подумал что если уж тратить время, то на что-то хоть немного полезное и интересное. Если Вас не затруднит, можно примерчик вызова любой функции из этой библиотеки, а то везде натыкаюсь на примеры с использованием lib? И еще вопрос: по ссылке что вы дали речь идет о старой и новой версии данной dll, файл .h там как я понял к старой, а dll у меня новая, нужно мне изменять файл .h или так работать тоже будет? Или я вообще что-то не так понял?
Rомпилятор(IAR) ругается
Error[Pe040]: expected an identifier C:\STM32\W5100 v12(trap list)\main.c 114
Error[Pe144]: a value of type "int" cannot be used to initialize an entity of type "List_IP_PORT" C:\STM32\W5100 v12(trap list)\main.c 114
Пытаюсь разобраться в чём отличия обращения к элементам структуры через точку или стрелочку. Пока только одна мысль что через стрелочку можно структуру наложить на массив а через точку нет.
С приведением типов указателей надо быть осторожным. Элементы в структуре могут быть расположены с выравниванием и например List_IP_PORT.n может занимать не один байт, как задумывалось, а два. Поэтому если идет разбор потока байт, структуру List_IP_PORT следует определить с атрибутом __packed или подобным. А еще могут быть проблемы с выравниванием доступа к памяти процессора, об этом надо тоже не забывать.
В Вашем случае List_IP_PORT это тип, определенный через typedef. Соответственно, ему ничего нельзя присвоить. На доступном примере: это все равно, что написать int=2.
Как сказали выше, надо объявить переменную этого типа и использовать ее.
BorisSPB писал(а):С приведением типов указателей надо быть осторожным
В данном примере это не сильно важно но вот в другой структуре это критично. Но пока всё работает стабильно если что отвалится буду знать куда копать.(Я так понял что отвалится она может при смене компилятора или если в настройках выравнивания структуры похимичить ?)
И ещё не большой вопросик появился если надо передать в функцию много параметров штук 10 как это сделать правильно ?
Причём из этих 10 штуки 2-3 это массивы. Если всё в лоб то она большая сильно становится.
По пробовал эти все параметры запихать в структуру и в функцию только структуру передавать. Но всё равно перед функцией
все эти данные объявить. Хотя мне так больше нравится.
если содержимое массива community меньше 20 к примеру 10 занимается остальное нули. как сделать что бы вместо нулей была переменная n ? думал сделать вот такое но адрес community почему-то 0.
Если размер массива меняется, то логично использовать указатель, как Вы написали, однако указателю нужно присвоить значение - адрес массива. Те сначала нужно выделить память под массив, а потом присвоить адрес этой памяти массиву. Механизмы выделения-освобождения памяти отличаются от операционной системы, под которую пишется программа. Вот пример под Linux с Вашей структурой
Таким образом мы имеем дело с динамически выделяемой памятью или "динамической памятью" (еще используется термин "куча").
Для МК тоже есть реализации упрощенного управления динамической памятью, однако в отличии от "взрослых" ОС память может выделяться из заранее отведенной области и только непрерывным блоком. Обсуждение механизмов управления динамической памятью заслуживает целой книги.
Можете погуглить словам malloc, heap.
PS: если Вы имеете дело с маленьким МК и памяти хватает, проще выделить статический массив с запасом, чем возиться с перераспределением памяти. Тут делема: производительность - расход памяти. Я советую использовать танцы с динамическим распределением, если памяти не хватает (в случае МК, естественно). Есть много методов оптимизации использования памяти, но все они приводят к снижению скорости выполнения программы.