Работая со старым кодом, столкнулся с интересным стилем.
После подключения библиотек и определение глобальных переменных идет main
, а в ней функции, которые уже должны работать. Фишка в том, что сами функции создаются после main
в конце кода. Неужели процессор не теряет такты, когда ему приходится читать сначала команды, потом искать их определение а потом снова читать и только потом выполнять?
Я понимаю, что команды и переменные находятся в разных сегментах памяти отведенной для программы, но хотел узнать, как правильно писать функции. Где их создавать и где определять?
Не важно, где определяется функция, важно лишь, чтобы к моменту ее использования она была объявлена.
Попытаюсь объяснить простыми словами.
Во-первых, вам нужно понять разницу между объявлением и определением:
Объявление (англ. declaration) функции несет информацию об имени функции, типе возвращаемого ею значения и списке ее параметров. То есть всю информацию об интерфейсе, с помощью которого эта функция может быть использована.
Определение (англ. definition) же, в свою очередь, несет информацию о том, что внутри этой функции происходит. То есть то, как функция устроена внутри, какова ее реализация.
Чтобы вызвать какую-либо функцию компилятору всегда нужно знать тип всех ее аргументов (чтобы правильно эти аргументы передать). Компилятор не сможет вызвать функцию, если не знает о списке ее аргументов, просто потому что не будет знать, как эту функцию правильно вызвать.
И здесь уже стоит сказать о том, что компилятор может скомпилировать код, использующий некторую функцию, даже не зная определения самой этой функции. Это приводит к широчайшим возможностям (раздельная компиляция, динамически подключаемые библиотек и так далее).
Например, вы наверняка сталкивались с использованием функции printf
из стандартной библиотеки:
#include <stdio.h>
int main(void)
{
printf("Hello, World!\n");
}
Это программа компилируется и отлично работает. Но ведь у нас нет ни объявления, ни определения функции printf
! Как компилятор вообще смог все это скомпилировать?
На самом деле, объявление функции у нас есть, и содержится оно в заголовочном файле <stdio.h>
1 и выглядит (один из возможных вариантов) так:
extern int printf (const char *__restrict __format, ...);
Это объявление, которое называют прототипом (англ. function prototype), говорит компилятору, как нужно вызывать эту функцию. И компилятор успешно генерирует ассемблерный код для ее вызова.
Объявление же этой функции становится известно только во время запуска программы, во время динамической линковки библиотеки, содержащей это определение. В роли библиотеки в данном случае выступает стандартная библиотека языка C, вернее ее конкрентая реализация (GNU C Library, в моем случае).
1. В теории, мы можем вообще не подключать <stdio.h>
, а скопировать протип функции printf
прямо в наш код. Хотя делать так, конечно, не стоит.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
что нужно написать в цикле чтобы перевести каждый элемент стринга в инт и прибавить его в 'c'
Как вывести совпадения для пользователя -user_i = 1Нужно вывести пользователей, которых лайкнул пользователь 1 и те пользователя, которые лайкнули...