Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Архив WinRAR / 2_Посібник_С_002.doc
Скачиваний:
39
Добавлен:
17.05.2015
Размер:
2.7 Mб
Скачать

5.11 Покажчики на void

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

Це дозволяє їм вказувати на будь-які дані: від char до double. Але на заміну вони мають великі обмеження: дані на які він вказує неможуть безпосередньо роіменовуватись(що є логічним , так як ми не маємо типу), з цієї причини ми повинні вказувати тип перд тим як розіменувати дані на які вказує цей покажчик.

Приклад 26. Покажчик наvoid.

void increase (void* data, int psize)

{

if ( psize == sizeof(char) ) {

char* pchar; pchar=(char*)data; ++(*pchar);

}

else if (psize == sizeof(int) ){

int* pint; pint=(int*)data; ++(*pint); }

}

int main ()

{

char a = 'x';

int b = 1602;

increase (&a,sizeof(a));

increase (&b,sizeof(b));

printf("a= %c, b= %i \n", a, b);

}

Результати роботи програми:

Пояснення:

В функцію передаються по черзі адреса на зміну а(символьний тип) та на b (тип цілого числа). Функція приймає покажчик на void тому не важливо що ми передали з осовної програми. Але для роботи з переданими даними, нам потрібно розіменувати покажчик *data. Тут і виникає проблема. Так як ми не знаємо що за тип буле передано. Це вирішується конструкцією if…else де за допомого функції sizeof() ми можемо встановити розмір зміної за її покажчиком((!) Покажчик не залежить від типу! А лише від розрядності ОС, так для 32-х бітних він матиме розмір 4 байти, для 64-х бітних – 8 байтів) на комірку розміщення зміної. Таким чином маючи опції вибору (якщо розмір = 1 байт то це char, якщо =4 то це int)ми встановлюємо тип даних.

В Сі дозволяється створювати покажчики на покажчики, що вказують на дані чи інші покажчики. Для цього потрібно додавати при оголошені покажчик на покажчик ще один оператор «*»:

Приклад 27. Створення покажчика на покажчику.(рис. 5.12)

int x =0;

int *y = &x;

int **z = &y;

x = 'a';

y = &x;

z = &y;

Рисунок 5.12 – Покажчик на покажчику

Значення кожної змінної пишеться всередині кожної клітини, під клітинкою їх адреси в пам'яті.

Нове в цьому прикладі змінна с, яка може використовуватися в трьох різних представленнях, кожне з них буде мати інше значення:

Приклад 28. Різні види представлення.

z має тип символ ** і значення 1000

* z має тип символів * і значення 100

** z має тип символ і значення ‘a’

5.12 Арифметика покажчиків

Виконання арифметичних дій з покажчиками дещо відрізняється від дій з цілочисельними даними, даними з плаваючою точкою чи інших типів. Над ними можна виконувати дії додавання чи віднімання. Але ці дії мають різну поведінку з покажчиками залежно від розміру типу даних, до яких вони застосовуються.

Розглядаючи різні основні типи даних, ми бачили, що деякі займають більше або менше місця, ніж інші, у пам'яті. Наприклад char займає 1 байт, short займає 2 байта і long займає 4.

Приклад 29. Встановлення покажчиків на різні типи даних..

char * pchar;

short * pshort;

long * plong;

Нехай вони вказують на комірку 100.

Якщо ми виконаємо дії інкремента , то зміщення в памяті буде наступним:

Приклад 30. Здійснення інкременту.

pchar++; (аналог pchar = pchar + 1;)

pshort++; (аналог pshort = pshort + 1;)

plong++; (аналог plong = plong + 1;)

Рисунок 5.13 -

Таким чином при збільшені покажчик на один пункт ми зміщуємо його на відповідний розмір типу, тобто для char це 1 байт, для short це 2 байти, для long це 4 байти.

Приклад 31. Представлення операцій з покажчиками та результати їх використання.

#include <stdio.h>

#include <stdlib.h>

intmain (){

inta[] = {10,20,30,40,50 }, b;

int*p = a;

int*p2 = &a[3];

b = p2 - p;

printf(" 1) b = %i\n", b);

printf(" 2) *p = %i", *p);

printf(" *p++ = %d \n", *p++);

printf(" 3) *p = %i", *p);

printf(" *(++p) = %d \n", *(++p));

printf(" 4) *p = %i", *p);

printf(" *p+2 = %d \n", *p+2);

printf(" 5) *p = %i", *p);

printf(" *(p+2) = %d \n", *(p+2));

printf(" 6) *p = %i", *p);

printf(" *(p+8) = %d \n", *(p+8));

system("PAUSE");

returnEXIT_SUCCESS;

}

Результат роботи програми:

Розглянемо детальніше дії:

b у нас різниця між покажчиками р і р2. Так як р2 покажчик на третій елемент, а р покажчик на перший то різниця між ними = 3 (тобто 3 розміра типу int або 3*4=12 байт );

Виводить на екран значення на яке вказує покажчик р, а також демонструє реакцію покажчика на оператори * і ++ (операція * виконується першою, і лише потім збільшується значення покажчика);

Значення р було зміщено на одне значення і тепер воно вказує на другий елемент масиву. В другій дії значення р змінюється до розіменовування тому воно дорівнює наступному значенню в масиві, тобто послідовність дій наступна: спочатку йде інкременування (обов’язково перед р має бути ++ , інакше результат буде як в попередньому полі!), а потім розіменовування;

Тут лише виводиться значення на 2 більше ніж те ,на яке вказує покажчик.

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

Тут вказано що вихід за границі масиву ніяк не контролюється, тому потрібно зберігати обережність при використані покажчиків!

Соседние файлы в папке Архив WinRAR