Поделиться через


Аргументы

Аргументы в вызове функции могут иметь следующую форму:

expression ( expression-listopt ) /* Вызов функции */

При вызове функции параметр expression-list содержит список выражений, разделенных запятыми. Значения этих выражений являются аргументами, которые передаются функции. Если функция не принимает аргументы, то список expression-list должен содержать ключевое слово void.

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

Хотя массивы и функции не могут передаваться в качестве аргументов, вы можете передать указатели на них. Благодаря этому функция сможет обращаться к значению по ссылке. Поскольку указатель на переменную содержит адрес переменной, то функция может обращаться к значению по этому адресу. Аргументы-указатели позволяют функции обращаться к массивам и функциям, хотя сами они и не могут передаваться в качестве аргументов.

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

При вызове функции вычисляются все выражения из списка expression-list, и для каждого аргумента выполняются обычные арифметические преобразования. Если доступен прототип, то результат вычисления аргументов сравнивается по типу с соответствующим параметром прототипа. Если они не совпадают, то либо выполняется преобразование, либо выводится диагностическое сообщение. Для параметров также проводятся обычные арифметические преобразования.

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

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

Пример

В следующем примере в качестве аргументов используются указатели:

int main()
{
    /* Function prototype */

    void swap( int *num1, int *num2 );
    int x, y;
    .
    .
    .
    swap( &x, &y );  /* Function call */
}

/* Function definition */

void swap( int *num1, int *num2 )
{
    int t;

    t = *num1;
    *num1 = *num2;
    *num2 = t;
}

В этом примере функция swap объявлена внутри функции main. Она имеет два аргумента, num1 и num2, которые являются указателями на значения типа int. Параметры num1 и num2 в определении прототипа также объявляются как указатели на значения типа int.

Функция вызывается следующей инструкцией:

swap( &x, &y )

Адрес x, который здесь используется, сохраняется в аргументе num1, а адрес y — в аргументе num2. Теперь для одного и того же местоположения имеется два имени, или псевдонима. Ссылки на значения *num1 и *num2 в функции swap одновременно представляют собой ссылки на значения x и y в функции main. Присваивания внутри функции swap, по сути, меняют содержимое переменных x и y. Поэтому оператор return не требуется.

Компилятор выполняет проверку типов для аргументов функции swap, поскольку в прототипе swap указаны типы аргументов для каждого параметра. Идентификаторы, приведенные в круглых скобках в прототипе и определении функции, могут совпадать, но могут и различаться. Важно лишь то, что типы аргументов в функции должны соответствовать типам параметров как в прототипе, так и в определении.

См. также

Вызовы функций