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

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

goto < метка >;

Он предназначен для передачи управления на оператор, помеченный меткой. Метка представляет собой идентификатор, оформленный по всем правилам идентификации переменных с символом «двоеточие» после него, например, пустой помеченный оператор:

m1: ;

Область действия метки - функция, где эта метка определена. В случае необходимости можно использовать блок.

Наиболее характерный случай использования оператора goto - выполнение прерывания (выхода) во вложенной структуре при возникновении грубых неисправимых ошибок во входных данных. И в этом случае необходимо, выйти из двух (или более) циклов, где нельзя использовать непосредственно оператор break, т.к. он прерывает только самый внутренний цикл:

for (...)

for (...)

{ ...

if ( ошибка ) goto error;

}

...

error: - операторы для устранения ошибки;

 

Если программа обработки ошибок нетривиальна и ошибки могут возникать в нескольких местах, то такая организация оказывается удобной.

Пример нахождения первого отрицательного числа в двумерном массиве:

for (i=0; i<N; i++)

for(j=0; j<M; j++)

{

if (v[i][j]<0) goto found;

... // Не найден

}

found: ... // Найден

 

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

found = 0;

for (i=0; i<N && !found; i++)

for (j=0; j<M && !found; j++)

found = v[i][j]<0;

if (found) ... // Найден

else ... // Не найден

Оператор continue

Этот оператор может использоваться во всех типах циклов, но не в операторах переключателя switch. Наличие оператора continue вызывает пропуск "оставшей­ся" части итерации и переход к началу следующей, т.е. досрочное завершение текущего шага и переход к следующему шагу.

В циклах while и do это означает непосредственный переход к проверочной части. В цикле for управле­ние передается на шаг коррекции, т.е. модификации выражения 3.

Фрагмент программы обработки только положительных элементов массива a, отрицательные значения пропускаются:

for ( i = 0; i<n; i++)

{ if( a[i]<0) continue;

... // обработка положительных элементов

}

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

 

Оператор break

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

 

Оператор return

Оператор return; производит досрочный выход из текущей функции. Он, так же возвращает значение результата функции: return <выражение>;

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

Пример 1:

float estim(float *x, int n) {

int i;

float y;

if ((!x)||(!n) {

error(x,n);

return 0;

}

for (y=i=0; i<n; i++) y+=x[i];

return y/n;

}

 

Пример 2:

void error(void *x, int n)

{

if (!x) printf("\nМассив не создан");

if (!n) printf("\nМассив пустой");

}

 

 

Указатели

 

Указатели

Указатель – это переменная, которая может содержать адрес некоторого объекта. Указатель объявляется следующим образом:

<тип> *< ID переменной-указателя>;

Например: int *a; double *f; char *w;

С указателями связаны две унарные операции & и *.

Операция & означает «взять адрес» операнда. Операция * имеет смысл - «значение, расположенное по указанному адресу».

Обращение к объектам любого типа как операндам операций в языке C может проводиться:

- по имени (идентификатору - ID);

- по указателю (операция косвенной адресации):

указатель = &ID_объекта;

Пример 1:

int x, // переменная типа int

*y; // указатель на элемент данных типа int

y=&x; // y - адрес переменной x

*y=1; // косвенная адресация указателем поля x, т.е.

// по указанному адресу записать 1 ® x=1;

 

Пример 2:

int i, j=8,k=5, *y;

y=&i;

*y=2; // i=2

y=&j;

*y+=i; // j+=i ® j=j+i ® j=j+2=10

y=&k;

k+=*y; // k+=k ® k=k+k = 10

(*y)++; // k++ ® k=k+1 = 10+1 = 11

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

int x[100], *y;

y = x; // Правильно - присваивание константы переменной

x = y; // Ошибка: в левой части - указатель-константа

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

int i,*x;

char *y;

x=&i; // x ® поле объекта int

y=(char *)x; // y ® поле объекта char

y=(char *)&i; // y ® поле объекта char

 

Значение указателя можно вывести на экран с помощью спецификации %p (pointer), результат выводится в шестнадцатеричном виде.

Рассмотрим фрагмент программы:

int a=5, *p, *p1, *p2;

p=&a; p2=p1=p;

++p1;p2+=2;

printf(“a=%d, p=%d, p=%p, p1=%p, p2=%p.\n”, a, p, p, p1, p2);

Результат выполнения: a=5, *p=5, p=FFC8, p1=FFCC, p2=FFD0.

Графически это выглядит так (адреса взяты символически):

 

   
  p p1 p2 400A  
                           

 

p=4000, p1=4002=(4000+1*sizeof(*p)) -> 4000+2 (int)

р2=4004=(4000+2*sizeof(*p)) -> 4000+2*2








Дата добавления: 2017-10-09; просмотров: 467;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.012 сек.