Содержание
- Функции в Си
- Для чего нужны функции в C?
- Простой пример функции в Cи
- Как из одной функции в Cи вызвать другую функцию?
- Прототип функции в Си
- Чем объявление функции в Си отличается от определения функции в Си?
- Оператор return
- Передача аргументов функции по значению
- Передача указателей функции Си
- C/C++ в Eclipse
- Рекомендуем к прочтению
Функции в Си
Для чего нужны функции в C?
Функции в Си применяются для выполнения определённых действий в рамках общей программы. Программист сам решает какие именно действия вывести в функции. Особенно удобно применять функции для многократно повторяющихся действий.
Простой пример функции в Cи
Пример функции в Cи:
Это очень простая программа на Си. Она просто выводит строку «Functions in C». В программе имеется единственная функция под названием main. Рассмотрим эту функцию подробно. В заголовке функции, т.е. в строке
int – это тип возвращаемого функцией значения;
main — это имя функции;
(void) — это перечень аргументов функции. Слово void указывает, что у данной функции нет аргументов;
return – это оператор, который завершает выполнение функции и возвращает результат работы функции в точку вызова этой функции;
EXIT_SUCCESS — это значение, равное нулю. Оно определено в файле stdlib.h;
часть функции после заголовка, заключенная в фигурные скобки
называют телом функции.
Итак, когда мы работаем с функцией надо указать имя функции, у нас это main, тип возвращаемого функцией значения, у нас это int, дать перечень аргументов в круглых скобках после имени функции, у нас нет аргументов, поэтому пишем vo >
Как из одной функции в Cи вызвать другую функцию?
Рассмотрим пример вызова функций в Си:
Запускаем на выполнение и получаем: 
В этом примере создана функция sum, которая складывает два целых числа и возвращает результат. Разберём подробно устройство этой функции.
Заголовок функции sum:
здесь int — это тип возвращаемого функцией значения;
sum — это имя функции;
(int a, int b) — в круглых скобках после имени функции дан перечень её аргументов: первый аргумент int a, второй аргумент int b. Имена аргументов являются формальными, т.е. при вызове функции мы не обязаны отправлять в эту функцию в качестве аргументов значения перемнных с именами a и b. В функции main мы вызываем функцию sum так: sum(d, e);. Но важно, чтоб переданные в функцию аргументы совпадали по типу с объявленными в функции.
В теле функции sum, т.е. внутри фигурных скобок после заголовка функции, мы создаем локальную переменную int c, присваиваем ей значение суммы a плюс b и возвращаем её в качестве результата работы функции опрератором return.
Теперь посмотрим как функция sum вызывается из функции main.
Вот функция main:
Сначала мы создаём две переменных типа int
их мы передадим в функцию sum в качестве значений аргументов.
Далее создаём переменную f:
её значением будет результат работы функции sum, т.е. мы вызываем функцию sum, которая возвратит значение типа int, его-то мы и присваиваем переменной f. В качестве аргументов передаём d и f. Но в заголовке функции sum
аргументы называются a и b, почему тогда мы передаем d и f? Потому что в заголовке функций пишут формальные аргументы, т.е. НЕ важны названия аргументов, а важны их типы. У функции sum оба аргумента имеют тип int, значит при вызове этой функции надо передать два аргумента типа int с любыми названиями.
Ещё одна тонкость. Функция должна быть объявлена до места её первого вызова. В нашем примере так и было: сначала объявлена функция sum, а уж после мы вызываем её из функции main. Если функция объявляется после места её вызова, то следует использовать прототип функции.
Прототип функции в Си
Рассмотрим пример функциив Си:
В этом примере функция sum определена ниже места её вызова в функции main. В таком случае надо использовать прототип функции sum. Прототип у нас объявлен выше функции main:
Прототип — это заголовок функции, который завершается точкой с запятой. Прототип — это объявление функции, которая будет ниже определена. Именно так у нас и сделано: мы объявили прототип функции
далее в функции main вызываем функцию sum
а ниже функции main определяем функцию sum, которая предварительно была объявлена в прототипе:
Чем объявление функции в Си отличается от определения функции в Си?
Когда мы пишем прототип функции, например так:
то мы объявляем функцию.
А когда мы реализуем функцию, т.е. записываем не только заголовок, но и тело функции, например:
то мы определяем функцию.
Оператор return
Оператор return завершает работу функции в C и возвращает результат её работы в точку вызова. Пример:
Эту функцию можно упростить:
здесь оператор return вернёт значение суммы a + b.
Операторов return в одной функции может быть несколько. Пример:
Если в примере значение аргумента a окажется больше двух, то функция вернет ноль (первый случай) и всё, что ниже комментария «// Первый случай;» выполнятся не будет. Если a будет меньше двух, но b будет меньше нуля, то функция завершит свою работу и всё, что ниже комментария «// Второй случай;» выполнятся не будет.
И только если оба предыдущих условия не выполняются, то выполнение программы дойдёт до последнего оператора return и будет возвращена сумма a + b.
Передача аргументов функции по значению
Аргументы можно передавать в функцию C по значению. Пример:
В примере, в функции main, создаём переменную int d = 10. Передаём по значению эту переменную в функцию sum(d). Внутри функции sum значение переменной увеличивается на 5. Но в функции main значение d не изменится, ведь она была передана по значению. Это означает, что было передано значение переменной, а не сама переменная. Об этом говорит и результат работы программы: 
т.е. после возврата из функции sum значеие d не изменилось, тогда как внутри функции sum оно менялось.
Передача указателей функции Си
Если в качестве аргумента функции передавать вместо значения переменной указатель на эту переменную, то значение этой переменной может меняться. Для примера берём программу из предыдущего раздела, несколько изменив её:
В этом варианте программы я перешел от передачи аргумента по значению к передаче указателя на переменную. Рассмотрим подробнее этот момент.
в функцию sum передается не значение переменной d, равное 10-ти, а адрес этой переменной, вот так:
Теперь посмотрим на функцию sum:
Аргументом её является указатель на int. Мы знаем, что указатель — это переменная, значением которой является адрес какого-то объекта. Адрес переменной d отправляем в функцию sum:
Внутри sum указатель int *a разыменовывается. Это позволяет от указателя перейти к самой переменной, на которую и указывает наш указатель. А в нашем случае это переменная d, т.е. выражение
Результат: функция sum изменяет значение переменной d: 
На этот раз изменяется значение d после возврата из sum, чего не наблюдалось в предыдущм пункте, когда мы передавали аргумент по значению.
C/C++ в Eclipse
Все примеры для этой статьи я сделал в Eclipse. Как работать с C/C++ в Eclipse можно посмотреть здесь. Если вы работаете в другой среде, то примеры и там будут работать.
Что означает следующее:
Я думаю, что int main() <. >означает, что main не получает никаких параметров (из командной строки):
Но что означает int main(void) <. >? что означает void?
Я посмотрел здесь, но это как-то другой вопрос.
В С++ нет разницы.
В C разница сомнительна. Некоторым нравится утверждать, что последняя версия (без void ) технически является просто общим расширением реализации и не гарантируется работой по стандарту из-за формулировки в стандарте. Однако в стандарте четко указано, что в определении функции пустой набор параметров имеет четко определенное поведение: функция не принимает никаких параметров. Таким образом, такое определение для основного соответствует следующему описанию в стандарте:
Он [основной] должен быть определен с типом возврата int и без параметров.
Однако существует заметная разница между ними: а именно, версия без void не может обеспечить правильный прототип функции:
О, и просто чтобы быть полным: void имеет во всех деклараторах функций следующее значение:
(6.7.6.3p10) Частный случай неименованного параметра типа void как единственного элемента в списке указывает, что функция не имеет параметров.
В C, в прототипе (не в С++ хотя) пустой список аргументов означает, что функция может принимать любые аргументы (в определении функции это означает отсутствие аргументов). В С++ пустой список параметров означает отсутствие аргументов. В C, чтобы не принимать аргументов, вы должны использовать void . См. этот вопрос для лучшего объяснения.
В С++, имеющем функцию foo(void) и foo() , это одно и то же. Однако в C это другое: foo(void) — это функция, которая не имеет аргументов, а foo() — это функция с неопределенными аргументами.
В С++ нет разницы, оба одинаковы.
Оба определения работают и на C, но второе определение с void считается технически лучше, поскольку оно ясно указывает, что main можно вызывать только без какого-либо параметра. В C, если сигнатура функции не указывает какой-либо аргумент, это означает, что функция может вызываться с любым количеством параметров или без каких-либо параметров. Например, попытайтесь скомпилировать и запустить следующие две программы C (не забудьте сохранить ваши файлы как .c).
Прежде всего, существует разница в том, что разрешено для размещенных систем и автономных систем, как показанных здесь.
Для размещенных систем, 5.1.2.2.1 применяется запуск программы:
Функция, вызванная при запуске программы, называется main. Реализация не объявляет прототип для этой функции. Он определяется с типом возврата int и без Параметры:
. (больше текста следует в отношении стилей argv/argc и т.д.).
Интересная часть — "без параметров". int main() и int main (void) в настоящее время эквивалентны, поскольку они оба являются деклараторами функций и не имеют параметров. Применимо (6.7.6.3):
10 Частный случай неименованного параметра типа void как единственного элемента в списке указывает, что функция не имеет параметров.
14 Список идентификаторов объявляет только идентификаторы параметров функции. Пустое список в объявлении функции, который является частью определения этой функции, указывает, что функция не имеет параметров. Пустой список в объявлении функции, который не является частью определение этой функции указывает, что никакой информации о количестве или типах параметры поставляются .145)
Подчеркните мишень, полужирный текст — это то, что относится к int main() . Также есть примечание 145) в конце текста, в котором говорится "Смотрите" "дальнейшие языковые направления (6.11.6)":
Использование деклараторов функций с пустыми скобками (не деклараторы типов параметров прототипа) является устаревшей функцией.
И вот в чем разница. Являясь объявлением функции, int main() является плохой стиль из-за вышеизложенного, так как он не гарантированно работает в следующей версии стандарта C. Он помечен как устаревшая функция в C11.
Поэтому вы должны всегда использовать int main (void) в размещенной системе и никогда int main() , даже если эти две формы на данный момент эквивалентны.
В С++ обе формы полностью эквивалентны, но там int main() является предпочтительным стилем для субъективных, косметических соображений (Bjarne Stroustrup говорит так. что, вероятно, довольно плохое объяснение, почему вы делаете что-то определенным образом).
В С++ нет разницы между двумя, а int main() — это законная подпись и тип возврата для main .
Прототип функции Type foo(void) абсолютно такой же, как Type foo() , между ними нет никакой разницы. Бывший может быть использован для удобства чтения.
Как и при использовании main — принятия аргументов или нет, программа все равно может обращаться к информации о командной строке с помощью других средств, таких как __argv , __argc , GetCommandLine или других символов платформы/компилятора.
Я знаю, что поток старый, но несколько лет назад этот вопрос беспокоил меня, поэтому я хотел бросить свою половину процента (если это).
Я всегда рассматриваю функции C, как если бы они фиксировали количество аргументов независимо от контекста, если только они не используют va_args. То есть, я верю, что ВСЕГДА имеют прототип:
даже если аргументы не переданы, функция имеет эти аргументы в стеке, потому что основная функция не имеет перегрузки функций.
C имеет возможность иметь примитивную перегрузку, просто делая вид, что аргумент отсутствует. В этом случае аргумент все еще передается и находится в стеке, но вы никогда не обращаетесь к нему, поэтому он просто уменьшает размер исходного кода.
Высказывание int main() просто означает, что я знаю, что функция может иметь параметры, но я их не использую, поэтому я пишу int main().
Высказывание int main (void) говорит о том, что main НЕКОТОРНО не имеет аргументов и подразумевает наличие двух разных прототипов функций:
Так как C не имеет функции перегрузки, это несколько вводит меня в заблуждение, и я не доверяю коду с основным (void) в нем. Я бы не стал, если main NEVER принял какие-либо параметры, и в этом случае main (void) будет полностью в порядке.
ПРИМЕЧАНИЕ. В некоторых реализациях есть больше параметров в основном, чем argc и argv, таких как env, но это меня не беспокоит, потому что я знаю, что я не говорю прямо, что это только два параметра, но это минимальные параметры, и все в порядке, чтобы иметь больше, но не меньше. Это противоречит прямому утверждению int main (void), который кричит на меня, поскольку ЭТОТ ФУНКЦИЯ НЕТ ПАРАМЕТРОВ, что неверно, поскольку это так, они просто опускаются.
Вот мой базовый код:
./sample У меня явно есть аргументы
У функции явно есть аргументы, переданные ей, несмотря на то, что она явно не говорит о том, что она не набирает void в прототип функции.
Как указано выше:
(6.7.6.3p10) Частный случай неименованного параметра типа void как только элемент в списке указывает, что функция не имеет параметров.
Таким образом, говоря, что функция имеет пустоту как аргумент, но фактически наличие аргументов в стеке является противоречием.
Моя точка зрения заключается в том, что аргументы все еще существуют, поэтому явное утверждение о том, что main не содержит аргументов, является нечестным. Честным способом было бы сказать int main(), который не утверждает ничего о том, сколько параметров у него есть, только о том, сколько параметров вам нужно.
ПРИМЕЧАНИЕ2: _argc, _pargv зависят от системы, чтобы найти ваши значения, которые вы должны найти, запустив эту программу:
Эти значения должны оставаться правильными для вашей конкретной системы.
Минимальной программой на C++ является
В этой программе представлено объявление функции main, которая не принимает никаких аргументов. Фигурные скобки отражают группировку в C++ и в данном случае показывают тело функции main. То есть начало функции main — открывающая скобка, и конец функции main — закрывающая скобка. Двойной слэш показывает начало комментария. Комментарии игнорируются компилятором и служат для уточнения информации в коде.
Каждая программа, написанная на C++, имеет в себе функцию main() , с которой начинается запуск программы. Функция main(), как правило, возвращает результат своего выполнения, о чем сигнализирует тип данных int (integer — целочисленный), который написан перед функцией main() . При правильном, успешном завершении функция main() возвращает в качестве результата 0 . Значение результата, отличное от нуля сигнализирует о нештатном завершении программы.
Возвращаемое программой значение по завершению может использоваться в операционной системе для служебных целей.
Типичным примером первой программы на любом языке программирования является вывод текста "Hello, World!":
Но так ли всё просто в данной программе? В целом, уже одна эта маленькая программа несёт в себе очень большой пласт информации, который необходимо понимать для разработки на C++.
- Директива #include
#include
сообщает компилятору о том, что необходимо подключить некий заголовочный файл, компоненты которого планируется использовать в файле, где объявлена функция main() . iostream — это стандартная библиотека ввода вывода из STL. То есть здесь уже используется функционал библиотек, хоть и являющихся для языка стандартом. И последний момент — это угловые скобки, в которых находится название библиотеки, которые говорят о том, что это включение внешних файлов в проект, а не тех которые находятся в составе проекта. Те же файлы, которые находятся в составе проекта подключаются обрамляясь в обычные кавычки, например #include "myclass.h". Такое подключение библиотек является стандартом. Например, в Visual Studio при несоблюдении данного стандарта будут выпадать ошибки.
std — это использование пространства имён, в котором находится оператор вывода cout. Пространства имён были введены в C++ для того, чтобы убрать конфликты имён между библиотеками и проектом разработчика, если где-то имеются повторяющиеся наименования функций или классов. В Java для разрешения конфликтов имён используется система пакетов.
cout — это оператор вывода, у которого перегружен оператор По статье задано0 вопрос(ов)





