Где определены функции в стандартной библиотеке C?

Меня не интересует исходный код, я хочу знать, как компилятор C (GCC) на самом деле находит функции. Например, когда препроцессор видит, что я включил stdio.h, где он ищет файлы, определяющие тела функций?

Изменить

Я, вероятно, также должен сказать, что использую Ubuntu 12.04, но если есть общий ответ, это тоже сработает.


person Tyler    schedule 07.03.2014    source источник
comment
Компилятору нужны только заголовочные файлы. Однако компоновщику нужны объектные или библиотечные файлы.   -  person Joey    schedule 07.03.2014
comment
связанные: stackoverflow.com/questions/11481154/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 18.04.2016


Ответы (5)


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

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

Посмотрите на http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html и обратите внимание на параметры -nostdlib и -nodefaultlibs. Вы можете использовать эти параметры, чтобы указать компоновщику gcc не включать стандартные файлы объектов библиотеки по умолчанию.

person Alex D    schedule 07.03.2014
comment
Таким образом компоновщик каждый раз автоматически включает объектные файлы, реализующие все функции стандартной библиотеки? Если да, то какой смысл связывать разные функции с разными заголовочными файлами, если они все равно включены? - person Tyler; 09.03.2014
comment
объектные файлы используются gcc компоновщиком. Файлы заголовков используются компилятором. Компилятору необходимо видеть заголовки, поэтому он знает сигнатуры функций и, таким образом, 1) может проверить тип кода и 2) может сгенерировать правильный код для передачи аргументов и получения возвращаемого значения. Почему они не поместили подписи для всех функций стандартной библиотеки в один заголовочный файл? Ну, во-первых, это было бы несовместимо со стандартом C, поскольку стандарт C фактически определяет, какими должны быть стандартные заголовочные файлы. Во-вторых, это замедлит время компиляции. - person Alex D; 09.03.2014
comment
Кроме того, @Tyler, компоновщик не включает объектные файлы из статической библиотеки, если они не нужны. Файл .a представляет собой проиндексированную библиотеку отдельных объектных модулей, и компоновщик будет включать только те, которые разрешают неопределенный символ (и некоторые из них могут ссылаться на новые неопределенные символы, поэтому он будет продолжать работать). В случае .so вся библиотека будет загружена во время выполнения, так что это неприменимо. - person greggo; 16.06.2015

gcc получает определения функций из библиотеки C. Вы можете определить путь, по которому gcc будет искать его по умолчанию, сказав:

ld --verbose | grep SEARCH_DIR

Это приводит к /usr/lib в моей системе.

Давайте попробуем выяснить, содержит ли библиотека символ стандартной функции, скажем, scanf:

nm -A /usr/lib/libc.so | grep scanf

Результаты включают в себя:

/lib/libc.so:0000000000042a90 T scanf

Рассмотрим небольшой пример:

#include <stdio.h>

int main() {
  printf("Hello World!\n");
  return 0;
}

Назовем его i.c:

$ gcc i.c              # Compile
$ ldd ./a.out          # Try to find dependencies
./a.out:
        -lc.12 => /usr/lib/libc.so.12

Последняя команда по существу подразумевает, что двоичный файл зависит от /usr/lib/libc.so.12 и что вы найдете в нем определения функций, используемых в коде.

person devnull    schedule 07.03.2014

Ваш вопрос связан с тем, где GCC ищет файлы заголовков. Он ищет стандартные включаемые каталоги. Вы можете найти эту thread быть полезным:

С помощью различных опций (таких как -I и -I- и -isystem) вы можете указать множество различных функций включения. По сути, каталоги, указанные с помощью -I, будут искаться перед теми, которые указаны с помощью -isystem, которые, в свою очередь, будут искаться перед каталогами в «стандартных системных каталогах» (по крайней мере, согласно моим тестам). Разница в том, что -I можно использовать для любой директивы #include, но -isystem будет использоваться только для #include ‹...> Тем не менее, рекомендуется использовать -I только для #include "... " директивы из-за порядка поиска. Использование -I- действительно дает вам большой контроль, потому что любой -I, использованный до -I-, будет искаться только для #include "...", в то время как любой -I, использованный после -I-, будет искаться для любой директивы #include . Кроме того, использование -I- означает, что текущий каталог не будет искать включенные файлы, если вы также не укажете -I. (поиск в текущем каталоге).

Если вы хотите получить список каталогов поиска, поддерживаемых по умолчанию, попробуйте запустить эту команду: cpp -v < /dev/null Это запустит препроцессор GNU C без каких-либо входных данных; в процессе он напечатает (с учетом флага -v) пути поиска каталога включения. Вы должны увидеть такие фразы, как "#include ‹...> поиск начинается здесь:", за которыми следует список каталогов. Это ваши стандартные пути поиска включения в порядке их поиска.

person djhaskin987    schedule 07.03.2014
comment
Это несколько касается того, где находятся библиотеки, хотя, если заголовки по умолчанию находятся в /some/path/include, библиотеки обычно находятся в /some/path/lib. - person Jonathan Leffler; 07.03.2014

Ваш libc (или libstdc++ для C++) может находиться либо в /usr/lib, либо в /usr/lib64 в Linux. Это общие библиотеки, и вы можете изменить переменную LD_LIBRARY_PATH, чтобы указать, в каких каталогах выполняется поиск. Практическим примером может быть установка локальной копии gcc, и есть вероятность, что она будет иметь обновленную версию стандартная библиотека, а не ваша система, поэтому вы хотите, чтобы ваш локальный gcc запускался с ней, т.е. export LD_LIBRARY_PATH=/home/user/local-install/gcc/lib64

person Community    schedule 07.03.2014
comment
Компилятору C вряд ли понадобится libstdc++. - person user_1818839; 07.03.2014
comment
@BrianDrummond: Да, наверное, опечатка. Я исправил ответ. - person sleske; 07.03.2014

Он просматривает пути к библиотекам, заданные переменной среды.

Подробнее: http://gcc.gnu.org/onlinedocs/cpp/Search-Path.html

person brokenfoot    schedule 07.03.2014
comment
Он не спрашивает, где gcc находит стандартные заголовки. Он спрашивает, где он находит тела этих функций. - person Alex D; 07.03.2014