Где определены функции в стандартной библиотеке C?
меня не интересует исходный код, я хочу знать, как компилятор C (GCC) фактически находит функции. Например, когда препроцессор видит, что я включил stdio.h
, где искать файлы, определяющие тела функций?
редактировать
Я, вероятно, также должен сказать, что я использую Ubuntu 12.04, но если есть общий ответ, это тоже сработает.
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
'линкер с не включить стандартные объектные файлы библиотеки по умолчанию.
gcc
получает определения функции из библиотеки Си. Вы можете определить путь, который 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
и что вы найдете определения функций, используемых в коде в нем.
ваш вопрос связан с тем, где GCC ищет файлы заголовков. Он ищет в стандартных каталогах. Вы можете найти этой теме будет полезно:
с различными параметрами (такими как-I и-I - и-isystem) вы можете указать множество различных функций включения. В основном, каталоги, указанные by-I будет искать перед указанными-isystem, которые будут в свою очередь, искать до тех, в " стандартной системе включают каталоги " (по крайней мере, согласно моим тестам). Разница в том, что - Я могу использоваться для любой директивы #include, но-isystem будет использоваться только для #include <...> Тем не менее, рекомендуется только используйте -I для #include "...- директивы из-за порядка поиска. Использование-Я-действительно дает вам много контроля, потому что любой-я использовал раньше - Я-будет искать только для #include"..."в то время как любой-я использовал после-я - будет искать любую директиву #include. Кроме того, с помощью - I-означает, что текущий каталог не будет искать включенные файлы, если вы также не укажете-I. (поиск текущего справочник.)
Если вы хотите получить список поддерживаемых каталогов поиска по умолчанию попробуйте выполнить следующую команду:
cpp -v < /dev/null
Это работает препроцессор GNU C без ввода; в процессе он будет печатать (учитывая флаг-v) пути поиска каталога включения. Вы должны см. такие фразы, как " #include <...> поиск начинается здесь: "далее ля список директорий. Это ваши стандартные пути поиска включения, в того, что они искали.
код libc
(или libstdc++
для C++) может быть расположен в любом /usr/lib
или /usr/lib64
на Linux. Это общие библиотеки и вы можете изменить LD_LIBRARY_PATH
переменная, чтобы указать, в каких каталогах они ищут. Практическим примером может быть установка локальной копии gcc, и, скорее всего, она будет иметь обновленную версию стандартной библиотеки в отличие от вашей системы, поэтому вы хотели бы, чтобы ваш локальный gcc запустился с этим вместо i.e export LD_LIBRARY_PATH=/home/user/local-install/gcc/lib64
он просматривает пути библиотеки, заданные переменной среды.
Подробнее:http://gcc.gnu.org/onlinedocs/cpp/Search-Path.html