реализация заголовочных файлов C?

#c #file #header #system #implementation

#c #файл #заголовок #система #реализация

Вопрос:

Я изучал язык C и просматривал некоторые заголовочные файлы в каталоге Linux, /usr/include такие stdio.h , stdlib.h и т.д. Что меня действительно беспокоило, так это то, что я вижу, что все функции определяются с помощью extern ключевого слова, что означает, что они объявляются только без какого-либо определения, такого как:

 extern FILE *fopen (__const char *__restrict __filename,
                    __const char *__restrict __modes) __wur;
  

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

Комментарии:

1. Заголовки, особенно системные заголовки, не подходят для изучения basic C. Сначала изучите язык, не беспокоясь о злоупотреблениях языком, подобных тому, что там используется.

2. Реализации находятся в библиотеке, о чем вам скажет любой базовый текст на языке C. … «внешняя переменная» — вы имеете в виду «внешнее ключевое слово».

3. Обратите внимание, что extern ключевое слово является чисто посторонним в объявлениях функций. Все, что это делает, это тратит впустую дисковое пространство и время синтаксического анализа, когда компилятор анализирует его. Конечно, имена комментариев и аргументов тоже делают это..

4. Почему вы не выбираете ответ в качестве правильного ответа?

Ответ №1:

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

Как только компилятор завершен, вызывается компоновщик. Вот где происходит волшебство. Компоновщик определяет, какая библиотека имеет фактическую реализацию функции. В этом случае это, вероятно, будет в стандартной библиотеке (называемой libc в некоторых системах), которая загружается автоматически. Компоновщик делает свое дело, и ваши вызовы этой функции затем обрабатываются библиотекой.

Если прототип существует, но реализация не может быть найдена, вы получаете ошибку компоновщика (что-то вроде «неопределенный символ»). Если прототип отсутствует, код будет скомпилирован, но вы, вероятно, получите предупреждение об этом (спасибо Джиму Балтеру за информацию об этом).

Комментарии:

1. «Аналогично, если функция не определена, но реализация существует, вы получите ошибку компилятора» — Неверно. Реализация — это определение. Если вы имеете в виду «необъявленные», объявление функций не требуется. «неопределенная ссылка на …» — Для функций такого сообщения об ошибке нет. Вы получите (другую) ошибку, если использование не согласуется с неявным объявлением функции.

2. P.S. «Если функция определена, но реализация не может быть найдена» — Это должно гласить «Если на функцию есть ссылка , …»

3. Лучше, но, опять же, для отсутствующих прототипов такой ошибки нет — прототипы не нужны; пожалуйста, проверьте свои утверждения. И оба утверждения по-прежнему неверны: простое наличие прототипа не приводит к созданию сообщения компоновщика; вы должны фактически ссылаться на функцию.

4. @Джим Балтер: Хм, я думал, что понял. Я вернулся и создал небольшую тестовую программу, и, клянусь богом, вы правы. Оба раза я получал ошибку, до этого момента я не осознавал, что в обоих случаях ошибку выдавал компоновщик. Виноват.

5. @KorayTugay в любом файле «.c», при условии, что этот результирующий файл «.o» включен в фазу компоновки. Эти имена символов являются глобальными.

Ответ №2:

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

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

Если вы работаете в системе Linux, использующей gcc, вы можете найти эти файлы библиотеки в /usr/lib . libc.a обычно содержит основную часть функций стандартной библиотеки C (stdio, stdlib, string и т.д.). Математические функции хранятся отдельно в libm.a . При нормальных обстоятельствах gcc автоматически ссылается на /usr/lib/libc.a , так что вам не нужно беспокоиться об этом. Если вам нужно использовать функции математической библиотеки, вам нужно добавить -lm в командную строку ссылку на математическую библиотеку.

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

Комментарии:

1. @JimBalter говорит, что «Реализация — это определение». в комментарии выше?

2. @KorayTugay: это правильно — определение функции (то есть тело функции) является реализацией. Объявление — это интерфейс. Заголовочные файлы (обычно) содержат только объявление функции.

Ответ №3:

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