Операції над змінними типу вказівник.
1. Присвоєння.
Вказівнику присвоюється адреса (це може бути, наприклад, ім’я масиву, або результат операції отримання адреси змінної &: &a). Якщо a[], то a = = &a[0], a (або &a) є константою і її значення не може змінюватися.
2. Розкриття вказівника (посилання на вказівник).
Операція *p дає величину, яка зберігається за адресою, на яку вказує p (див. приклад вище).
Якщо ptr = &a, то val = *ptr те саме, що val = a.
3. Отримання адреси вказівника.
Змінна типу вказівник, як і всі решта, має адресу і значення. Операція & показує адресу, за якою знаходиться сам вказівник.
4. Операції збільшення і зменшення.
Ці операції здійснюються згідно правил адресної арифметики, описаних вище.
5. Різниця вказівників на елементи масиву показує, на якій відстані в масиві вони знаходяться.
Якщо оголошено масив a[], то зміст наступних виразів такий:
ptr=a;
*ptr - значення a[0]
*(ptr+i) - значення a[i]
ptr+I - адреса a[i] ( &a[i] )
Вказівники, як звичайні змінні, можуть бути зібрані в масивах за правилами утворення масивів.
Для символьних масивів існує декілька особливостей. Символьний масив (рядок) може бути оголошений за допомогою вказівника таким чином:
char *mlit = “Функція sin”;
У статичній пам’яті виділяється 12 байтів для рядка. Крім цього, виділяється ще кілька (2 або 4) байтів пам’яті для змінној mlit, яка є вказівником. Спочатку ця змінна вказує на початок рядка, але її значення може змінюватися за правилами адресної арифметики (наприклад, можна писати ++mlit). *mlit не треба оголошувати статичною змінною, оскільки ініціалізувався не масив, а змінна типу вказівник.
Двомірний символьний масив є послідовністю рядків, можливо різної довжини, що залежить від способу оголошення цього масиву (через ідентифікатор масиву або через вказівник). Наприклад, якщо оголосити двомірний символьний масив через ідентифікатор з вказанням розмірностей:
static char symb [3][5] = “abcd”,
“efgh”,
“i”;
то неповний третій рядок буде доповнений нулями і масив займе 15 байтів. Це незручно, оскільки неефективно використовується пам'ять, а також програміст повинен правильно вказати довжину рядків. Якщо ж застосувати масив вказівників на char:
char *menu [6] = “Sinus”,
“Cosinus”,
“Logarithm”,
“Exponenta”,
“Parabola 2”,
“Parabola 3” ;
то компілятор сам підрахує необхідну кількість комірок пам’яті і розмістить усі рядки послідовно без зайвих пропусків. Тут оголошено масив із шести вказівників на char. Кожен елемент цього масиву вказує на початок відповідного рядка. За допомогою індексних виразів можна здійснювати доступ як до кожного рядка, так і до кожној літери. Так, операція menu[1] вкаже на початок другого рядка, а операція *(menu[1]+3) дасть значення четвертого елемента другого рядка, тобто літеру 's'.
Завдання
1. Створити массив із N елементів кожен з яких є цілочисельного типу і задається довільною залежністю, використовуючи для його заповнення один із відомих вам циклів. Роздрукувати значення елементів масиву в головній функції. Передати масив у створену функцію користувача, в якій кожен елемент поділити навпіл, та роздрукувати з точністю 4 знаки. Повернути модифікований масив у викликаючу функцію, роздрукувати, порівняти значення, зробити висновки.
2. Змодифікувати програму обчислення суми арифметичној прогресії, створеної у попередній роботі таким чином, щоб масив був оголошений не локально, а передавався за допомогою формальних параметрів у обидві функції.
2. Дослідити на прикладах особливості вказівників.
#include <stdio.h>
#define PR(x) printf("x=%d,*x=%d,&x=%d\n",x,*x,&x)
main()
static int arr[] = 100,200,300;
int *ptr1, *ptr2;
ptr1 = arr;
ptr2 = &arr[2];
PR(ptr1); ptr1++; PR(ptr1);
PR(ptr2); ++ptr2; PR(ptr2); printf("ptr2-ptr1 = %d\n",ptr2-ptr1);
#include <stdio.h>
#define PR(value) printf("value=%d\t",(value)) #define NL putchar('\n')
int a[] = 0,1,2,3,4;
main()
int i,*p;
/*1*/ for(i=0;i<=4;i++) PR(a[i]); NL;
/*2*/ for(p=&a[0];p<=&a[4];p++) PR(*p); NL;
/*3*/ for(p=&a[0],i=1;i<=5;i++) PR(p[i]); NL;
/*4*/ for(p=a,i=0;p+i<=a+4;p++,i++) PR(*(p+i)); NL;
/*5*/ for(p=a+4;p>=a;p--) PR(*p); NL;
/*6*/ for(p=a+4,i=0;i<=4;i++) PR(p[-i]); NL;
/*7*/ for(p=a+4; p>=a;p--) PR(a[p-a]); NL;
