предупреждение о неявном объявлении: каковы встроенные функции?

Интерфейс вопросов и ответов помечает многие «Вопросы, на которые, возможно, уже есть ваш ответ», но я попытался проявить должную осмотрительность, чтобы проверить, спрашивают ли они, что именно я здесь. Приношу свои извинения, если это дубликат.

Предположим, у меня есть следующая некорректная программа:

extern void undefined_function(void);
int main(int argc, char **argv)
{
    undefined_function();
    undeclared_function();
    exit(0);
}

Компиляция с помощью gcc дает:

$ gcc warnings.c 
warnings.c: In function ‘main’:
warnings.c:6:2: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
/tmp/ccVzjkvX.o: In function `main':
warnings.c:(.text+0x15): undefined reference to `undefined_function'
warnings.c:(.text+0x1f): undefined reference to `undeclared_function'
collect2: ld returned 1 exit status
$ 

Я знаю, почему появляются эти предупреждения и как их исправить - это не мой вопрос.

Из выходных данных видно, что gcc обрабатывает exit() иначе, чем другие неопределенные / необъявленные функции, потому что считает это «встроенной функцией».

Для данного gcc, как я могу определить список функций, которые gcc считает «встроенными функциями»? Это точно список стандартных библиотечных функций c или что-то еще?

Я подумал о том, чтобы сделать nm libc.so, но на моей виртуальной машине Ubuntu этот glibc, похоже, удален, поэтому здесь нет полезной информации по этому поводу:

$ nm /lib/x86_64-linux-gnu/libc.so.6
nm: /lib/x86_64-linux-gnu/libc.so.6: no symbols
$ 

person Digital Trauma    schedule 14.11.2013    source источник


Ответы (3)


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

person Ernest Friedman-Hill    schedule 14.11.2013
comment
@AlecTeal - Почему бы и нет? - есть даже значок для кодирования именно этого: stackoverflow.com/help/badges/805/sportsmanship - person Digital Trauma; 14.11.2013

Покопавшись еще немного в документации gcc, я думаю, что нашел разумный частичный ответ на этот вопрос (хотя этот ответ более полный в своих ссылках):

http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Other-Builtins.html#Other-Builtins

«GCC включает встроенные версии многих функций стандартной библиотеки C» (выделено мной). Я понимаю, что это означает, что большинство, но не все стандартных библиотечных функций являются встроенными.

Документация продолжается несколькими списками, применимыми к различным уровням стандарта c:

"Функции ISO C90 abort, abs, acos, asin, atan2, atan, calloc, ceil, cosh, cos, exit, ..."


Примером стандартной библиотечной функции, которая не является встроенной функцией gcc, является bsearch(). Если я добавлю к этому вызов в программе без #include <stdlib.h> и скомпилирую с -Wimplicit-function-declaration, я получу только:

warnings.c:5:2: warning: implicit declaration of function ‘bsearch’ [-Wimplicit-function-declaration]

А для exit() я получаю:

warnings.c:8:2: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
warnings.c:8:2: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
person Digital Trauma    schedule 14.11.2013

Вы компилируете C, который допускает неявные объявления, поэтому ваш «выход» объявляется неявно. и компилятор надеется, что вы определите его позже.

Неявные объявления - это нормально, если вы подразумевали выход с обычным поведением (подразумеваемый прототип был идентичен фактическому прототипу), все было бы хорошо.

GCC может сказать вам только о встроенных, потому что вы знаете, что для компилятора C там будет stdlib. Это единственная функция, о существовании которой он знает (встроенная), чтобы сообщить вам, что вы неправильно намекаете.

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

GCC знает о встроенном stdlib =.

Дополнение

GCC поверит вам на слово, что неопределенные функции будут существовать, используя свойство неявного объявления, и ничто не противоречит этому, так что это нормально. Он не знает, как undeclared_function должен выглядеть на самом деле, но он знает, как должен выглядеть exit.

Затем, как вы знаете, компоновщик вызывает истерику (это, конечно, справедливо), потому что не может их найти.

person Alec Teal    schedule 14.11.2013
comment
Это полезно, но я специально ищу точный список функций, будь то вывод gcc или другого инструмента или документация. - person Digital Trauma; 14.11.2013
comment
@DigitalTrauma - вся стандартная библиотека C. Просто включите каждый файл heaver, и пусть GCC выдаст список объявлений. Вы можете скомпилировать с некоторыми флагами, которые говорят ему не использовать стандартную библиотеку (скажем, если вы делаете ядро ​​...) кстати. - person Alec Teal; 14.11.2013
comment
Голосовать против меня. Но ответ, который я только что нашел, не совсем такой, как ваш. - person Digital Trauma; 14.11.2013
comment
@DigitalTrauma он знает обо всех, это работа GCC, но он может не предупреждать о некоторых из более экзотических / менее часто используемых, потому что вы не используете их так часто. Стандарт не определяет, как / когда компилятор должен предупреждать, это потому, что GCC - очень полезный инструмент. - person Alec Teal; 14.11.2013
comment
@ ErnestFriedman-Hill см. Выше. GCC знает о них всех, но явно не предупреждает о них всех. Он может быть действительно умным и действительно полезным, если он видит, что вы используете кучу функций, обычно используемых вместе, если они вообще используются, он может не предупредить вас, если вы используете только одну, но если вы используете группу, то может. - person Alec Teal; 14.11.2013
comment
Вы компилируете C, который допускает неявные объявления - Не совсем так. C90 допускает неявные объявления (и предполагает, что вызываемая функция возвращает int), а C99 - нет. Начиная с C99, вызов функции без видимого объявления является нарушением ограничения, требующим диагностики. По умолчанию gcc компилирует C90 с расширениями, специфичными для GNU. Вы можете использовать -std=..., чтобы изменить это. - person Keith Thompson; 14.11.2013
comment
@KeithThompson точно. C стал намного более безопасным по типу в C99 (и не только). - person Alec Teal; 14.11.2013
comment
Вы говорите точно, но в вашем ответе по-прежнему говорится, что C допускает неявные объявления. Возможно, вы захотите обновить свой ответ, чтобы прояснить этот момент. - person Keith Thompson; 14.11.2013
comment
Если кто-то говорит C ++, какой из них вы предполагаете? Если кто-то говорит C, мы все предполагаем, что C90 с расширениями GNU, даже у Clang есть расширения GNU. Это также подразумевается вопросом OP: если бы это не c90, он не получил бы того же результата. Это чересчур педантично. - person Alec Teal; 14.11.2013
comment
@AlecTeal: Если вы отвечаете кому-то, пожалуйста, укажите имя человека, которому предшествует знак at; в противном случае они не будут уведомлены о вашем ответе. Я случайно увидел твой комментарий. Нет, мы не все предполагаем, что C означает C90 с расширениями GNU. Текущая официальная версия C определена стандартом ISO 2011 года. Неявные объявления функций были удалены из языка в 1999 году, и это всегда было плохой идеей. Это не педантизм, а аккуратность. - person Keith Thompson; 16.11.2013
comment
@KeithThompson, вы должны опубликовать ответ о том, что эти предупреждения неверны. - person Alec Teal; 16.11.2013
comment
@AlecTeal: Кто сказал, что они неправы? Предупреждение о неявном объявлении совершенно справедливо для расширений C90 или C90 плюс GNU. Но C охватывает более обширную территорию. - person Keith Thompson; 16.11.2013
comment
@KeithThompson, ты слишком (и досадно) педантичен. Если я дрался с кем-то, кого вы не пойдете, вы имеете в виду, что использовал человека как оружие или сражался против человека - контекст помогает; остальное - здравый смысл. - person Alec Teal; 16.11.2013