Рефераты. Массивы

оператори:

b = *р + 1 (взяти те, на що вказує р, додати до нього 1, а результат

привласнити змінній b.

До покажчиків можна застосувати операцію привласнення. Покажчики одного і

того ж типу можуть використовуватися в операції привласнення, як і будь-які

інші змінні. Розглянемо приклад. #include void mai n() { int x=

1 0;

int *p, *g;

p=&x;

g=p;

printf("%p", р); /* друк вмісту р */

printf("%p",g); /* друк вмісту g */

р г і n t f (" % d % d ", x, * g); / * друк величини хі величини за

адресою g*/

} Результат: FFF4 FFF4 10 10

У цьому прикладі приведена ще одна специфікація формату функції

printf() - %р. Цей формат використовується для друку адреси пам'яті в

шістнадцятковій формі.

Не можна створити змінну типу void, але можна створити покажчик на тип

void. Покажчику на void можна привласнити покажчик будь-якого іншого типу.

Однак при зворотному привласненні необхідно використати явне перетворення

покажчика на void/void *pv;

float f, *pf;

pf=&f;

pv=pf;

pp=(fioat*) pv;

У мові С допустимо привласнити покажчику будь-яку адресу пам'яті.

Однак, якщо оголошений покажчик на ціле

int *р;

а за адресою, яка привласнена даному покажчику, знаходиться змінна х типу

float, то при компіляції програми буде видане повідомлення про помилку в

рядку

р=&х;

Цю помилку можна виправити, перетворювавши покажчик на int до типу

покажчика на float явним перетворенням типу:

p=(int*)&x;

Але при цьому втрачається інформація про те, на який тип вказував

початковий покажчик.

Як і над іншими типами змінних, над покажчиками можна виробляти

арифметичні операції: складання і віднімання (операції ++ і є окремими

випадками операцій складання і віднімання). Арифметичні

дії над покажчиками мають свої особливості. Виконаємо найпростішу

програму

#include void main() { і n t x= 1 0;

int *p, *g;

p=&x;

g=p;

printf("%p", p); /* друк вмісту p */ printf("%p", p++); /* друк вмісту g

*/ } Результат: FFF4 FFF6

Після виконання цієї програми ми побачимо, що при операції ++1

значення покажчика р збільшилося не на 1, а на 2. І це правильне, оскільки

нове значення покажчика повинно вказувати не на наступну адресу пам'яті, а

на адресу наступного цілого. А ціле, як ми пам'ятаємо, займає 2 байти. Якби

базовий тип покажчика був не int, a double, то були б надруковані адреси,

відмінні на 8 (Результат:

FFEE FFF6), саме стільки байт пам'яті займає змінна типу double, тобто при

кожній операції ++р значення покажчика буде збільшуватися на кількість

байт, що займаються змінної базового типу покажчика .

Операції над покажчиками не обмежуються тільки операціями ++ і

--. До покажчиків можна додавати деяке ціле або відняти ціле. int *p=2000;

float *p=2000;

Р=Р+3; р=р+10;

Результат: р=2006 Результат: р=2040

Загальна формула для обчислення значення покажчика після виконання

операції р=р+п; буде мати вигляд

=+п*

Можна також відняти один покажчик з іншого. Так, якщо р і pi

-покажчики на елементи одного і того ж масиву, то операція р-рі дає такий

же результат, як і віднімання індексів відповідних елементів масиву.

Інші арифметичні операції над покажчиками заборонені, наприклад не

можна скласти два покажчики, помножити покажчик на число і т.д.

|#include void rnai n() Результат: Error UKAZAT2.CPP |

|p-g=0008 |14: Invalid pointer addition |

Покажчики можна порівнювати. Застосовні всі 6 операцій:

, =, =, == і !=.

Порівняння р < g означає, що адреса, що знаходиться в р, менше адреси,

що знаходиться в g.

Якщо рід вказують на елементи одного масиву, то індекс елемента, на

який вказує р, менше індексу масиву, на який вказує g.

ЗВ'ЯЗОК ПОКАЖЧИКІВ І МАСИВІВ

Будь-який доступ до елемента масиву за допомогою операції

індексування може бути виконаний за допомогою покажчика (що в загальному

випадку працює швидше).

Декларація

int a[10]

визначає масив а розміру 10:

[pic]

Запис а[і] посилає нас до і-му елемента масиву. int *р;

р=&а[0]; /* р вказує на нульовий елемент а або містить адресу елемента а[0]

*/

[pic]

х = *р; => х = а[0], У= *(Р+1); => У = а[1];

Значення змінної типу масив (ім'я масиву) є адреса

нульового елемента масиву.

р = &а[0]; => р = а;

*(а+і) ^ а[і] &а[і] => а+і

Результат буде один і той же. Перевага використання другого варіанту

полягає в тому, що арифметичні операції над покажчиками виконуються швидше,

якщо ми працюємо з підряд йдучими елементами масиву. Якщо ж вибір елементів

масиву випадковий, то швидше і більш наочна робота з індексами.

Між ім'ям масиву і покажчиком,-виступаючим в ролі імені масиву, існує

одна відмінність. Покажчик змінна, тому можна написати р = а або р++. Але

ім'я масиву не є змінною, і записи типу а = р або а++ не допускаються.

Дуже часто доводиться працювати над обробкою текстів, т. е. з масивами

рядків. Як ми пам'ятаємо, в мові С рядок - це масив символів, що

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

практично, одні і ті ж дії.

#incl ude

#include

void main()

{ char *p, str[]="String From Letters in Different Registers";

/* Рядок, що Складається з Букв в Різних Регістрах; */ int і=0; printf(

"Рядок Буде Надрукований Заголовними Буквами");

while (str[i]) printf("%c", toupper(str[i++]));

p=str; printf(" Рядок Буде Надрукований Малими Буквами");

while (*p) printf("%c", tolower(*p++)); }

Якщо в цих прикладах замінити рядок на англійській мові на рядок,

набраний російськими буквами, то ніякого перетворення букв в рядкові або,

навпаки, в прописні не станеться. Це пов'язано з тим, що стандартні функції

toupper() і tolower () аналізують значення

1

0 аргументу і повертають те ж саме значення, якщо він не є відповідно малою

або великою буквою латинського алфавіту. Якщо ж аргумент є малою буквою

латинського алфавіту, то значенням функції toupper() буде відповідна

велика буква (точніше, код цієї букви). Функція tolower () змінює код лише

великих букв латинського алфавіту. Прототипи цих функцій знаходяться в

заголовному файлі ctype.h.

МАСИВИ ПОКАЖЧИКІВ

Покажчики, як і змінні будь-якого іншого типу, можуть об'єднуватися в

масиви. Оголошення масиву покажчиків на 10 цілих чисел має вигляд int

*x[10] ;

Кожному з елементів масиву можна привласнити адресу; наприклад, третьому

елементу привласнимо адресу цілої змінної у:

х[2]=&у;

щоб знайти значення змінною у, можна написати *х(2].

Наведемо приклад використання масиву покажчиків. Частіше за все це

буває зручно при обробці масиву рядків.

/* you must run. exe-file to watch the rezult of this program. Перегляд

файлів в поточному каталозі з одним з шести розширень */

#include

#include ^include

#include

main()

{char ch, s[80], *ext[]={"exe", "corn", "cpp", "c", "pas", "*"};

clrscr();

for(;;) {do { printf( "Файли з розширенням:^");

printf("1. exe\n"); "printf( 2. com\n"); "printf( 3. cpp\n"); "pnntf( 4.

з \ n ");

printf("5. pas\n"); printf("6. *\n"); //any extension printf("7.

quit\n");

printf("BauJ вибір(1-7):)( \n");

ch=getche();

printf("\n");

} while (ch'7');

if (ch=='7') break;

strcpy(s, "dir *."); strcat(s, ext[ch-'0'-1 ]); strcat(s, "/p");

system(s);} }

Тут функція system() - бібліотечна функція, яка примушує операційну

систему DOS виконати команду, що є аргументом цієї функції.

Взагалі рядкова константа в мові С асоціюється з адресою початку рядка в

пам'яті, тип рядка виходить char* (покажчик на тип char). Тому можливо і

активно використовується наступне привласнення:

char *pc;

"рс = Hello, World!";

У мові С можлива також ситуація, коли покажчик вказує на покажчик. У

цьому випадку опис буде мати наступний вигляд:

int -*'*point;

[pic]

point має тип покажчик на покажчик на int. Відповідно, щоб набути

цілочисельного значення змінною, на яку указьіваеі point, треба у

вираженні використати **point.;

Приклад використання:

11

^include

void m а і n()

{ int i, pi, ppi;

і =7; pi=&i;

p p i = & p i;

printf( "i = %d pi = %p ppi = %p \n", i, pi, ppi);

*pi++;

printf( "i = %d pi = %p ppi = %p \n", i, pi, ppi);

**ppi = 12;

printf( "i = %d pi = %p ppi = %p \n", i, pi, ppi);

}

ІНІЦІАЛІЗАЦІЯ ПОКАЖЧИКІВ

Після того як покажчик був оголошений, але до того, як йому було

привласнене якесь значення, покажчик містить невідоме значення. Спроба

використати покажчик до привласнення йому якогось значення є неприємною

помилкою, оскільки вона може порушити роботу не

тільки вашої програми, але і операційної системи. Навіть якщо цього не

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

буде досить складно.

Вважають, що покажчик, який вказує в "нікуди", повинен мати значення

null, однак і це не робить його "безпечним". Після того, як він попаде в

праву або ліву частину оператора привласнення, він знову може стати

"небезпечним".

З іншого боку нульовий покажчик можна використати, наприклад, для

позначення кінця масиву покажчиків.

Якщо була спроба привласнити яке-небудь значення тому, на що вказує

покажчик з нульовим значенням, система видає попередження, що з'являється

під час роботи програми (або після закінчення роботи програми) "Null

pointer assignment". Поява цього повідомлення є мотивом для пошуку

використання неініціалізувати покажчика в програмі.

Страницы: 1, 2



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.