Подтвердить что ты не робот

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

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

Edit

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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 и что вы найдете определения функций, используемых в этом коде.

Ответ 3

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

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

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

Ответ 4

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