Я не включил заголовочный файл, почему я все еще могу успешно вызывать функцию getpid ()? - PullRequest
0 голосов
/ 08 февраля 2020

Код как показано ниже:

int main (int argc, char *argv[]) {
    long pid = (long)getpid();
    long test = pid + 1;
}

Не включены файлы заголовков, все еще может успешно скомпилировать код и все еще может успешно запустить программу.

Почему?

Информация о среде: Ubuntu 18.04.2 LTS, г cc (Ubuntu 4.8.5-4ubuntu8) 4.8.5

Ответы [ 2 ]

2 голосов
/ 08 февраля 2020

Не включены файлы заголовков, все еще может успешно скомпилировать код. все еще может запустить программу успешно. Почему?

Почему бы и нет?

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

Однако в вашем конкретном случае вы используете G CC 4.8.5. Серия G CC 4.8 по умолчанию компилируется для стандарта C90 с расширениями GNU. C90 позволяет вызывать функции без декларации в области, для совместимости с более ранней практикой предварительной стандартизации. Это больше не разрешено в C99 или более поздней версии, но, тем не менее, многие реализации продолжают принимать его как расширение.

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

Обратите внимание также что G CC 4 определенно имеет возможность выдавать предупреждения об использовании, такие как ваше, даже при компиляции в режиме C90 или GNU90. Вам будет полезно включить опцию -Wall при компиляции, а также, возможно, дополнительные опции предупреждения.

0 голосов
/ 08 февраля 2020

Обычно, чтобы использовать динамическую библиотечную функцию c, вам нужно будет связать ее с указанной библиотекой во время компиляции с помощью переключателя -l, как, например, gcc -lm prog.c при использовании функций c mathemati (из *). 1003 *).

Однако, поскольку это так часто встречается, G CC всегда связывает стандартную библиотеку C по умолчанию, что означает, что выполнение gcc prog.c на самом деле аналогично выполнению gcc -lc prog.c. Это всегда делается независимо от того, включен ли заголовок или нет.

Второе, что делает эту работу, это то, что G CC предполагает, что любая функция, которая не была объявлена ​​во время компиляции, имеет подпись int func(void) , В этом случае подпись очень похожа на сигнатуру действительной функции getpid().

Если вы посмотрите на скомпилированную программу с помощью инструмента ldd, чтобы показать, какие библиотеки динамического c являются обязательно, вы увидите, что программа связана с libc:

$ ldd prog
    linux-vdso.so.1 (0x00007ffede7d0000)
==> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0f47018000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f0f475b9000)

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

Вы можете сказать G CC не ссылаться на стандартную библиотеку по умолчанию, используя переключатель компилятора -nostdlib, но это не так полезно в вашем случае Реальное решение - всегда обрабатывать предупреждения о неявных объявлениях функций как ошибки (-Werror=implicit-function-declaration).

Если ваш компилятор не выдает это предупреждение по умолчанию, я бы предложил вам обновить его до более новой версии. G CC 4 определенно не последняя версия, доступная для Ubuntu 18.

$ sudo apt update
$ sudo apt upgrade
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...