Если под «модулем» вы имеете в виду просто файл CPP, вы можете просто поместить декларацию и определение прямо в файл CPP.
Если это действительно функция, которая является внутренней только для этого файла .c, тогда да. Это должно помочь избежать загрязнения глобального пространства имен. Кроме того, я думаю, что компилятор может выполнить некоторые оптимизации с соглашениями о вызовах, если функция статическая, поскольку он не знает, что ни один другой исходный файл не должен знать, как ее вызывать. Это действительно применимо только к c, потому что, как отмечали другие, у C++ есть пространства имен для решения этой проблемы.
Для C++ лучше, чем static, - поместить его в безымянное (анонимное) пространство имен. Это предпочтительный способ предотвратить загрязнение глобального пространства имен.
namespace {
void myLocalFunction() {
// stuff
}
}
Еще одно преимущество анонимных пространств имен состоит в том, что вы все еще можете передавать адрес объектов внутри него в шаблоны, поскольку они все еще имеют внешнюю связь.
+1, дополнительную информацию можно найти в этой ветке SO: stackoverflow.com/questions/154469/…
Недостаток в том, что это не полезно в C. Вопрос был о c / C++
Я не заметил тега C. Это решение только для C++.
Не совсем устарел, он продолжит работать. Но пространства имен - лучший способ, который рекомендуется для любого нового кода.
Одна проблема с анонимными пространствами имен: у некоторых отладчиков возникают проблемы с установкой точек останова по имени функции, когда вы их используете.
@kshahar: static не является устаревшим. Тот, кто предлагал это, довольно быстро понял / получил ответ, насколько они были неправы, и static остается первоклассной функцией, как и всегда.
Я думаю, что C и C++ имеют разные ограничения относительно static: в C у вас нет пространств имен, а файлы .c - это ваши модули, поэтому действительно очень важно поместить все непубличные функции как статические, чтобы предотвратить ошибки!
В C++ вы должны использовать анонимное пространство имен, например:
// foo.cpp
namespace
{
class Core { ... };
void InternalFandango(Core *);
}
void SomeGloballyVisibleFunction()
{
InternalFandango(&core);
}
Преимущество: это применимо и к объявлениям структур / классов. В C просто отметьте функции «статическими». Нет ничего против использования «static» в C++, но я научился отдавать предпочтение пространству имен, поскольку это единая концепция, которая работает для всех объявлений.
Да - это неправильно - вы должны отредактировать свой ответ, чтобы исправить это - иначе вас могут отклонить!
Единственное потенциально полезное свойство, которое я могу придумать для этого использования "static" в C++, которое анонимные пространства имен не предоставляют, это то, что в GCC есть предупреждение, которое вы можете включить для неиспользуемых статических функций (форма мертвого кода) . Вы не получите этого для неиспользуемых функций в анонимных пространствах имен, поэтому в маловероятном случае, когда вы хотите, чтобы компилятор сообщал вам, когда вы прекращаете использовать функцию, сделайте это таким образом.
Очень похожий вопрос был задан перед здесь. Существует пример крайнего случая, когда объявление функции статической приводит к поведению, совершенно отличному от поведения безымянной функции пространства имен. См. Мой отвечать.
Много было о деталях реализации и не слишком много о концепции.
Ограничение объема переменной / функции и т. д. Действительно является хорошей практикой. Это основная концепция объектно-ориентированного дизайна - вы хотите, чтобы конфиденциальность оставалась конфиденциальной. Таким образом ваш интерфейс станет чище, а обслуживание кода станет проще. И вы не найдете ни одного дня, чтобы изменение чего-то, что вы считали частной компиляцией, сломалось, потому что кому-то в другой части проекта понравилась ваша функция и он решил ее использовать.
В C я делаю все - функции и переменные - статическими в области видимости файла, пока не смогу продемонстрировать, что они необходимы вне файла. Я сделаю вещи статичными внутри функции, если только эта функция будет их использовать, и они не будут слишком большими. В принципе, если объявление больше, чем остальная часть функции, я могу поместить объявление вне функции. И, конечно же, в исходном файле есть заголовок для общедоступных сервисов.
Следует быть осторожным при использовании static в функциях в отношении повторного входа и многопоточности.
@ Илья: согласен. Я стараюсь делать вещи тоже константными, когда это возможно. Так получилось, что большая часть моей работы не связана с потоками. Однако я стараюсь избегать глобальных переменных; Я также стараюсь избегать статических переменных как в области файлов, так и в функциях, где это возможно.
В коде C сделайте ваши функции статическими по умолчанию. Делайте нестатические функции и объявления .h только для функций, которые потребуются другим модулям.
В коде C++ поместите те функции, которые являются локальными для файла, в анонимное пространство имен и, сделайте их статическими. По крайней мере, в компиляторе GNU это приведет к получению наилучшего и наименьшего кода, потому что никакая функция не будет написана, если все использования встроены. Если вы хотите, чтобы он был встроенным, то, конечно, пометить его встроенным даже лучше, чем статический.
Я не знаю, почему g ++ вообще записывает тела не вызываемых функций, которые находятся в анонимных пространствах имен, в вывод, но это так. Кажется, также появляются функции со скрытой видимостью; помечены как скрытые символы, но по-прежнему создают неиспользуемые блоки кода в объектном файле. GCC, вероятно, не понимает, что код в таких случаях не нужен. Или я чего-то упускаю, всегда возможно.
То, что вы описали, должно быть, было ошибкой GCC, которую я не могу воспроизвести. Хотя это могло быть полезной информацией для людей, использующих этот компилятор в тот момент, нет смысла экстраполировать это на общие рекомендации по использованию как namespace {, так и static. Правильный ответ - сообщить об ошибке, а не обременять свой и чужой код шаблонным кодом, который не имеет смысла с точки зрения языка.
Если вы используете GCC, вам следует взглянуть на флаг видимости (полное обсуждение см. В http://gcc.gnu.org/wiki/Visibility).
Он полностью скроет символы, а не помечает их как недоступные. Это уменьшает таблицу символов и помогает сократить время связывания.
Мало того, это открывает дверь для большего встраивания, если это то, что вам нужно.
В C++ вы бы объявили функцию частной следующим образом:
class MyClass
{
public:
void publiclyAccessibleFunction();
private:
void onlyAccesibleFromWithinTheClass();
int some_member_parameter;
};
Обратите внимание на функцию onlyAccesibleFromWithinTheClass().
OP говорил о модулях, т.е. отдельно скомпилированных исходных файлах и их заголовках, а не об объектах.
Согласовано. Как следствие, прототипы статических функций должны располагаться в верхней части файла .c, а не в файле .h.
Это на самом деле не мешает генерации внешнего символа, поэтому он все еще может конфликтовать с одним из другого «модуля».