C установка IDE C структура програми C змінні C типи даних С функція printf C константи C арифметичні операції C операції порівняння і логічні операції C порозрядні операції C операції присвоювання C перетворення типів C умовні конструкції C цикли С масиви і рядки С функція scanf C препроцесор. Директива #include C #define директива C макроси C умовна компіляція C функції. Визначення та опис функцій C функції. Передача параметрів в функцію C функції. Повернення результату з функції C функції. Рекурсивні функції C область видимості змінних C зовнішні об'єкти C вказівники C вказівник. Операції з вказівниками C покажчики. Арифметика покажчиків C покажчики. Константи і покажчики C покажчики. Покажчики та масиви C покажчики. Масиви покажчиків, рядки і багаторівнева адресація C покажчики. Покажчики в параметрах функції C покажчики. Динамічна пам'ять C покажчики. Покажчик як результат функції C покажчики. Управління динамічної пам'яттю C покажчики. Покажчики на функцію C покажчики. Покажчики на функції як параметри і результати функцій C покажчики. Функції зі змінною кількістю параметрів C struct. Визначення структур C struct. Структури як елементи структур C struct. Покажчики на структури C struct. Масиви структур C struct. Структури і функції C struct. union об'єднання C struct. Бітові поля С file. Введення-виведення і робота з файлами C file. Читання і запис бінарних файлів C file. Читання і запис структур в файл C file. Читання і запис текстових файлів C file. Форматування вводу-виводу C file. Позиціонування в потоці C file. Консольне введення-виведення

C вказівники


Що таке покажчики

Покажчики є об'єктами, значеннями яких служать адреси інших об'єктів (змінних, констант, покажчиків) або функцій.

Покажчики - це невід'ємний компонент для управління пам'яттю в мові Сі.

Для визначення покажчика треба вказати тип об'єкта, на який вказує покажчик, і символ зірочки * . Наприклад, визначимо покажчик на об'єкт типу int :

int *p;

Поки покажчик не посилається на жоден об'єкт. Тепер дамо йому адресу змінної:

int x = 10;     // визначаємо змінну
int *p;         // визначаємо вказівник
p = &x;         // вказівник отримує адресу змінної

Вказівник зберігає адресу об'єкта в пам'яті комп'ютера. І для отримання адреси до змінної застосовується операція & . Ця операція застосовується тільки до таких об'єктів, які зберігаються в пам'яті комп'ютера, тобто до змінних і елементів масиву.

Що важливо, змінна x має тип int , і покажчик, який вказує на її адресу теж має тип int . Тобто має бути відповідність за типом.

Яку саме адресу має змінна x ? Для виведення значення вказівника можна використовувати спеціальний специфікатор %p :

#include <stdio.h>
 
int main(void)
{
    int x = 10;
    int *p;
    p = &x;
    printf("%p \n", p);     // 0060FEA8
    return 0;
}

У моєму випадку машинний адресу змінної x - 0060FEA8 . Але в кожному окремому випадку адреса може бути іншою. Фактично адреса являє цілочисельне значення, виражене в шістнадцятковому форматі.

Тобто в пам'яті комп'ютера є адреса 0x0060FEA8 , за якою розташовується змінна x . Так як змінна x представляє тип int , то на більшості архітектур вона буде займати наступні 4 байти (на конкретних архітектурах розмір пам'яті для типу int може відрізнятися). Таким чином, змінна типу int послідовно займає комірки пам'яті з адресами 0x0060FEA8 , 0x0060FEA9 , 0x0060FEAA , 0x0060FEAB .

І покажчик p буде посилатися на адресу, за якою розташовується змінна x , тобто на адресу 0x0060FEA8 .

Але так як покажчик зберігає адресу, то ми можемо за цією адресою отримати значення яке там зберігається, тобто значення змінної x . Для цього застосовується операція * або операція разіменування, тобто та операція, яка застосовується при визначенні вказівника. Результатом цієї операції завжди є об'єкт, на який вказує вказівник. Застосуємо дану операцію і отримаємо значення змінної x :

#include <stdio.h>
 
int main(void)
{
    int x = 10;
    int *p;
    p = &x;
    printf("Address = %p \n", p);
    printf("x = %d \n", *p);
    return 0;
}

// RESULT:
/*
Address = 0060FEA8
х = 10
*/

Використовуючи отримане значення в результаті операції разіменування ми можемо привласнити його іншій змінній:

int x = 10;
int *p  = &x;
int y = *p;
printf("x = %d \n", y); // 10

І також використовуючи покажчик, ми можемо змінювати значення за адресою, яка зберігається у вказівнику:

int x = 10;
int *p = &x;
*p = 45;
printf("x = %d \n", x);  // 45

Так як за адресою, на який вказує вказівник, розташовується змінна x , то відповідно її значення зміниться.

Створимо ще кілька вказівників:

#include <stdio.h>
 
int main(void)
{
    char c = 'N';
    int d = 10;
    short s = 2;
     
    char *pc = &c;          // отримуємо адресу змінної с типу char
    int *pd = &d;           // отримуємо адресу змінної d типу int
    short *ps = &s;         // отримуємо адресу змінної s типу short
     
    printf("Variable c: address=%p \t value=%c \n", pc, *pc);
    printf("Variable d: address=%p \t value=%d \n", pd, *pd);
    printf("Variable s: address=%p \t value=%hd \n", ps, *ps);
    return 0;
}

// RESULT:
/*
Variable C: address = value 0060FEA3 = N
Variable d: address = value 0060FE9C = 10
Variable s: address = value 0060FE9A = 2
*/

За адресами можна побачити, що змінні часто розташовані в пам'яті поруч, але не обов'язково в тому порядку, в якому вони визначені в тексті програми.


Наш партнер:
beta test mp3 playlist downloader