2010-11-01 4 views
2

Я стараюсь изо всех сил пытаться. И я думал, что понял это связующее дело. Но я думаю, нет. У меня есть простой файл main.c:Связывание объектных файлов, в том числе избыточное?

#include "function.h" 
int main(char args[]) 
{ 
    int print = myfunction(); 
} 

затем вторая пара файлов function.c/function.h

int myfunction(); //function.h 

int myfunction() //function.c 
{ 
    return 5; 
} 

компилирования это прекрасно работает. Тем не менее, он отлично работает независимо от того, использую ли я #include "function.h" в своем основном файле или нет. Почему мне нужно включить функцию.h?

+0

Кстати, аргументы 'main' должны быть' (int argc, char * argv []) 'или возможно' (void) ', а не' (char args []) ' – aschepler

ответ

2

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

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

За исключением вариационной функции, и даже там параметры «переменных» по-прежнему в основном следуют тем же правилам, что и прототип функции.

+0

Все исчерпывающие ответы, но вы были тщательно и быстро .. Принято! – Max

+1

Для nitpick: объявление требуется, если тип возвращаемого значения является чем-то другим, чем int (результаты с плавающей запятой обычно возвращаются в другом регистре, чем целочисленные), если есть какой-либо параметр, который будет продвигаться (типа char, short) и для (у них может быть другая ABI, чем нормальная функция, оставляя вызывающей стороне задачу очистить стек вместо того, чтобы всплывать сами аргумент). – AProgrammer

0

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

В вашем простом примере это не требуется.

3

Я не знаю, какую систему вы, но если он использует GCC или что-то совместимое, попробуйте еще раз с

cc -Wall -Werror *.c 

Или, включите эквивалентные параметры для вашей системы.

Большие программы всегда созданы таким образом, чтобы компилятор проверял типы аргументов. В отличие от динамических и скриптовых языков, C генерирует фактический машинный код и не проверяет количество параметров или совместимость во время выполнения.

Итак, прототипы функций были добавлены на базовый язык для проверки типов во время компиляции. Они не являются обязательными.

+0

И соответствующее предупреждение от GCC будет следующим: 'main.c: 4: 5: warning: неявное объявление функции 'myfunction' [-Wimplicit-function-declaration]' – user

0

Если вы используете функцию, которая не была объявлена, старые компиляторы C предполагают, что у нее есть аргументы ... и тип возврата int. Это не рекомендуется. Если вы включите предупреждения компилятора, вы, скорее всего, получите предупреждение об использовании незаявленной функции. Компилятор может поймать больше ошибок, если он видит function.h перед компиляцией main.c, поэтому он точно знает, как должен действовать myfunction.

1

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