Унарная операция взятия адреса (&) позволяет получить адрес операнда, хранящего свое значение в оперативной памяти (точнее, адрес первого байта, если под значение отводится несколько байт). Объект, предназначенный для хранения адреса операнда, называется указателем и описывается по аналогии с описанием переменной с тем лишь отличием, что перед именем указателя ставится звездочка (*). Например:
int a = 5, b = 10, c; //описание переменных a, b, c и инициализация a и b
int *pa, *pb; //описание указателей pa и pb, которые пока ни на что не указывают
pa = &a; //указатель pa теперь будет указывать на переменную а
pb = &b; //указатель pb теперь будет указывать на переменную b
Последние 3 строки можно записать короче:
int *pa = &a, *pb = &b; //описание и инициализация указателей pa и pb
Унарная операция разадресации (*) позволяет получить значение операнда по значению указателя на этот операнд:
c = *pa; //c = 5
c = *pb; //c = 10
c = *pa + *pb; //c = 15
pb = pa;
c = *pb; //c = 5
Чтобы указатель ни на что не указывал, нужно приравнять его нулю или, что то же самое, приравнять встроенной константе NULL, которая введена специально для работы с указателями:
pa = 0; //указателей pa теперь ни на что не указывает
pb = NULL; //указателей pb теперь ни на что не указывает
c = *pa; //ошибка
c = *pb; //ошибка
Оставшиеся 4 унарные операции (строка 1), будут рассмотрены позднее. Отметим лишь следующее:
Операция () обозначает вызов функции (например main(), printf(…), scanf(…) и др.).
Операция [] обеспечивает доступ к элементам массива.
Операции. (точка) и -> обеспечивают доступ к полям структуры.
Тема 4. Операторы
Операторы языка вместе с его типами данных определяют круг задач, которые можно решать с помощью этого языка. Язык С реализует типичный набор операторов для языка программирования общего назначения. Операторы подразделяются на исполняемые и неисполняемые. Исполняемые операторы задают действия над данными. Неисполняемые операторы служат для описания данных и называются операторами описания или просто описаниями.
Любое выражение, завершающееся точкой с запятой, рассматривается как оператор. Выполнение исполняемого оператора заключается в вычислении выражения. Частным случаем выражения является пустой оператор «;». Он используется, когда по синтаксису оператор требуется, а по смыслу – нет. Примеры:
int a=1, b=2, c=3; //описание переменных a, b, c и их инициализация
a++;
c *= a + b;
printf(“zdes byl vasia”); //вызов функции printf стандартной библиотеки stdio
while(1); //бесконечный цикл из пустого оператора
Блок или составной оператор, – это последовательность описаний и операторов,, заключенная в фигурные скобки. Блок воспринимается компилятором как один оператор и может использоваться всюду, где синтаксис требует одного оператора, а алгоритм – нескольких. В частности, блок может содержать один оператор, или быть пустым.
Описания, содержащиеся внутри блока, называются локальными, т.к. они описывают объекты (например, переменные), которые существуют только внутри блока и будут разрушены сразу же при выходе из него. Соответственно описания, не принадлежащие ни одному из блоков, называются глобальными и описывают объекты, существующие до конца работы программы.
Структура программы
Программа на языке С состоит из функций, описаний и директив препроцессора. Одна из функций должна иметь имя main. Выполнение программы начинается с первого оператора этой функции.
директивы препроцессора
глобальные описания
int func1()
{
локальные описания функции func1
исполняемые операторы функции func1
}
short func2()
{
локальные описания функции func2
исполняемые операторы функции func2
}
void main()
{
локальные описания функции main
исполняемые операторы функции main
}
Обычно функция используется для вычисления некоторого значения, поэтому перед именем функции указывается его тип. Если функция не должна возвращать результат вычислений, указывается тип void.
Тело функции является блоком (составным оператором) и, следовательно, заключается в фигурные скобки.
Функции не могут быть вложенными.
Если какая-то функция, например func1, уже описана, то ее можно использовать в теле другой, описанной ниже функции, например func2 или main. Кроме того, в теле любой функции можно использовать функции, описанные в стандартных библиотеках языка С, которые подключаются с помощью директив препроцессора.
Пример: задаются координаты (x, y) точки, принадлежащей окружности с центром в начале координат. Необходимо найти площадь круга, ограниченного этой окружностью.
#include <stdio.h>
#include <math.h>
float x, y; //описание глобальных переменных x, y
const double PI = 3.14; //описание глобальной именованной константы PI
double GetRadius()
{
double z; //описание локальной переменной z
z = pow(x, 2) + pow(y, 2); //вызов функции pow стандартной библиотеки math
z = sqrt(z); //вызов функции sqrt стандартной библиотеки math
return z; //возврат вычисленного значения радиуса окружности
}
double GetCircleArea()
{
double z; //описание локальной переменной z
z = GetRadius(); //вызов уже описанной функции GetRadius
z = PI * pow(z, 2); //вызов функции pow стандартной библиотеки math
return z; //возврат вычисленного значения площади круга
}
void main()
{
double z; //описание локальной переменной z
printf(“Введите значения x и y:\n”);
scanf(“%f%f”, &x, &y);
z = GetCircleArea();
printf(“Площадь круга равна %f”, z);
}
Упрощенный вариант той же программы:
#include <stdio.h>
#include <math.h>
void main()
{
float x, y;
printf(“Введите значения x и y:\n”);
scanf(“%f%f”, &x, &y);
printf(“Площадь круга равна %f”, 3.14*(pow(x, 2) + pow(y, 2)));
}