17537

ДОСЛІДЖЕННЯ ВКАЗІВНИКІВ ТА ДИНАМІЧНОЇ ПАМ’ЯТІ в С++

Лабораторная работа

Информатика, кибернетика и программирование

ЛАБОРАТОРНА РОБОТА № 6 ДОСЛІДЖЕННЯ ВКАЗІВНИКІВ ТА ДИНАМІЧНОЇ ПАМ’ЯТІ Мета роботи – дослідити механізми створення та використання вказівників та механізми роботи з динамічною пам’яттю. Завдання Вивчити поняття вказівників та методи виділення динамічної п...

Украинкский

2013-07-04

85 KB

12 чел.

ЛАБОРАТОРНА РОБОТА № 6

ДОСЛІДЖЕННЯ ВКАЗІВНИКІВ ТА ДИНАМІЧНОЇ ПАМ’ЯТІ

Мета роботи – дослідити механізми створення та використання вказівників та механізми роботи з динамічною пам’яттю.

Завдання

  1.  Вивчити поняття вказівників та методи виділення динамічної пам’яті.
  2.  Написати програму на мові С++ для дослідження опису та використання вказівників (покажчиків), та механізм виділення динамічної пам’яті, відповідно варіанту.

Теоретичні відомості

Вказівник (покажчик) - це змінна, що містить адресу іншої змінної. Вказівники дуже широко використовуються у мові C.  Це відбувається тому, що є певні операції, які можна виконувати тільки за допомогою покажчиків. Також  покажчики дозволяють писати більш компактні і ефективні програми

 Так як вказівник містить адресу об'єкта, то за допомогою вказівника можна отримати  "непрямий" доступ до цього об'єкта. Припустимо, що х - змінна, наприклад, типу int, а рх - покажчик. Унарна операція & отримує адресу об'єкта, так що оператор

px = &x;
присвоює адресу x змінної px; кажуть, що px "вказує" на x. Операція & відноситься тільки до змінних і елементів масиву, конструкції виду:

&(х-1) и &3

є не правильними.

Унарна операція *  розіменування  отримує значення, яке лежить за певною адресою. Отже, якщо y теж має тип int, то

y = *px;

присвоює y вміст того, на що вказує px.

Так, послідовність операторів:

int *px;     // об’ява змінної вказівника

px = &x; // отримання адреси змінної х

Вказівник - це не просто адреса, а адреса величини певного типу. Вказівник xPtr - адреса цілої величини. Визначити адреси величин інших типів можна наступним чином:

 unsigned long *lPtr;      

// Вказівник на ціле число без знака

 char * cp;      // Вказівник на байт

Адресна арифметика

З вказівниками можна виконувати не тільки операції привласнення і звернення за адресою, але і ряд арифметичних операцій. Перш за все, вказівники одного і того ж типу можна порівнювати за допомогою стандартних операцій порівняння. При цьому порівнюються значення вказівників, а не значення величин, на які дані вказівники посилаються. Так, у наведеному нижче прикладі результат першої операції порівняння буде хибним:

int x = 10;

int y = 10;

int *xPtr = &x;

int *yPtr = &y;

// Порівнюємо вказівники

if (xPtr == yPtr) {

    cout <<"Вказівники рівні" <<endl;

} else {

    cout <<"Вказівники не рівні" <<endl;

}

 

// Порівнюємо значення, на які вказують вказівники

if (*xPtr == *yPtr) {

     cout <<"Значення рівні" <<endl;

} else {

     cout <<"Значення нерівні" <<endl; }

Проте результат другої операції порівняння буде істинним, оскільки змінні x і y мають одне і те ж значення.

Крім того, над вказівниками можна виконувати обмежений набір арифметичних операцій. До вказівника можна додати ціле число або відняти від нього ціле число. Результатом додавання до вказівником одиниці є адреса наступної величини типу, на який посилається вказівник, у пам'яті. Пояснимо це на малюнку. Нехай xPtr - вказівник на ціле число типу long, а cp - вказівник на тип char. Починаючи з адреси 1000, в пам'яті розташовані два цілих числа. Адреса другого - 1004 (в більшості реалізацій Сі + + під тип long виділяється чотири байти). Починаючи з адреси 2000, в пам'яті розташовані об'єкти типу char.


Мал. 1. Адресна арифметика.

Розмір пам'яті, виділеної для числа типу long і для char, різний. Тому адресу при збільшенні xPtr і cp теж змінюється по-різному. Однак і в тому, і в іншому випадку збільшення вказівника на одиницю означає перехід до наступної в пам'яті величиною того ж типу. Додаток або віднімання будь-якого цілого числа працює за тим же принципом, що і збільшення на одиницю. Вказівник зсувається вперед (при додаванні позитивного числа) або назад (при відніманні позитивного числа) на відповідну кількість об'єктів того типу, на який показує вказівник.

Вказівники одного і того ж типу можна один з одного віднімати. Різниця Вказівників показує, скільки об'єктів відповідного типу може поміститися між зазначеними адресами.

Зв'язок між масивами і вказівниками

Між вказівниками і масивами існує певний зв'язок. Припустимо, є масив з 100 цілих чисел. Запишемо двома способами програму підсумовування елементів цього масиву:

long array [100];

long sum = 0;

for (int i = 0; i <100; i++)

     sum += array[i];

Те ж саме можна зробити за допомогою вказівників:

long array[100];

long sum = 0;

for(long *ptr = &array[0]; ptr <&array [99] + 1; ptr++)

     sum += *ptr;

Елементи масиву розташовані в пам'яті послідовно, і збільшення вказівника на одиницю означає зміщення до наступного елементу масиву. Згадка імені масиву без індексів перетвориться на адресу його першого елемента:

 for (long *ptr = array; ptr <&array[99] + 1; ptr++)

     sum += *ptr;

Динамічний розподіл пам'яті використовується, насамперед, тоді, коли заздалегідь невідомо, скільки об'єктів знадобиться в програмі і знадобляться вони взагалі.  Якщо необхідно динамічно створити масив, то потрібно використовувати операцію new:

int *a =  new int [100];

На відміну від визначення змінної типу масив, розмір масиву в операції new може бути довільним, в тому числі обчислюваним в ході виконання програми. (Нагадаємо, що при оголошенні змінної типу масив розмір масиву повинен бути константою.)

Звільнення пам'яті, виділеної під масив, має бути виконане за допомогою наступної операції delete

 delete []a;

Динамічний масив:

int n;

cin>>n; // n — розмірність масиву

int *mas=new int[n]; // виділення пам’яті під масив

delete [] mas; // звільнення пам’яті

Адресація базова *(pa + i) і індексна *pa++:

Якщо ра вказує на а[0], то *(ра + 1) посилається на вміст а[1], ра + і – адреса а[і], а  *(ра + і) – вміст а[і]

Базова індексація дає доступ до першого (базового елементу) від якого отримують доступ усі інші елементи

За допомогою індексної адресації можна отримати доступ до кожного елементу окремо.

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

cout<<*(pa+i) << \t;

}

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

cout<<*pa++ << \t;

}

Вказівники  та динамічний розподіл пам'яті - дуже потужні засоби мови. З їх допомогою можна розробляти гнучкі і досить ефективні програми. Зокрема, одна з областей застосування С++ - системне програмування - практично не могла б існувати без можливості роботи з вказівниками. Проте можливості, які отримує програміст при роботі з вказівниками, накладають на нього і велику відповідальність.

Варіанти

  1.  Згенерувати і вивести на екран масив з 10 випадкових чисел від -40 до 60, та створити і вивести на екран новий масив, що складається з додатних елементів масиву. Визначити максимальний елемент серед додатних елементів.
  2.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -130 до 160.  Визначити суму  перших трьох і останніх шести додатних елементів. Чисто n вводить користувач.
  3.  Згенерувати і вивести на екран масив з 10 випадкових чисел від -140 до 100, та створити і вивести на екран новий масив, що складається з парних елементів масиву. Визначити мінімальний елемент серед додатних елементів.
  4.  Згенерувати і вивести на екран масив з 10 випадкових чисел від -50 до 50. Ненульові елементи масиву перенести в інший масив, розташувати їх у зворотному порядку.
  5.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -120 до 120.  Вивести номер передостаннього додатного елемента. Чисто n вводить користувач. 
  6.  Згенерувати і вивести на екран масив з 10 випадкових чисел від -50 до 50. Додатні елементи масиву перенести в інший масив №1, а від’ємні елементи перенести в інший масив №2.
  7.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -120 до 120. Створити новий масив з  елементів масиву, що більше -50 і менше 50.
  8.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -120 до 120.  Чисто n вводить користувач. Знайти добуток другого й четвертого елементів, більших 30.
  9.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -45 до 65.  Чисто n вводить користувач. Максимальний елемент поміняти місцями з мінімальним елементом.
  10.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -100 до 100.  Чисто n вводить користувач. Останній від'ємний елемент поміняти місцем з максимальним елементом.
  11.  Згенерувати і вивести на екран масив з 10 випадкових чисел від
    -140 до 140, та сформувати інший масив з елементів масиву, які більше 30
  12.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -100 до 100.  Чисто n вводить користувач. Вивести номери двох найбільших елементів масиву.
  13.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -160 до 100.  Чисто n вводить користувач. Максимальний елемент поміняти місцями з четвертим.
  14.  Згенерувати і вивести на екран масив з 10 випадкових чисел від
    -140 до 140, та створити масив, значення якого перебувають між значенням третього елемента і максимальним значенням.
  15.  Згенерувати і вивести на екран масив з цілого числа n випадкових чисел від -150 до 145.  Чисто n вводить користувач. Знайти добуток номерів найменших елементів серед додатних.

Контрольні питання

  1.  Яка операція використовується для отримання адреси змінної?
  2.  Яка операція використовується для звернення за адресою?
  3.  Що таке динамічна пам'ять.
  4.  Що таке вказівник
  5.  Для чого використовується вказівник.
  6.  Як вказівник відображається в програмному коді
  7.  Яке застосування операцій new і delete
  8.  Яке призначення операцій & та *
  9.  Як оголошується змінна типу вказівник
  10.  Какой результат следующего выражения ?

int *a; int b[2]; a = b;

b[0] = 7; b[1] = 10; *a++; cout << *a;


 

А также другие работы, которые могут Вас заинтересовать

76780. Вспомогательные аппараты мышц 185.15 KB
  Лесгафта на взаимоотношение между работой и строением мышц и костей; мышцы – синергисты и антагонисты. Фасция – соединительнотканная оболочка в виде футляра вокруг мышцы создающая опору для мышечного брюшка и отграничивающая мускул чем устраняется трение между мышцами. Фасции подразделяются на: поверхностные которые служат мягкой опорой для подкожной клетчатки и отделяют ее от глубже расположенных фасций и мышц; собственные которые окружают отдельные мышцы и мышечные группы и часто называются по области где располагаются: плечевая...
76781. Мышцы и фасции груди 183.63 KB
  Кроме того на груди поверхностные мышцы распределяют на передние боковые и задние соответственно делению грудной стенки на переднюю боковую и заднюю области. Внутренние межреберные мышцы 11 имеют направление волокон перпендикулярное наружным и заполняют промежуток от грудины до угла ребра где переходят в заднюю мембрану. Подреберные мышцы начинаются от углов XXII ребер и перекидываясь через одно два ребра прикрепляются к внутренней поверхности вышележащих ребер.
76782. Мышцы живота 183.58 KB
  Мышцы передней брюшной стенки прямые: правая и левая – начинаются узкими длинными пучками от лобковых гребней и лобкового симфиза прикрепляются к наружной поверхности хрящей YYII ребер широкими лентовидными полосами; по своему ходу мышечные пучки прерываются 34 сухожильными поперечными перемычками которые срастаются с влагалищем прямых мышц; влагалище прямой мышцы образуется из апоневрозов косых и поперечных мышц живота так что передняя и задняя стенки его имеют неодинаковое строение: над межостистой линией обе стенки влагалища...
76783. Паховый канал 180.59 KB
  Его четыре стенки образуются: верхняя – нижними краями внутренней косой и поперечной мышц живота; нижняя – паховой связкой важным клиникоанатомическим ориентиром особенно при отличии паховой грыжи от бедренной и наоборот; передняя – апоневрозом наружной косой мышцы; задняя – поперечной фасцией рыхло прилежащей к париетальной брюшине. Медиальнонижняя оконечность кольца образована загнутой связкой из латеральной ножки апоневроза и паховой связки; латеральноверхняя округлость состоит из межножковых фиброзных волокон собственной...
76784. Диафрагма. Послойное строение диафрагмы 181.04 KB
  Послойное строение диафрагмы сверху вниз: диафрагмальная плевра: правая и левая между ними по средине – диафрагмальный листок перикарда; подплевральная клетчатка и верхняя диафрагмальная фасция часть внутригрудной фасции; мышца диафрагмы и ее сухожильное растяжение; нижняя диафрагмальная фасция – часть внутрибрюшной фасции; подбрюшинная клетчатка и диафрагмальная брюшина. Все три части в середине диафрагмы сходятся образуя фиброзное растяжение – сухожильный центр который со стороны грудной полости имеет в середине перикардиальное...
76785. Мышцы шеи 193.78 KB
  Поверхностная мышечная группа состоит из подкожной и грудино-ключично-сосцевидной мышц, окруженных поверхностной пластинкой шейной фасции. Средняя группа (мышцы, связанные с подъязычной костью) включает надподъязычные мышцы: челюстно-подъязычную, подбородочно-подъязычную, шилоподъязычную, двубрюшную и подподъязычные мышцы: лопаточно-подъязычную, грудино-подъязычную, грудино-щитовидную, щитоподъязычную.
76786. Мимические мышцы 181.98 KB
  В процессе развития мимические мышцы совершают большие миграции но сохраняют иннервацию от лицевого нерва. Лицевые мышцы сокращаясь формируют выражение лица мимику участвуют в регуляции дыхания артикуляции речи жевании. Мышцы свода черепа Надчерепная мышца состоит из трех частей: лобной затылочной и сухожильного шлема между ними который образует апоневроз затылочнолобной мышцы.
76787. Жевательные мышцы 184.17 KB
  Из промежуточной части – с началом от внутренней поверхности скуловой дуги и суставного бугорка височной кости и прикреплением к наружной поверхности ветви нижней челюсти ниже ее вырезки. Из глубокой части начинающейся от внутренней поверхности скуловой дуги и прикрепляющейся к наружной поверхности мыщелкового отростка и сухожилию височной мышцы. Височная мышца заполняет веерообразно височную яму и состоит: из поверхностного слоя начинающегося от верхней височной линии теменной кости височной фасции и прикрепляющегося к наружной...
76788. Мышцы и фасции плечевого пояса 183 KB
  Под мышцей в области большого плечевого бугра располагается поддельтовидная синовиальная сумка. Кровоснабжение – из торакоакромиальной пекторальной задней огибающей артерий которые анастомозируют в области плечевого сустава с артериями надлопаточной из подключичной окружающей лопатку из подмышечной образуя артериальную сеть. Дельтовидный мускул иннервируется от подмышечного нерва плечевого сплетения.