|
Как соблюсти ПРАВИЛА ХОРОШЕГО ТОНА при написании программ на Си?, (Как компоновать проект? Что оставлять в xxx.c, а что в xxx.h ?) |
|
|
|
May 4 2009, 18:14
|

Местный
  
Группа: Свой
Сообщений: 208
Регистрация: 6-07-04
Из: Полтава
Пользователь №: 279

|
Написал было объемистое предисловие, но Фаерфокс глюкнул и оно исчезло, поэтому обойдусь без него.
Перешел с ассемблера на Си, создал ряд проектов, работающих, но так и не получил четкого представления о том, как нужно оформлять программу на Си по ПРАВИЛАМ. Может сказалась былая практика программирования на Фортране и Паскале. Наибольшее непонимание у меня вызывает то, что нужно оставлять в xxx.c, а что выносить в xxx.h. Виной тому - ужасная чересполосица в куче разных сторонних проектов, которые довелось разбирать в процессе освоения Си. В одних проектах водораздел один, в других - совсем иной. И даже в атмеловских аппноутах - тоже полный разнобой.
Пользуюсь IAR EWAVR-ом.
Вот пара примеров написания программ, с которыми встречался: Имеются: основной модуль - xxx.c, хедер к нему - xxx.h, пара модулей - yyy.c, zzz.c и хедеры к ним yyy.h, zzz.h.
Первый вариант организации проекта. В проект подключен основной модуль xxx.c, в котором в самом начале подключен при помощи директив #include необходимый набор стандартных библиотек, хедер xxx.h, а также два дополнительных модуля yyy.c и zzz.c. В самих модулях yyy.c и zzz.c при помощи этих директив подключены yyy.h и zzz.h соответственно. В основном модуле располагается главная программа и набор функций, относящихся непосредственно к ней. В хедере располагаются глобальные определения, описания глобальных переменных и констант, а также прототипы функций основного модуля. В дополнительных модулях располагаются функции модулей, а в хедерах дополнительных модулей располагаются определения, переменные, константы и прототипы, касающиеся этих модулей.
Во втором варианте организации проекта дополнительные модули включены в проект подобно основному. В основном же модуле при помощи #include подключены yyy.h и zzz.h. Также они подключены с помощью этой директивы и в yyy.c и zzz.c соответственно.
Оба проекта полностью рабочие, потому как в конечном счете все полностью завязано и в первом и во втором случае.
Встречался также с вариантами написания программ, где, например, описания переменных вынесены в ***.c вместо ***.h.
Имею два конкретных вопроса:
1. КАК нужно подключать в проект модули и хедеры согласно ПРАВИЛ ХОРОШЕГО ТОНА написания программ на языке Си? 2. ЧТО нужно согласно тех же ПРАВИЛ выносить в ***.h, а что оставлять в ***.c?
Четкого, внятного, однозначного ответа я так и не нашел. Хотелось бы узнать мнение уважаемого сообщества.
PS: Конечно, можно компоновать как попало, имея в результате полноценный рабочий код, но вопрос в том, как общепринято ПРАВИЛЬНО это выполнять?
|
|
|
|
|
May 4 2009, 19:22
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
C Си нет ничего проще. В хидерах только прототипы функций, переменных, структур, константы, макросы. Крайне редко ввиде исключения могут быть, например, функции форсируемые в качестве инлайновых. Никакие *.c никогда через include не включаются - на то есть линкер. Стандартным примером разумной организации являются системные хидеры.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 4 2009, 19:23
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(kv_addr @ May 4 2009, 21:14)  Первый вариант организации проекта. В проект подключен основной модуль xxx.c, в котором в самом начале подключен при помощи директив #include необходимый набор стандартных библиотек, хедер xxx.h, а также два дополнительных модуля yyy.c и zzz.c. Обычно С файлы через #include не подключают. Объясню далее. Видимо, это ваш второй вариант. Цитата Во втором варианте организации проекта дополнительные модули включены в проект подобно основному. В основном же модуле при помощи #include подключены yyy.h и zzz.h. Также они подключены с помощью этой директивы и в yyy.c и zzz.c соответственно. ... 1. КАК нужно подключать в проект модули и хедеры согласно ПРАВИЛ ХОРОШЕГО ТОНА написания программ на языке Си? 2. ЧТО нужно согласно тех же ПРАВИЛ выносить в ***.h, а что оставлять в ***.c? Все моё ИМХО. Модули нужно подключать, подключив хидеры xxx.h; линкеру дать инструкции подключить объектные файлы полученные из сырцов xxx.c. Header - это в первую очередь описания интерфейсов. В понятие интерфеса входят методы, глобальные переменные, константы (для С++, в С с константами хуже, обычно там define). Почему в хидерах не пишут код? Дело в том, что в случае изменения кода в .с файле пересобирается этот файл. А в случае изменения в хидере пересобираются еще и все модули, которые включают этот хидер (зависимые модули). То есть в хидере - то, что видно снаружи. В сырцах - все остальное.
|
|
|
|
|
May 4 2009, 19:45
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата Никакие *.c никогда через include не включаются - на то есть линкер. Мне кажется, слишком категорично. Иногда делаю отдельный .c-инклуд для уменьшения видимых размеров исходника с сохранением одной единицы компиляции. Иногда выношу константы в отдельный .c-файл, когда эти константы static и генерируются отдельным софтом в пребилде. Конечно, можно обойтись без этого, но мне иногда так удобнее. Собственно, это больше издержки отсутствия пространств имен в plain c. Вспомнилось... Третий турбопаскаль под CP/M умел собирать код под всю память только при инклуде исходников с диска и компиляции на диск. Иначе не лезло  Но это так, ностальжи...
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
May 4 2009, 19:55
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Rst7 @ May 4 2009, 22:45)  Мне кажется, слишком категорично. Исключения только подтверждают правило  . Я тоже исключение приводил. Ну а "единицу компиляции" уже можно многие компиляторы просить обеспечить вне зависимости от количества составляющих ее файлов. Цитата Иногда выношу константы в отдельный .c-файл, когда эти константы static и генерируются отдельным софтом в пребилде. А в этом приеме где противоречие с невключением файлов с исходниками по include?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 4 2009, 20:14
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата Исключения только подтверждают правило Ну Вы же грамотный человек, зачем употребляете нелогичную фразу  Исключения только опровергают правило (или ограничивают область применимости, это если с точки зрения физики)  Да и многофайловая компиляция - недавнее приобретение  А второй пример - это я к тому, что подключается на этапе препроцессора. Хоть и .с. Повторюсь - в большинстве случаев это издержки отсутствия namespace. Гм, мне кажется, или движок форума шибко вумный, приклеивает точку к предыдущему слову?
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
May 4 2009, 22:46
|

Местный
  
Группа: Свой
Сообщений: 208
Регистрация: 6-07-04
Из: Полтава
Пользователь №: 279

|
TNX. Где-то так и предполагал, что второй вариант будет более правильным и логичным. Следующий вопрос. Каков общепринятый порядок расположения компонентов хедера? Это на мой взгляд далеко не праздный вопрос. Хотелось бы впредь выработать четкие правила создания логично скомпонованных удобочитаемых и удоборазбираемых программ. Для своего потребления я могу программу наклепать как угодно, все равно она будет работать согласно установленного алгоритма, но для других она будет выглядеть диковато и не удобоваримо. Я не совсем новичок в программировании, пописывал программы еще когда вычислительные машины были большими и очень большими.  Но в основном я - схемотехник, поэтому это было как бы приложением к основной работе. Когда появились "писюки", писать программы на них как-то не приходилось. К микроконтроллерам приступил наперевес с ассемблером. Но когда задачи усложнились, писать на ассемблере стало чрезмерно времязатратным. Поэтому, преодолев некоторые фобии, решил освоиться с Си. Конечно, embedded C весьма специфичен, но вроде уже как освоился и программу "чувствую". Но, понимая, что это немаловажно, также решил упорядочить стиль создания программ, дабы писАть  не только под себя. Вот, собственно говоря, это и есть основной причиной моих вопросов. Кстати, хотя по Си перечитал литературы достаточно, но так и не нашел четких ЛАКОНИЧНО изложенных правил. Может кто подскажет такой источник. Предпочтительно - русскоязычный. Это не значит, что по-английски не читаю, но предпочитаю родной язык, как более удобный в любом случае.
|
|
|
|
|
May 5 2009, 07:00
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Rst7 @ May 4 2009, 23:46)  Можем пойти в оффтоп обсудить, там есть кому подхватить, страниц на 20-30  Нет  там любая тема всегда к одному и тому-же сводится  . Я тут недавно эксперимента ради объединил темы про "опель" и "гомосексуализм" в одну и НИЧЕГО НЕ ИЗМЕНИЛОСЬ  . Ну а с подтверждением правил на самом деле все логично - если признается существование единого общего правила, то тогда все отклонения от него являются ИСКЛЮЧЕНИЯМИ из правила, что самим своим названием "исключение", заметьте "исключение", а не "правило номер 2" подтверждает наличие "правила".
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 5 2009, 07:36
|

инопланетянин
  
Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832

|
Цитата(kv_addr @ May 5 2009, 02:46)  Следующий вопрос. Каков общепринятый порядок расположения компонентов хедера? Это на мой взгляд далеко не праздный вопрос. Хотелось бы впредь выработать четкие правила создания логично скомпонованных удобочитаемых и удоборазбираемых программ. Для своего потребления я могу программу наклепать как угодно, все равно она будет работать согласно установленного алгоритма, но для других она будет выглядеть диковато и не удобоваримо. о говоря, это и есть основной причиной моих вопросов. Я где-то такую последовательность видел.. но точно не вспомню где.. Я обычно делаю так: Код #ifndef _XXX_H_ #define _XXX_H_ 1. макросы, константы 2. определения типов структур, объединений 3. экспортируемые переменные 4. экспортируемые функции #endif Также я во всех проектах создаю файл includes.h, который включен во все *.с, больше никаких include в с-файлах.. А includes.h выглядит примерно так: Код #ifndef _INCLUDES_H_ #define _INCLUDES_H_ /* ******************************************************************************** * Project Includes ******************************************************************************** */ #include "main.h" #include "Timer0.h" #include "Timer1.h" #include "io_ports.h" #include "sync.h" #include <stdlib.h> #include <string.h> #include <util/atomic.h> #include <util/delay.h> #include <avr/power.h> #include <avr/sfr_defs.h> #include <compat/deprecated.h> #include <avr/eeprom.h> #include "avrport.h" #include "config.h" #include "hwclock.h" #include "keys.h" #include "led.h" #include "nnspi.h" #include "ntrxdil.h" #include "ntrxiqpar.h" #include "ntrxranging.h" #include "ntrxtypes.h" #include "ntrxutil.h" #include "OffstMapInit.h" #include "usart.h" #include "rtc.h" #include "usart_my.h" #include "usart_protocol.h" #include "io_ports.h" #include "led.h" #include "ascold.h" #include "ext_flash.h" #include "soft_spi.h" #include "i2cmaster.h" #include "temp.h" #include "adc.h" #include "soft_reset.h" #include "eeprom_map.h" #include "gui_fonts_defs.h" #include "fonts.h" #include "gui.h" #include "lcd.h" #include "simple_font_digit.h" #endif Цитата(kv_addr @ May 5 2009, 02:46)  Кстати, хотя по Си перечитал литературы достаточно, но так и не нашел четких ЛАКОНИЧНО изложенных правил. Может кто подскажет такой источник. Предпочтительно - русскоязычный. Это не значит, что по-английски не читаю, но предпочитаю родной язык, как более удобный в любом случае. Макконелл, Совершенный Код.. достаточно интересная книга, много всяческих небольших ньюансов, про которые не пишут в классических учебниках
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|