Студопедия — Операции с указателями
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Операции с указателями






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

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

char a;//переменная типа char

char * p = new char;/*выделение памяти под указатель и под динамическую переменную типа char */

*p = 'Ю'; a = *p;//присваивание значения обеим переменным

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

#include <stdio.h>

int main()

{unsigned long int A=0Xсс77ffaa;

unsigned int* pint =(unsigned int *) &A;

unsigned char* pchar =(unsigned char *) &A;

printf(" | %x | %x |", *pint, *pchar);}

на IBM PC выведет на экран строку:

| ffaa | aa |

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

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

Присваивание без явного приведения типов допускается только указателям типа void* или если тип указателей справа и слева от операции присваивания один и тот же.

Присваивание указателей данных указателям функций (и наоборот) недопустимо.

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

Инкремент перемещает указатель к следующему элементу массива, декремент — к предыдущему.

Фактически значение указателя изменяется на величину sizeof(тип).

Разность двух указателей — это разность их значений, деленная на размер типа в байтах. Суммирование двух указателей не допускается.

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

*p++ = 10;

То же самое можно записать подробнее:

*p = 10; p++;

Выражение (*p)++, напротив, инкрементирует значение, на которое ссылается указатель.

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

Ссылки

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

тип & имя;

где тип — это тип величины, на которую указывает ссылка, & — оператор ссылки, означающий, что следующее за ним имя является именем переменной ссылочного типа, например:

int kol;

int& pal = kol;//ссылка pal — альтернативное имя для kol

const char& CR = '\n';//ссылка на константу

· Переменная-ссылка должна явно инициализироваться при ее описании, кроме случаев, когда она является параметром функции, описана как extern или ссылается на поле данных класса.

· После инициализации ссылке не может быть присвоена другая переменная.

· Тип ссылки должен совпадать с типом величины, на которую она ссылается.

· Не разрешается определять указатели на ссылки, создавать массивы ссылок и ссылки на ссылки.

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

Операция над ссылкой приводит к изменению величины, на которую она ссылается.

 

 

Лекция 8. Массивы

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

Конечная именованная последовательность однотипных величин называется массивом. Описание массива в программе отличается от описания простой переменной наличием после имени квадратных скобок, в которых задается количество элементов массива (размерность):

float a [10]; //Пример описания массива из 10 вещественных чисел

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

int b[5] = {3, 2, 1};// b[0]=3, b[1]=2, b[2]=1, b[3]=0, b[4]=0

Размерность массива может быть задана только целой положительной константой или константным выражением.

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

Пример 1
#include <iostream.h> int main(){ const int n = 10; int marks[n] = {3, 4, 5, 4, 4}; for (int i = 0, sum = 0; i<n; i++) sum += marks[i]; cout << "Сумма элементов: " << sum;}

Размерность массивов предпочтительнее задавать с помощью типизированных констант.

Динамические массивы создают с помощью операции new, при этом необходимо указать тип и размерность, например:

float *p = new float [100];

В этой строке создается переменная-указатель на float, в динамической памяти отводится непрерывная область, достаточная для размещения 100 элементов вещественного типа, и адрес ее начала записывается в указатель p. Динамические массивы нельзя при создании инициализировать, и они не обнуляются.

Преимущество динамических массивов состоит в том, что их размерность может не быть константой.

Память, зарезервированная под динамический массив с помощью new [], должна освобождаться оператором delete [], а память, выделенная функцией malloc — посредством функции free, например:

delete [] p; free (q);

Размерность массива не указывается, но квадратные скобки обязательны.

Многомерные массивы задаются указанием каждого измерения в квадратных скобках, например, оператор

int matr [6][8];

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

Для доступа к элементу многомерного массива указываются все его индексы, например, matr[i][j].

Инициализация многомерного массива:

int mass2 [][]={ {1, 1}, {0, 2}, {1, 0} };

int mass2 [3][2]={1, 1, 0, 2, 1, 0};

Для создания многомерного массива в динамической памяти необходимо указать все его размерности (первая из них может быть переменной):

matr = new int [a] [b];

Освобождение памяти из-под массива с любым количеством измерений выполняется с помощью операции delete []. Указатель на константу удалить нельзя.

Пример 2
Программа определяет в целочисленной матрице номер строки, которая содержит наибольшее количество элементов, равных нулю. #include <stdio.h> int main(){ const int nstr = 4, nstb = 5;//Размерности массива int b[nstr][nstb]; int i, j; for (i = 0; i<nstr; i++)//Ввод массива for (j = 0; j<nstb; j++) scanf("%d", &b[i][j]); int istr = -1, MaxKol = 0; for (i=0; i<nstr; i++){//Просмотр массива по строкам int Kol = 0ж for (j = 0; j<nstb; j++)if (b[i][j]==0)Kol++; if (Kol>MaxKol){istr = i; MaxKol = Kol;} } printf(" Исходный массив:\n"); for (i = 0; i<nstr; i++){ for (j = 0; j<nstb; j++)printf("%d ", b[i][j]); printf("\n");} if (-1 == istr)printf("Нулевых элементов нет"); else printf("Номер строки: %d", istr); return 0;}

Строки

Строка представляет собой массив символов, заканчивающийся нуль-символом. Нуль-символ — это символ с кодом, равным 0, что записывается в виде управляющей последовательности '\0'. По положению нуль-символа определяется фактическая длина строки. Строку можно инициализировать строковым литералом:

char str[10] = "Vasia";

В этом примере под строку выделяется 10 байт, 5 из которых занято под символы строки, а шестой — под нуль-символ. Если строка при определении инициализируется, ее размерность можно опускать (компилятор сам выделит соответствующее количество байт):

char str[] = "Vasia";//Выделено и заполнено 6 байт

Оператор

char *str = "Vasia"

создает не строковую переменную, а указатель на строковую константу.

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

Библиотека предоставляет возможности копирования, сравнения, объединения строк, поиска подстроки, определения длины строки и т.д. (возможности библиотеки описаны в разделе «Функции работы со строками и символами»), а также содержит специальные функции ввода строк и отдельных символов с клавиатуры и из файла.

Пример 3
Пример (программа запрашивает пароль не более трех раз). #include <stdio.h> #include <string.h> int main(){ char s[5], passw[] = "kuku";/*passw – эталонный пароль. Можно описать как *passw = "kuku";*/ int i, k = 0; for (i = 0;!k && i<3; i++){ printf("\nвведите пароль:\n"); gets(s);//функция ввода строки if (strstr(s,passw))k = 1;// функция сравнения строк } if (k) printf("\nпароль принят"); else printf("\nпароль не принят");}

При работе со строками часто используются указатели.

Пример 4
Рассмотрим процесс копирования строки srcв строку dest. #include <iostream.h> int main(){ char *src = new char [10]; char *dest = new char [10], *d = dest; cin << src; while (*d++ = *src++); cout << dest;}

 







Дата добавления: 2015-08-12; просмотров: 471. Нарушение авторских прав; Мы поможем в написании вашей работы!



Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...

Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...

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

Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...

ТЕХНИКА ПОСЕВА, МЕТОДЫ ВЫДЕЛЕНИЯ ЧИСТЫХ КУЛЬТУР И КУЛЬТУРАЛЬНЫЕ СВОЙСТВА МИКРООРГАНИЗМОВ. ОПРЕДЕЛЕНИЕ КОЛИЧЕСТВА БАКТЕРИЙ Цель занятия. Освоить технику посева микроорганизмов на плотные и жидкие питательные среды и методы выделения чис­тых бактериальных культур. Ознакомить студентов с основными культуральными характеристиками микроорганизмов и методами определения...

САНИТАРНО-МИКРОБИОЛОГИЧЕСКОЕ ИССЛЕДОВАНИЕ ВОДЫ, ВОЗДУХА И ПОЧВЫ Цель занятия.Ознакомить студентов с основными методами и показателями...

Меры безопасности при обращении с оружием и боеприпасами 64. Получение (сдача) оружия и боеприпасов для проведения стрельб осуществляется в установленном порядке[1]. 65. Безопасность при проведении стрельб обеспечивается...

МЕТОДИКА ИЗУЧЕНИЯ МОРФЕМНОГО СОСТАВА СЛОВА В НАЧАЛЬНЫХ КЛАССАХ В практике речевого общения широко известен следующий факт: как взрослые...

СИНТАКСИЧЕСКАЯ РАБОТА В СИСТЕМЕ РАЗВИТИЯ РЕЧИ УЧАЩИХСЯ В языке различаются уровни — уровень слова (лексический), уровень словосочетания и предложения (синтаксический) и уровень Словосочетание в этом смысле может рассматриваться как переходное звено от лексического уровня к синтаксическому...

Плейотропное действие генов. Примеры. Плейотропное действие генов - это зависимость нескольких признаков от одного гена, то есть множественное действие одного гена...

Studopedia.info - Студопедия - 2014-2024 год . (0.01 сек.) русская версия | украинская версия