Объявление функции против определения функции

Если у меня есть этот прототип:

int bar(int);

для компилятора я объявляю идентификатор bar.

Если у меня есть это определение:

int bar(int a) {};

для компилятора я определяю идентификатор bar.

Вообще говоря, определение выделяет память для объекта, но:

  1. это также верно для объявления функции? Также в этом случае не выделяется память?
  2. какая память выделена для определения функции и когда она выделена?

P.S. Спецификация C, когда говорится об объявлении или определении, говорит об их отношении к идентификатору (т.е. объявление идентификатора...) Но я также читал текст, где говорится о объявлении идентификатора переменная. Так есть ли какая-то разница или это только "двойной способ" сказать об одном значении?


person xdevel2000    schedule 10.10.2014    source источник


Ответы (4)


В случае функции выделение памяти выполняется при первом вызове функции. Само определение не выделяет память.

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

int bar(int a) {};  

[Предупреждение] элемент управления достигает конца непустой функции [-Wreturn-type]
[Предупреждение] ISO C не допускает дополнительных ';' вне функции [-педантичный]

person haccks    schedule 10.10.2014
comment
и что вы думаете о правильной терминологии между объявлением идентификатора и объявлением переменной? - person xdevel2000; 10.10.2014
comment
Я бы сказал: Declaration говорит о существовании чего-то. Definition — это реализация/создание этого объявления. Вы хотели бы прочитать: В чем разница между определение и объявление? - person haccks; 10.10.2014
comment
Также обратите внимание, что нет никакой разницы между идентификатором и переменной. - person haccks; 10.10.2014
comment
Нет, я думаю, что есть разница. Идентификатор — это декларатор сущности (переменной или функции). Сам идентификатор является лишь именем объекта, который он описывает. Кроме того, стандарт делает это различие: т. Е. Когда он говорит о классе хранения, он говорит об объектах, когда он говорит о области действия и связи, он говорит об идентификаторах. - person xdevel2000; 10.10.2014

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

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

person Dr. Debasish Jana    schedule 10.10.2014

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

В стандарте (то есть в абстрактной машине) функция не занимает памяти. Термин «определение» определен в C11 (n1570) 6.7 p5.

Объявление определяет интерпретацию и атрибуты набора идентификаторов. Определение идентификатора — это объявление для этого идентификатора, которое: - для объекта вызывает резервирование памяти для этого объекта; - для функции включает тело функции;*) - для константы перечисления является (единственным) объявлением идентификатора; - для имени typedef это первое (или единственное) объявление идентификатора. [немного отличается от C99, где переопределение typedef не разрешено]

*) Определения функций имеют другой синтаксис, описанный в 6.9.1.

Стандарт использует термин «переменная» только в ненормативных частях, таких как сноски (как существительное; в нормативных частях он используется как прилагательное, например, в «массиве переменной длины»).

Термин «идентификатор» см. там же. 6.4.2.1,

(2) Идентификатор представляет собой последовательность нецифровых символов (включая подчеркивание _, строчные и прописные латинские буквы и другие символы) и цифр, которая обозначает один или несколько объектов, как описано в 6.2.1.

и там же. 6.2.1 п1

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

Для полноты прототип функции — это объявление; объявления старого стиля и определения старого стиля не являются объявлениями прототипа.

person mafso    schedule 10.10.2014

Что значит объявить что-то в C и C++

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

Так как же выглядит декларация? Например, если вы пишете:

int func();

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

Что означает определение чего-либо в C и C++

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

Например, наличие объявления часто достаточно для компилятора. Вы можете написать такой код:

int func();

int main()
{
 int x = func();
 }

int func()
 {
 return 2;
 }

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

Вы также можете объявить класс, не определяя его.

класс МойКласс

Код, который должен знать подробности того, что находится в MyClass, не может работать — вы не можете сделать это:

class MyClass;

MyClass an_object;

 class MyClass 
 {
 int _a_field;
 };

Поскольку компилятору необходимо знать размер переменной an_object, а он не может этого сделать из объявления MyClass; ему нужно определение, которое показано ниже.

person Walter    schedule 10.10.2014