Арифметика покажчиків, масиви.
Масиви, оператор індексації, базові операції над покажчиками
Практичні приклади - функції strcpy і strlen
замість висновку
Корисні вправи
Список літератури
За винятком перерахованих, інші арифметичні операції над покажчиками не визначені - їх використання призведе до помилок компіляції програми. Так, помилку компіляції викличе спроба складання двох покажчиків або порівняння покажчиків на об'єкти різного типу, спроба вирахування з покажчика числа з плаваючою точкою і ін. Ті ж арифметичні операції, що можуть застосовуватися до покажчиків, в переважній більшості випадків мають сенс тільки в контексті роботи з масивами (з цієї причини арифметика покажчиків і масиви зазвичай розглядаються одночасно).
Масиви, оператор індексації, базові операції над покажчиками
Масив - це упорядкований набір (колекція) однотипних об'єктів, що розміщуються в єдиному блоці пам'яті послідовно один за одним. Однотипні об'єкти, що входять до складу масиву, називають елементами масиву. Кожному елементу масиву відповідає порядковий номер - індекс. Індексація елементів починається з нуля. початковий (перший) елемент масиву має індекс 0, наступний за ним (другий) - індекс 1, наступний за другим (третій) - індекс 2 і т. д. Останній елемент масиву з k елементів має індекс k - 1.
Мал. 1. Масив з k елементів
Більш конкретно принципи роботи з масивами і базові операції над покажчиками розглянемо на наступному невеликому прикладі.
Масиви, так само як і будь-які інші види об'єктів, можуть бути розміщені як в стеці, так і в динамічної пам'яті. Спочатку розглянемо розміщення масивів в стеці. Код першого рядка функції main виконує таке розміщення:
Відповідно до семантикою оператора індексації, тут здійснюється перехід до об'єкта масиву vec з індексом 2, після чого отриманого об'єкту присвоюється нове значення - в відведені під цей об'єкт осередки пам'яті записується число 103 (рис. 6).
Мал. 7. Покажчик на елемент масиву з k об'єктів
Якщо p вказує на об'єкт, який не є елементом масиву, то результат складання p з цілим числом не визначений (причому до помилки компіляції таке складання не приведе - помилка виникне в процесі виконання програми).
У нашому випадку vec - це покажчик на початковий елемент масиву, отже, при обчисленні виразу vec + 2 ми повинні отримати покажчик на другий після початкового, т. Е. На третій елемент масиву. В умовах наших припущень про розташування об'єктів в пам'яті маємо:
vec + 2 = vec + 2 * sizeof (short) = 0xF838 + 2 * 2 = 0xF838 + 4 = 0xF83C.
Якщо роздрукувати значення елемента масиву з індексом 2 і об'єкта, на який вказує vec + 2:
Наведені вище фрагменти коду є також прикладами випадків, коли неважливо, який саме оператор інкремента - префіксний або постфіксний - використовується для збільшення значення змінної. У цих фрагментах оператор інкремента потрібен тільки для збільшення значення індексу i. безпосередньо повертається їм значення не використовується.
Можливо, вираз while (* p ++ = * s ++) на перший погляд і здається незрозумілим, однак такий запис зручна, на практиці подібний код зустрічається. Про важливість його розуміння говорить і той факт, що розібраний нами приклад розглянуто також в книзі Бйорна Страуструпа «Мова програмування C ++» [1] і книзі Брайана Керніган і Денніса Рітчі «Мова програмування C» [2]. Додатково про важливість знання аспектів реалізації функції strcpy можна почитати в книгах Джоела Спольскі «Джоел про програмування" [6] і "Джоел: і знову про програмування» [10].
На закінчення розділу розглянемо операцію віднімання одного покажчика з іншого. З використанням даної операції реалізується, зокрема, функція обчислення довжини рядка strlen стандартної бібліотеки C / C ++.
замість висновку
Значна частина помилок при роботі з пам'яттю пов'язана з її витоками, т. Е. З не звільненням або неправильним звільненням раніше виділеної динамічної пам'яті. Зокрема, поширеною помилкою є видалення масиву об'єктів оператором delete замість оператора delete []. Така підміна операторів може ніяк не виявитися при видаленні масиву об'єктів вбудованого типу, але при руйнуванні масиву складних об'єктів, наприклад масиву рядків (об'єктів типу std :: string), використання оператора delete призведе до того, що буде вилучена тільки перший рядок, інші залишаться в пам'яті. Для виявлення помилок подібного роду створені спеціальні інструментальні засоби, одне з яких було розглянуто в першій частині статті.
Таким чином, робота з пам'яттю вимагає особливої уваги і акуратності, некоректне поводження з нею призводить до досить важко виявляються помилок і суттєвих втрат часу при розробці програмного забезпечення.
Корисні вправи
- Виконайте введення з клавіатури двох цілочисельних масивів, сформуйте і виведіть на екран третій масив, одержуваний вставкою всіх елементів другого масиву після заданого елемента першого.
- Виконайте введення з клавіатури двох рядків, сформуйте і виведіть на екран третій рядок, що є конкатенацией введених.