2015-11-13 3 views
0

Я программист на Java, я немного научился C++, и теперь я изучаю немного C для своей работы. Я не могу понять поведение C в отношении объявления/определения функции и связанных вызовов функций. Из К & RI знаю, что в C (очень отличается от C++) я могу вызвать функцию, которая не была ранее объявлена, и компилятор предполагает неявное объявление типа:C определение функции и объявление

int main() 
{ 
    function(10); // implicit function declaration (int function()) 
} 

, и я знаю, что такое объявление подразумевает функцию, которая принимает фиксированное, но неопределенное количество аргументов любого типа (до тех пор, пока каждый вызов согласуется с другими). И я знаю, что это K & R C, до C89, но я хочу знать, как это работает. Теперь у меня есть тестовый код, я не могу понять:

#include <stdio.h> 

function(); 

int main() 
{ 
    printf("hello %d",function(1,2,3)); 
    implicit(11,12,32);  // implicit function declaration (implicit()) 
} 


int implicit(int b) 
{ 

} 

function(int a) 
{ 

} 

в случае function декларации (предполагается, тип возвращаемого быть ИНТ, никаких предположений об аргументах) ничего не соответствует определению (компилятор выдает предупреждение), но если я вызываю функцию с неправильными аргументами, она компилируется! То же самое для функции implicit. Я не могу понять.

+0

Эти проблемы возникают именно потому, что C++ требует, чтобы функции были объявлены в расширенном режиме. И это практика, которой я придерживался в C. –

+6

Это старый, устаревший, плохой код. Вам, как начинающему C, действительно нужно знать, как работает плохой код? –

+0

Да, C нужны файлы .h, где вы помещаете свои определения функций (прототипы). Предполагается, что они существуют где-то во время компиляции, а затем не работают во время выполнения. Взгляните на файл stdio.h. –

ответ

3

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

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

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

+0

, поэтому в C++ каждое имя функции объявляется прототипом, а прототип должен соответствовать определению (в том же или другом компиляторе), я мог бы использовать тот же синтаксис в ANSI C , но если я использую старый стиль (который я не буду) C и использую неявное или no-arg объявление функции, компилятор не применяет соответствие определения/определения, и все может случиться? – Luca

+3

@Luca Короткий ответ на длинный вопрос - да. –

0

Невозможно ничего понять. Это унаследованное поведение С, которое было крайне слабым языком. Пока компилятор может генерировать инструкцию по сборке, он с удовольствием скомпилирует ваш код и оставит его для очистки беспорядка.

Именно поэтому он компилируется в вашем случае. Компилятор может генерировать инструкцию для вызова функции - поэтому он делает это по запросу.

+0

Да, но с точки зрения C++ это трудно понять. Это поведение компилятора меня озадачивает, позволяя вызвать вызов функции, который «соответствует» предыдущему объявлению (неявный или разрешающий любые аргументы), но с последующим другим определением. – Luca

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