2016-09-05 2 views
2

Я столкнулся с similar problem в моем (большом) проекте.Почему у меня нет «неопределенной ссылки на»?

//# include <string.h> // not included 

void foo(char * str, const char * delim) 
{ 
    char * tok = strtok(str, delim); 
    // warning^"assignement makes pointer from integer without a cast" 

    // [...] 
} 

Ответ (просто добавить #include <string.h> иметь прототип strtok) решается вопрос, действительно.

Однако из-за моего плохого знания компилятора/компоновщика я не понимаю, как процесс принимает функцию, которая не была прототипирована. Я предпочел бы ожидать ошибку undefined reference to function 'strtok', которая типична, когда вы забудете включить правый заголовок.

[EDIT] Я понимаю, почему этот вопрос был отмечен как дубликат, но я думаю, что это другое: я знаю о «хорошей практике», касающейся включений, мне просто интересно о поведении компилятора. Однако я признаю, что я могу нашел (часть) ответ на свой вопрос в этом посте: Are prototypes required for all functions in C89, C90 or C99? или это один: Must declare function prototype in C?

+1

Короткий ответ: вы получите сообщение об ошибке, если вы скомпилируете код как C99 или новее. Добавьте флаг gcc '-std = c11' или' -std = c99'. –

+0

Компилятор никогда не будет «бросать» (что бы это ни значило) или сообщить об этой ошибке. Это линкер. И независимо от «необходимости»: вы окончательно ** должны **. Любой средний уровень современного кодирования последних 20 лет требует этого. – Olaf

+0

@Olaf Fixed (это уже ключ к ответу на мой пост). Любой шанс вернуть знак «дубликат» после моего редактирования? – Coconop

ответ

3

Хотя связывая ваш бинарный файл, если явно не указано, бинарный файл связан со стандартом по умолчанию C библиотека (glibc, например) в любом случае, где функция определена.

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

FWIW, согласно C11, поддержка неявного объявления функции уронила, но большинство компиляторов поддерживают плохое поведения, чтобы сохранить обратную совместимость для унаследованного кода.


Примечание:

неявной функции декларации: Ранее (до C99, AFAIK), стандарт не мандат на функции, чтобы иметь опережающее объявление. В случае, если бы функция использовалась без прямого объявления, предполагается, что она возвращает int и принимает любое количество входящих параметров.

+0

Я бы сказал «* плохое поведение» «немного силен - это по-разному». С устаревшим кодом, не требующим прототипов, является критическая языковая функция, потому что небезопасно просто добавлять прототипы для функций, которые были закодированы без них, поскольку аргументы функции обрабатываются по-разному - см. Http://stackoverflow.com/questions/1255775/default-argument -промоции-в-c-функции-звонки –

+0

@AndrewHenle Простите, но я не понял. Разве нет вариативных функций для достижения того же, в то время как они соответствуют стандарту? Что мне не хватает? –

1

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

Если вы скажете куб.см до не ссылки библиотеки С помощью -nostdlib, то вы увидите сообщение об ошибке вы ожидали:

$ gcc -nostdlib file.c 

С другой стороны, вы всегда должны предоставить прототипы функций.

Возможно, вас заинтересуют другие аналогичные варианты ссылок, такие как -nodefaultlibs, nostartfiles и т. Д., Которые вы можете найти в gcc's manual.

Смежные вопросы