Лекции по программированию

Автор: Пользователь скрыл имя, 17 Января 2011 в 18:57, курс лекций

Описание работы

6 тем.

Работа содержит 1 файл

Лекции.doc

— 615.00 Кб (Скачать)

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

Оператор безусловного перехода goto имеет формат:

    goto <метка>;

В теле той же функции  должна присутствовать ровно одна конструкция  вида:

    <метка>:<оператор>;

Оператор goto передает управление на помеченный меткой оператор. Рассмотрим пример использования оператора goto :

    #include <iostream>

    using namespace std;

    int main()

    {

      float x;

      metka:cout <<"x="; //оператор, помеченный меткой

      cin>>x;

      if (x) cout<<"y="<<1/x<<endl;

      else

      {

        cout<<"функция  не определена\n";

        goto metka;// передача управление метке

      }

      return 0;

    }

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

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

Мы с вами уже  применяли оператор break для выхода из оператора switch, аналогичным образом он может применяться для выхода из других операторов.

Оператор перехода к следующей итерации цикла continue пропускает все операторы, оставшиеся до конца тела цикла, и передает управление на начало следующей итерации (повторение тела цикла).Рассмотрим оператор continue на примере .

    #include <iostream>

    using namespace std;

    int main()

    {

      for (int i=1;i<100; ++i) // перебираем все числа от 1 до 99

      {

        if ( i % 2) continue ; //если число нечетное, то переходим к следующей итерации

        cout << i <<"\ t "; //выводим число на экран

      }

      return 0;

    }

В результате данной программы на экран будут выведены только четные числа из интервала  от 1 до 100, т.к. для нечетных чисел текущая итерация цикла прерывалась и команда cout<<i<<"\t" не выполнялась.

Оператор возврата из функции return завершает выполнение функции и передает управление в точку ее вызова. Данный оператор мы неоднократно использовали при разработке функций, возвращающих значение

    МАССИВЫ 

6.1. Указатели 
Когда компилятор обрабатывает оператор определения переменной, например, int a =50; , то он выделяет память в соответствии с типом int и записывает в нее значение 50. Все обращения в программе к переменной по ее имени заменяются компилятором на адрес области памяти, в которой хранится значение переменной. Программист может определить свои собственные переменные для хранения адресов области памяти. Такие переменные называются указателями. В С++различают три вида указателей – указатели на объект, на функцию и на void, которые отличаются друг от друга свойствами и допустимыми операциями. Указатель не является самостоятельным типом, он всегда связан с каким-либо другим – базовым типом.

Указатель на объект содержит адрес области памяти, в которой хранятся данные определенного типа (простого или составного). Простейшее объявление указателя на объект имеет следующий вид:

    <базовый тип> [<модификатор>] * <имя указателя>;

где базовый тип – имя типа переменной, адрес которой будет содержать переменная указатель; тип может быть любым, кроме ссылки (см. следующий раздел)и битового поля (см. справочники по С++);

модификатор необязателен и может иметь значение: near , far или huge (см. справочники по С++). По умолчанию устанавливается модификатор near. Нам этого будет достаточно для решения задач, поэтому при описании указателей модификатор явным образом указывать не будем.

Примеры:

    int * a ; //указатель  на целочисленное значение

    int **x; //указатель  на указатель на целочисленное значение

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

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

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

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

1) присваивание указателю  адреса существующего объекта:

· с помощью операции получения адреса:

    int a =50; //целая переменная

    int * x =& a ; //указателю  присваивается адрес целой переменной  а

    int * y (& a ); //указателю  присваивается адрес целой переменной  а

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

    int *z=x; //указателю  присваивается адрес, хранящийся  в х

· с помощью имени  массива или функции (рассмотрим позже).

2) присваивание указателю  адреса области памяти в явном  виде:

    int *p=(int *) 0xB8000000;

где 0xB8000000– шестнадцатеричная  константа, ( int *) – операция явного приведения типа к типу указатель на целочисленное значение.

3) присваивание пустого  значения:

    int *x=NULL;

    int *y=0;

где NULL стандартная  константа, определенная как указатель  равный 0

4) выделение участка  динамической памяти и присваивание ее адреса указателю:

    int *a = new int; //1

    int *b = new int (50); //2

В строке 1 операция new выполняет выделение достаточного для размещения величины типа int участка динамической памяти и записывает адрес начала этого участка в переменную . Память под переменную aвыделяется на этапе компиляции. В строке2, кроме действий описанных выше, производится инициализация выделенной динамической памяти значением 50.

Освобождение памяти, выделенной с помощью операции new, должно выполняться с помощью операции delete. При этом переменная-указатель сохраняется и может инициализироваться повторно. Пример использования операции delete:

    delete a; 

    delete []b;

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

Операция  разадресации (*) предназначена для доступа к значению, адрес которой хранится в указателе. Эту операцию можно использовать как для получения значения, так и для его изменения. Рассмотрим пример:

    #include <iostream>

    using namespace std;

    int main()

      int *a=new int(50); //инициализация указателя на целочисленное значение

      int b=*a; //переменной b присваивается значение, хранящееся по адресу указателя а

      cout<<"adress \t *a\t b\n";

      /*выводим:  адрес, хранящийся  в указателе а;  значение,хранящееся  по адресу

      указателя а; значение переменной b*/

      cout <<a<<"\t" <<*a<<"\t" <<b<<endl;

      *a=100; //изменяем значение, хранящееся по адресу указателя а

      cout <<a<<"\t" <<*a<<"\t" <<b<<endl;

      return 0;

    }

Результат работы программы:

Adress * a b
00355900 50 50
00355900 100 50

Замечания

1) При запуске данной  программы на вашем компьютере будет выведен другой адрес, записанный в указателе a. Это связано текущим состоянием динамической памяти.

2) При попытке выполнить  команду a=100; возникнет ошибка, т.к. – переменная-указатель, в ней может храниться только адрес ОП, но не целочисленное значение.

3) При попытке выполнить  команду *b=100; также возникнет ошибка, т.к. операция разадресации может применяться только к указателям, а не к обычным переменным.

Операция  получения адреса (&) применима к величинам, имеющим имя и размещенным в ОП. Рассмотрим пример :

    #include<iostream>

    using namespacestd;

    int main()

      int b=50;

      int *a=&b; //в указатель a записали адрес переменной b

      cout<<"adress \t *a\t b\n";

      cout <<a <<"\t"<<*a<<"\t" <<b<<endl;

      b+=10; //1

      cout <<a <<"\t"<<*a<<"\t" <<b<<endl;

      *a=100; //2

      cout <<a <<"\t"<<*a<<"\t" <<b<<endl;

      return 0; 

    }

Результат работы программы:

Address *a b
0012FF60 50 50
0012FF60 60 60
0012FF60 100 100

Замечание . После того, как в указатель а был записан адрес переменной b,мы получили доступ к одной и той же области памяти через имя обычной переменной и через указатель. Поэтому, изменяя в строке1 значение переменной b, мы фактически изменяем значение по адресу, записанному в указателе а. И наоборот (см. строку 2).

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

Более подробно эти  операции будут рассмотрены при  изучении массивов. Однако хотелось обратить внимание на следующий пример:

    #include <iostream>

    using namespace std ;

    int main()

    {

      int *a =new int(50);

      cout <<"adress \t *a\n";

      cout <<a <<"\t"<<*a<<endl;

      (* a )++; // 1 увеличивается на 1 значение, хранящееся по адресу указателя а

      cout <<a<<"\t" <<*a<<endl;

Информация о работе Лекции по программированию