C++ Указатели с примери

Какво представляват указателите?

In C++, указателят препраща към променлива, която съдържа адреса на друга променлива. Подобно на обикновените променливи, указателите имат тип данни. Например, указател от тип integer може да съдържа адреса на променлива от тип integer. Указател от символен тип може да съдържа адреса на променлива от символен тип.

Трябва да видите указател като символно представяне на адрес на паметта. С указатели програмите могат да симулират извикване по препратка. Те могат също да създават и манипулират динамични структури от данни. в C++, указателна променлива се отнася до променлива, сочеща към конкретен адрес в памет, посочена от друга променлива.

Адреси в C++

Да разбера C++ указатели, трябва да разберете как компютрите съхраняват данни.

Когато създадете променлива във вашия C++ програма, тя получава известно място в паметта на компютъра. Стойността на тази променлива се съхранява в зададеното място.

За да знаете мястото в паметта на компютъра, където се съхраняват данните, C++ осигурява & (референтен) оператор. Операторът връща адреса, който заема променливата.

Например, ако x е променлива, &x връща адреса на променливата.

Синтаксис на декларация на указател

Декларацията на C++ приема следния синтаксис:

datatype *variable_name; 
  • Типът данни е основният тип на указателя, който трябва да е валиден C++ тип данни.
  • variable_name трябва да бъде името на променливата на указателя.
  • Звездичката, използвана по-горе за деклариране на указател, е подобна на звездичката, използвана за извършване на операция за умножение. Това е звездичката, която маркира променливата като указател.

Ето пример за валидни декларации на указател в C++:

int    *x;    // a pointer to integer
double *x;    // a pointer to double
float  *x;    // a pointer to float
char   *ch     // a pointer to a character

Оператор за препратка (&) и оператор за отклоняване (*)

Операторът за справка (&) връща адреса на променливата.

Операторът за дерефериране (*) ни помага да получим стойността, която е съхранена в адрес на паметта.

Например:

Ако имаме променлива с име num, съхранена на адрес 0x234 и съхраняваща стойност 28.

Референтният оператор (&) ще върне 0x234.

Операторът за дерефериране (*) ще върне 5.

Пример 1:

#include <iostream>
using namespace std;
int main() {
	int  x = 27;  
	int  *ip;        
	ip = &x;       
	cout << "Value of x is : ";
	cout << x << endl;
	cout << "Value of ip is : ";
	cout << ip<< endl;
	cout << "Value of *ip is : ";
	cout << *ip << endl;
	return 0;
}

Изход:

Оператор за препратка (&) и оператор за отклоняване (*)

Как работи това:

Оператор за препратка (&) и оператор за отклоняване (*)

Ето екранна снимка на кода:

Оператор за препратка (&) и оператор за отклоняване (*)

Обяснение на кода:

  1. Импортирайте заглавния файл на iostream. Това ще ни позволи да използваме функциите, дефинирани в заглавния файл, без да получаваме грешки.
  2. Включете пространството от имена std, за да използвате неговите класове, без да го извиквате.
  3. Извикайте функцията main(). Логиката на програмата трябва да се добави в тялото на тази функция. { маркира началото на тялото на функцията.
  4. Декларирайте целочислена променлива x и й присвоете стойност 27.
  5. Декларирайте указателна променлива *ip.
  6. Съхранявайте адреса на променлива x в променливата указател.
  7. Отпечатайте малко текст на конзолата.
  8. Отпечатайте стойността на променливата x на екрана.
  9. Отпечатайте малко текст на конзолата.
  10. Отпечатайте адреса на променлива x. Стойността на адреса се съхранява в променливата ip.
  11. Отпечатайте малко текст на конзолата.
  12. Отпечатайте стойността на съхранена на адреса на показалеца.
  13. Програмата трябва да върне стойност при успешно изпълнение.
  14. Край на тялото на функцията main().

Указатели и масиви

Масивите и указателите работят въз основа на свързана концепция. Има различни неща, които трябва да имате предвид, когато работите с масиви, които имат указатели. Самото име на масива обозначава основния адрес на масива. Това означава, че за да присвоите адреса на масив към указател, не трябва да използвате амперсанд (&).

Например:

p = arr;

Горното е правилно, тъй като arr представлява адреса на масивите. Ето още един пример:

p = &arr;

Горното е невярно.

Можем имплицитно да преобразуваме масив в указател. Например:

int arr [20];
int * ip;

По-долу е валидна операция:

ip = arr;

След горната декларация ip и arr ще бъдат еквивалентни и ще споделят свойства. Въпреки това, различен адрес може да бъде присвоен на ip, но не можем да присвоим нищо на arr.

Пример 2:

Този пример показва как да преминете през масив с помощта на указатели:

#include <iostream>
using namespace std;
int main() {
	int *ip;
	int arr[] = { 10, 34, 13, 76, 5, 46 };
	ip = arr;
	for (int x = 0; x < 6; x++) {
		cout << *ip << endl;
		ip++;
	}
	return 0;
}

Изход:

Указатели и масиви

Ето екранна снимка на кода:

Указатели и масиви

Обяснение на кода:

  1. Декларирайте целочислена указателна променлива ip.
  2. Декларирайте масив с име arr и запазете 6 цели числа в него.
  3. Присвояване на arr на ip. IP и arr ще станат еквивалентни.
  4. Създайте for цикъл. Променливата на цикъла x е създадена за итерация на елементите на масива от индекс 0 до 5.
  5. Отпечатайте стойностите, съхранени на IP адреса на указателя. Една стойност ще бъде върната на итерация и ще бъдат извършени общо 6 повторения. Краят е a C++ ключова дума, която означава крайния ред. Това действие ви позволява да преместите курсора на следващия ред, след като всяка стойност бъде отпечатана. Всяка стойност ще бъде отпечатана на отделен ред.
  6. За да преместите показалеца на следващата int позиция след всяка итерация.
  7. Край на for цикъл.
  8. Програмата трябва да върне нещо при успешно изпълнение.
  9. Край на тялото на функцията main().

NULL указател

Ако няма точен адрес, който да бъде присвоен, тогава променливата на указателя може да бъде присвоена NULL. Това трябва да стане по време на декларацията. Такъв указател е известен като нулев указател. Стойността му е нула и е дефинирана в много стандартни библиотеки като iostream.

Пример 3:

#include <iostream>
using namespace std;
int main() {
	int  *ip = NULL;
	cout << "Value of ip is: " << ip;
	return 0;
}

Изход:

NULL указател

Ето екранна снимка на кода:

NULL указател

Обяснение на кода:

  1. Декларирайте указателна променлива ip и й присвоете стойност NULL.
  2. Отпечатайте стойността на променливата ip на показалеца заедно с някакъв текст на конзолата.
  3. Програмата трябва да върне стойност при успешно завършване.
  4. Край на тялото на функцията main().

Указатели на променливи

с C++, можете да манипулирате данни директно от паметта на компютъра.

Пространството на паметта може да бъде назначено или преназначено по желание. Това става възможно благодарение на променливите указатели.

Променливите указатели сочат към конкретен адрес в паметта на компютъра, към който сочи друга променлива.

Може да се декларира по следния начин:

int *p;

Или,

int* p;

В примера you сме декларирали променливата указател p.

Той ще съдържа адрес от паметта.

Звездицата е операторът за дереференция, който означава указател към.

Указателят p сочи към цяло число в адреса на паметта.

Пример 4:

#include <iostream>

using namespace std;
int main() {
	int *p, x = 30;
	p = &x;
	cout << "Value of x is: " << *p;
	return 0;
}

Изход:

Указатели на променливи

Ето екранна снимка на кода:

Указатели на променливи

Обяснение на кода:

  1. Декларирайте указателна променлива p и променлива x със стойност 30.
  2. Присвоете адреса на променлива x на p.
  3. Отпечатайте стойността на променливата на показалеца p заедно с някакъв текст на конзолата.
  4. Програмата трябва да върне стойност при успешно завършване.
  5. Край на тялото на функцията main().

Приложение на указатели

Функции в C++ може да върне само една стойност. Освен това всички променливи, декларирани във функция, се разпределят в стека за извикване на функция. Веднага щом функцията се върне, всички променливи на стека се унищожават.

Аргументите към функцията се предават по стойност и всяка модификация, извършена върху променливите, не променя стойността на действителните променливи, които се предават. Следният пример помага да се илюстрира тази концепция: -

Пример 5:

#include <iostream>

using namespace std;
void test(int*, int*);
int main() {
	int a = 5, b = 5;
	cout << "Before changing:" << endl;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	test(&a, &b);

	cout << "\nAfter changing" << endl;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	return 0;
}

void test(int* n1, int* n2) {
	*n1 = 10;
	*n2 = 11;
}

Изход:

Приложение на указатели

Ето екранна снимка на кода:

Приложение на указатели

Обяснение на кода:

  1. Създайте прототип на функция с име test, която ще приема два целочислени параметъра.
  2. Извикайте функцията main(). Ще добавим логиката на програмата в нейното тяло.
  3. Декларирайте две цели променливи a и b, всяка със стойност 5.
  4. Отпечатайте малко текст на конзолата. Endl (краен ред) ще премести курсора, за да започне печат на следващия ред.
  5. Отпечатайте стойността на променлива a на конзолата заедно с друг текст. Endl (краен ред) ще премести курсора, за да започне печат на следващия ред.
  6. Отпечатайте стойността на променлива b на конзолата заедно с друг текст. Endl (краен ред) ще премести курсора, за да започне печат на следващия ред.
  7. Създайте функция с име test(), която приема адресите на променливи a и b като параметри.
  8. Отпечатайте малко текст на конзолата. \n ще създаде нов празен ред, преди текстът да бъде отпечатан. Endl (краен ред) ще премести курсора, за да започне отпечатването на следващия ред, след като текстът бъде отпечатан.
  9. Отпечатайте стойността на променлива a на конзолата заедно с друг текст. Endl (краен ред) ще премести курсора, за да започне печат на следващия ред.
  10. Отпечатайте стойността на променлива b на конзолата заедно с друг текст. Endl (краен ред) ще премести курсора, за да започне печат на следващия ред.
  11. Програмата трябва да върне стойност при успешно завършване.
  12. Край на тялото на функцията main().
  13. Дефиниране на функцията test(). Функцията трябва да приема две целочислени указателни променливи *n1 и *n2.
  14. Присвояване на променливата на показалеца *n1 на стойност 10.
  15. Присвояване на променливата на показалеца *n2 на стойност 11.
  16. Край на тялото на функцията test().

Въпреки че се присвояват нови стойности на променливи a и b във функционалния тест, след като извикването на функцията завърши, същото не се отразява във външната основна функция.

Използването на указатели като аргументи на функцията помага да се предаде действителният адрес на променливата във функцията и всички промени, извършени върху променливата, ще бъдат отразени във външната функция.

В горния случай функцията 'test' има адреса на променливите 'a' и 'b.' Тези две променливи са директно достъпни от функцията 'test' и следователно всяка промяна, направена на тези променливи, се отразява в извикващата функция 'main'.

Предимства на използването на указатели

Ето плюсовете/ползите от използването на указатели

  • Указателите са променливи, които съхраняват адреса на други променливи в C++.
  • Повече от една променлива може да бъде модифицирана и върната от функция с помощта на указатели.
  • Паметта може да бъде динамично разпределяна и освобождавана с помощта на указатели.
  • Указателите помагат за опростяване на сложността на програмата.
  • Скоростта на изпълнение на програмата се подобрява чрез използване на указатели.

Oбобщение

  • Указателят препраща към променлива, съдържаща адреса на друга променлива.
  • Всеки указател има валиден тип данни.
  • Указателят е символно представяне на адрес в паметта.
  • Указателите позволяват на програмите да симулират извикване по референция и да създават и манипулират динамични структури от данни.
  • Масивите и указателите използват свързана концепция.
  • Името на масива обозначава основата на масива.
  • Ако искате да присвоите адреса на масив към указател, не използвайте амперсанд (&).
  • Ако няма конкретен адрес за присвояване на променлива указател, присвоете му NULL.

Обобщете тази публикация с: