Фраза "Структурная переменная описывается с помощью переменной структурного типа" на мой Взгляд является тафтология. Из нее сложно понять суть утверждения. Хотелось бы полке понятного описания. |
Функции
Все функции в программе, написанной на языке Си, равноправны. Каждая из них может вызывать любую другую функцию и, в свою очередь, каждая может быть вызвана любой другой функцией. Это делает функции языка Си несколько отличными от процедур Паскаля, поскольку процедуры в Паскале могут быть вложены в другие процедуры, причем процедуры, описанные в разных процедурах, являются недоступными для процедур, описанных в других независимых процедурах.
У процедуры main есть специфика. Она заключается в том, что после сборки программы, состоящей из нескольких функций, ее выполнение начинается с первого оператора функции main( ).
Каждая функция может вызвать саму себя. Действие, состоящее в том, что функция вызывает сама себя, называется рекурсией.
Рекурсивной называют функцию, которая прямо или косвенно сама вызывает себя. Именно возможность прямого или косвенного вызова позволяет различать прямую или косвенную рекурсию. При каждом обращении к рекурсивной функции создается новый набор объектов автоматической памяти, локализованных в теле функции. Функция называется косвенно рекурсивной в том случае, если она содержит обращение к другой функции, содержащей прямой или косвенный вызов определяемой (первой) функции. В этом случае по тексту определения функции ее рекурсивность (косвенная) может быть не видна. Если в теле функции явно используется вызов этой же функции , то имеет место прямая рекурсия.
Локальные переменные
Переменные, известные только одной функции, а именно той, которая их содержит, называются локальными переменными. Теперь мы подчеркиваем, что локальные переменные являются действительно локальными. Даже в том случае, когда мы используем одно и то же имя для переменных в двух различных функциях, компилятор считает их разными переменными.
Нахождение адресов
В результате выполнения операции & определяется адрес ячейки памяти, которая соответствует переменной. Если age - имя переменной, то &age - ее адрес. Можно представить себе адрес как ячейку памяти, но можно рассматривать его и как метку, которая используется компилятором для идентификации переменной. Предположим, мы имеем оператор
age=105;
Пусть также адрес ячейки, где размещается переменная age - 15125. В результате выполнения оператора
printf("%d %d\n", age, &age);
получим 105 15125.
Указатели, первое знакомство
Указатель - некоторое символическое представление адреса. В описанном примере &age означает указатель на переменную age. Фактический адрес - это число, а символическое представление адреса &age является константой типа указатель. Адрес ячейки, отводимой переменной age, в процессе выполнения программы не меняется. В языке Си имеются и переменные типа указатель. Точно так же как значением переменной типа char является символ, а значением переменной типа int - целое число, значением переменной типа указатель служит адрес некоторой величины. Если мы дадим указателю имя ptr, то сможем написать, например, такой оператор:
ptr = &age; /* присваивает адрес age переменной ptr */
Мы говорим в этом случае, что ptr указывает на age. Различие между двумя формами записи, ptr и &age, заключается в том, что ptr - это переменная, в то время как &age - константа. В случае необходимости мы можем сделать так, чтобы переменная ptr указывала на какой-нибудь другой объект:
ptr = &name; /*ptr указывает на name, а не на age*/
Теперь значением переменной ptr является адрес переменной name.
Операция косвенной адресации *
Предположим, мы знаем, что в переменной ptr содержится ссылка на переменную name. Тогда для доступа к значению этой переменной можно воспользоваться операцией косвенной адресации *:
val = *ptr; /* определение значения, на которое указывает ptr */
Последние два оператора, взятые вместе, эквивалентны следующему:
val = name;
Описание указателей
int *pi; /*указатель на переменную типа целого*/ char *pc; /*указатель на символьную переменную*/ float *pf, *pg; /* указатели на переменные с плавающей точкой*/
Спецификация типа задает тип переменной, на которую ссылается указатель, а символ звездочка ( * ) определяет саму переменную как указатель. Описание вида int *pi говорит , что pi - это указатель и что *pi - величина типа int.
При вызове функции информация о переменной может передаваться функции в двух видах. Если мы используем форму обращения
function1(x);
происходит передача значения переменной x. Если же мы используем форму обращения
function2(&x);
происходит передача адреса переменной x. Первая форма обращения требует, чтобы определение функции включило в себя формальный аргумент того же типа, что и x:
function1(num) int num;
Вторая форма обращения требует, чтобы определение функции включало в себя формальный аргумент, являющийся указателем на объект соответствующего типа:
function2(&ptr) int *ptr;