Почему я должен объявлять статическую "приватную" функцию, когда я просто не могу поместить ее в заголовочный файл? - PullRequest
2 голосов
/ 05 апреля 2019

Я понимаю, что ключевое слово static используется для создания функций или переменных, которые являются "частными" для единицы перевода (исходного файла).

Однако, насколько я понимаю, чтобы убедиться, что конкретная функция или переменная не доступны извне файла .c, в котором он был объявлен, я могу просто не объявить его в соответствующий .h файл.

Например:

f.c

void public_func() {
    // ...
}

void private_func() {
    // ...
}

f.h

void public_func();

// no declaration of private_func

Так почему я должен также объявлять private_func как static? Это просто соглашение или оно имеет техническую выгоду по сравнению с тем, что просто не объявляет его в файле .h?

Ответы [ 3 ]

3 голосов
/ 05 апреля 2019

Проблема в том, что компиляторы работают на основе «единицы перевода», то есть один файл .c и все включенные в него файлы .h.Поэтому он традиционно не может обнаруживать конфликты имен во всем проекте.

Так что, если вы не сделаете это static, функция по умолчанию имеет «внешнюю связь».То есть, если у вас есть функция private_func, а другой модуль перевода в том же проекте использует то же имя, вы получите коллизии пространства имен во время компоновки и ошибок компоновщика.

Это также вопрос корректности - частные функции / переменныепросто не должны быть доступны извне, ни преднамеренно, ни случайно.

1 голос
/ 05 апреля 2019

Я понимаю, что ключевое слово static используется для создания функций или переменных, которые являются "частными" для единицы перевода (исходного файла).

Это правда.

Это просто соглашение или оно имеет техническое преимущество перед тем, как просто не объявлять его в файле .h?

Здесь есть технический момент.Когда компилятор выполняет свою работу, он создает объектный файл.Этот файл имеет таблицу символов, которая позже используется компоновщиком, когда компоновщик собирает программу из отдельных объектных файлов.static функции не попадут в эту таблицу, поэтому прямые ссылки на эту функцию из других объектных файлов завершатся с ошибкой «неразрешенная ссылка» на этапе компоновки.

Benefits?Что ж, вы сэкономите немного крошечного пространства в вашем объектном файле, этап компоновки пройдет быстрее, так как для обработки будет меньшая таблица.Но это достаточно мало, чтобы не иметь значения, если только мы не говорим о сложном случае тысяч функций с зацикленными именами.

Если у вас есть не-1017 * функция, и вы опускаете ее объявление взаголовочный файл, имя функции все еще попадает в таблицу символов.И если мне случится узнать объявление каким-либо образом (кроме как из заголовка), я все равно могу вызывать / ссылаться на функцию непосредственно из другого модуля перевода, ошибка компоновщика не произойдет.

0 голосов
/ 05 апреля 2019

Допустим, вы пишете библиотеку, которая состоит из нескольких файлов .c и .h. Клиенты вашей библиотеки должны будут использовать некоторые заголовочные файлы, чтобы использовать вашу библиотеку. Они должны видеть только публичные функции.

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

Таким образом, вы получите два типа объявлений:

Для клиентов вашей библиотеки

void public_func();

Для внутреннего использования

static void private_func();

Предпочтительно, частные и публичные объявления находятся в отдельных заголовочных файлах, и клиенты вашей библиотеки должны включать только заголовочные файлы с открытыми функциями.

...