COKPOWEHEU писал(а):но пнуть явным образом все равно лучше.
Так явным образом и было, надо было только заглянуть под спойлер.

COKPOWEHEU писал(а):С объявлениями переменных вопрос сложный. Если уж делить логику на несколько файлов, стоит минимизировать количество связей, а это тоже непросто. Кстати, именно в данном случае может иметь смысл обойтись без *.c-файла, оставив всю логику в заголовке. Как я уже говорил, это применимо только когда этот заголовок подключается только в один файл исходного кода.
Ну, раз уж вы оба решили забежать вперед, приведу для
Мikа свои пояснения.
Итак, препроцессор, встретив
#include, подставляет вместо него все содержимое указанного в нем файла в тот файл, где он (
#include) встретился. Из этого есть два основных следствия:
1. Можно разделить все функции и переменные .c-модуля на локальные и глобальные, и внести объявления глобальных в .h-файл, что обеспечит видимость этих объявлений в каждом .c-файле, имеющем соответствующий
#include.
2. Необходимо позаботиться о том, чтобы многократное включение .h-файла не приводило к многократному созданию одинаковых функций и переменных в каждом .c-файле с таким
#include'ом. С функциями это делается просто - у них объявление отличается от реализации отсутствием блока кода (func(); вместо func(){...;}). С переменными есть разные подходы. Один из самых распространенных заключается в том, что переменные объявляются в .h-файле с модификатором
extern, что равносильно объявлению без создания. Но тогда приходится давать второе объявление этих переменных в .c-файле модуля, что ухудшает модифицируемость исходного кода, так как программист должен помнить о необходимости
синхронного изменения объявлений переменных в .c и .h частях модуля. Одно время я выходил из положения таким образом:
Код: Выделить всё
sr595.c ----------
// сообщаем, что текущий файл - это исходник модуля:
#define __SR595_MOD__
// теперь включаем объявления модуля:
#include "sr595.h"
---------- sr595.c
sr595.h ----------
...
#ifndef __SR595_MOD__
#define __Vstorage extern
#else
#define __Vstorage
#endif
__Vstorage unsigned char Encoder_State;
__Vstorage signed char Encoder_Summ;
__Vstorage unsigned char Encoder_NewState;
...
---------- sr595.h
Теперь объявления переменных модуля существуют в единственном экземпляре и их редактирование не может привести к разнобою. Правда, необходимо будет определять флаг модуля перед
#include'ом, но это можно забыть сделать только один раз для каждого модуля - до первой жалобы линкера на отсуствие этих переменных в объектниках.

А вот насчет помещения кода в заголовочные файлы ("
в данном случае может иметь смысл обойтись без *.c-файла, оставив всю логику в заголовке") - я принципиально против этого. Всегда может понадобиться превратить такой модуль в нормальный, пригодный для многократного включения... и тогда придется, чертыхаясь на самого себя за лень, разделять объявления и реализацию между .h- и .c-файлами. Особенно громко приходится чертыхаться, когда это доводится делать спустя некоторое время после реализации модуля, когда её детали уже успели подзабыться.

- Из овощей я больше всего люблю пельмени... © Соседский Мальчик