Зміст курсу
Основи C
Основи C
Функції, Масиви та Два Вказівники
Функції з вказівниками
Давайте експериментувати з базовою функцією для зміни значення наших даних. Наприклад, уявіть, що вам потрібна функція, яка перетворює кіло-Оми в Оми (1 кОм = 1000 Ом).
Main
#include <stdio.h> void Ohm(double R) { R = R * 1000; } int main() { double r = 1.5; // kOhm printf("The value of resistance before using function: %f\n", r); Ohm(r); printf("The value of resistance after using function: %f", r); return 0; }
Наша спроба змінити значення змінної r
була невдалою. Це тому, що функція отримує копію змінної r
, а не саме значення.
Щоб наша програма працювала як задумано, нам потрібно передати адресу змінної r
у функцію. В результаті, функція Ohm
повинна приймати double*
замість просто double
.
Main
#include <stdio.h> void Ohm(double* R) { // dereferencing the entered address and changing the object it points to *R = *R * 1000; } int main() { double r = 1.5; // kOhm printf("The value of resistance before using function: %f\n", r); Ohm(&r); printf("The value of resistance after using function: %f\n", r); return 0; }
Зверніть увагу, що ми посилаємося на змінну r
двічі. Після виклику функції Ohm
, значення r
змінюється. Це тому, що функція отримала оригінальну адресу змінної r
, а не просто копію, і потім змінила значення за цією адресою.
Крім того, функція може повернути вказівник на об'єкт, який вона створила:
Main
#include <stdio.h> #include <stdlib.h> int* func() { int* x = (int*)malloc(sizeof(int)); printf("Address into function: %p\n", x); return x; } int main() { int* pointerToFunc = func(); printf("Address after using function: %p\n", pointerToFunc); return 0; }
Чи є масиви просто вказівниками?
Що ви передбачаєте, що станеться, якщо до адреси додати число?
Main
#include <stdio.h> int main() { int x = 100; int* pX = &x; printf("Address: %p | Adress + 1: %p", pX, pX + 1); return 0; }
Коли до адреси додається число (pX + 1
), це дає адресу наступної комірки пам'яті!
Давайте напишемо цикл, щоб пройти "послідовність" ОЗП:
Main
#include <stdio.h> int main() { int* pX = NULL; // pointer to `int` type (4 bites) for (int i = 0; i < 3; i++) printf("Address: %p\n", pX + i); return 0; }
Ми спроектували три кроки вперед. З отриманих адрес очевидно, що існує чітка ієрархія.
Оскільки тип int
займає 4 байти, ми просуваємося на 4 байти з кожним кроком. Ця поведінка вражаюче нагадує масив!
Здається, масив по суті є фіксованою адресою (представленою ім'ям масиву) у поєднанні з виділеною пам'яттю. Індекси елементів представляють їх зміщення від адреси початкового елемента!
Цю ідею можна підтвердити наступною програмою:
Main
#include <stdio.h> int main() { int array[] = {1,2,3,4,5}; printf("Address of array: %p\n", array); for(int i = 0; i < 5; i++) printf("Value: %d | Address of element with index %d: %p\n", *(array + i), i , &array[i]); return 0; }
Як спостерігається, ми не проходимо безпосередньо через масив. Ми використовуємо лише його адресу, зокрема адресу його початкового елемента.
Дякуємо за ваш відгук!