Передача параметра по ссылке

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

Передача по ссылке позволяет избежать копирования всей информации, описывающей состояние объекта (а это может быть существенно больше чем sizeof(int)) и является необходимой для конструктора копирования.

Если функция возвращает значение по ссылке (например в виде return *this;), то её вызов можно использовать слева от оператора присваивания (смотри также L-выражение).

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

Таким образом можно ожидать, что примерная программа напечатает (если закоментировать ошибочную строку) 0010 022 233 333.

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

57. Рекурсия в языке Си.

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

Пример. Составить рекурсивную функцию, вычисляющую факториал числа n следующим образом: n!= 1 , если n 1

long fact( int n)

{ if (n

else return (n * fact ( n -1 )); // функция fact вызывает саму себя

}

Таким образом, последовательно вызываются функции f(n), f(n-1),f(n-2)…f(1).

Достоинством рекурсий является компактная запись, а недостатком – расход времени и памяти на повторные вызовы функции и передачу ей копий параметров.

58. Указатель на функцию в языке Си.

Возможны только две операции с функциями: вызов и взятие адреса. Указатель, полученный с помощью последней операции, можно впоследствии использовать для вызова функции. Например:

void error(char* p) { /* … */ }

void (*efct)(char*); // указатель на функцию

void f()
{
efct = &error; // efct настроен на функцию error
(*efct)(error); // вызов error через указатель efct
}

Для вызова функции с помощью указателя (efct в нашем примере) надо вначале применить операцию косвенности к указателю — *efct. Поскольку приоритет операции вызова () выше, чем приоритет косвенности *, нельзя писать просто *efct(error). Это будет означать *(efct(error)), что является ошибкой. По той же причине скобки нужны и при описании указателя на функцию. Однако, писать просто efct(error) можно, т.к. транслятор понимает, что efct является указателем на функцию, и создает команды, делающие вызов нужной функции.

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

59. Классы хранения переменных языка Си.

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

В языке C имеется 4 класса памяти:

— extern (внешние переменные);

— auto (автоматические переменные);

— register (регистровые переменные);

— static (статические переменные);

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

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

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

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

Служебное слово, определяющее класс памяти, ставится в описаниях переменных перед служебным словом, задающим тип переменных:

static int i,j;

extern char ch1;

register int k;

60. Консольный ввод/вывод данных в языке Си.

Ввод/вывод информации в языке C осуществляется с помощью функций, объявленных в заголовочных файлах и, в принципе, способ их организации нас не интересует. Единственно, что необходимо знать программисту, это правила использования этих функций. Простейший способ воспользоваться функцией – написать обращение к этой функции.

Как уже отмечалось, основные функции ввода/вывода задаются в заголовочном файле stdio.h. Познакомимся с двумя полезными функциями, объявленными в этом файле и выполняющими следующие действия:

printf() – консольный вывод

scanf() – консольный ввод.

Структура (синтаксис) обращения к функции:

printf (строка формата, арг1, арг2, …, аргN);

В качестве аргументов функции арг1…аргN используются идентификаторы переменных или выражения. Список аргументов может быть пустым.

Строка формата записывается в двойных кавычках и может содержать:

  • любой текст;
  • спецификаторы форматов (по количеству аргументов), обозначаются символом %, содержат информацию о типе выводимого значения и его модификации;
  • управляющие символы.

Напомним, что управляющий символ, или ESC-последовательность, формируется из символа обратной наклонной черты\, называемого в языке C escape-символом, и латинской буквы.

Структура (синтаксис) обращения к функции:

scanf(строка формата, список аргументов);

С помощью данной функции производится ввод с клавиатуры значений переменных, перечисленных в списке аргументов в формате, определенном строкой формата. Функция преобразует последовательность вводимых символов в различные формы: целые числа, числа с плавающей точкой, символы и строки C.

Особенности функции:

  • в языке C в строке формата рекомендуется писать только спецификаторы форматов; количество спецификаторов должно быть равно числу аргументов в строке; каждый спецификатор имеет ту же структуру, что и в функции printf();
  • список аргументов может состоять из одного или нескольких аргументов; разделителем в списке аргументов служит [,];
  • в качестве аргументов функции используются только адреса переменных.

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

При использовании функции scanf() необходимо помнить два правила:

61. Файловый ввод/вывод данных в языке Си.

Основы Java. Урок 19: Передача аргументов по значению и по ссылке


Похожие статьи.

Понравилась статья? Поделиться с друзьями: