Skip to main content

4-dars. Pointer tushunchasi

Darsning Maqsadlari:

  • Pointer tushunchasini va uning dasturlashdagi ahamiyatini o‘rganish.
  • Pointerlarni qanday qilib e'lon qilishni va o‘zgaruvchilar bilan qanday ishlatishni bilish.
  • Funksiyalar bilan pointerlardan qanday foydalanishni tushunish.
  • Pointerlar va massivlar (seriyalar) o‘rtasidagi bog‘lanishni o‘rganish.
  • Dasturlashda pointerlar bilan ishlashning afzallik va xavf-xatarlarini bilish.
  • Dasturda pointer turlarini va array pointerlarni qanday ishlatishni bilish.
  • Array pointerlari nima ekanini, qanday ishlashini o'rganish.

Pointer Nima?

Dasturlashda pointer (ko‘rsatkich) — bu kompyuter xotirasidagi manzilni saqlovchi o‘zgaruvchi. Oddiy qilib aytganda, pointer o‘z ichida boshqa o‘zgaruvchining xotiradagi joylashuvini saqlaydi. Pointerlardan foydalanish orqali dasturni samaraliroq qilish, katta hajmdagi ma'lumotlar ustida ishlash va ba'zi jarayonlarni soddalashtirish mumkin.


Pointerni E'lon Qilish va O'zgaruvchilar Bilan Ishlatish

Pointerni E'lon Qilish

Pointerni e'lon qilish uchun biz * (yulduzcha) belgisi bilan o‘zgaruvchi tipini yozamiz. Misol uchun, int tipidagi pointer quyidagicha e'lon qilinadi:

int *ptr;

Bu yerda:

  • int — pointer orqali ko‘rsatadigan qiymat turi (int — butun son).
  • ptr — bu ptr nomli integer tipidagi pointerni bildiradi.

O'zgaruvchi Manzili Va Qiymati Bilan Ishlash

  • Manzil olish: Har bir o‘zgaruvchining xotirada manzili bor. Manzilni olish uchun & (ampersand) belgisidan foydalanamiz. Masalan:

    int a = 5;
    int *ptr = &a; // 'a' ning manzili 'ptr' ga yuklanadi
  • Qiymat olish: Pointer orqali ko‘rsatilgan qiymatni olish uchun yana * belgisidan foydalanamiz:

printf("Qiymati: %d\n", *ptr); // natija: 5

Tushunish uchun misol:

#include <stdio.h>

int main() {
int son = 10;
int *pointer = &son; // 'son' o'zgaruvchisining manzilini 'pointer' ga yuklash

printf("Sonning qiymati: %d\n", son); // Sonning o'zi
printf("Pointer orqali qiymat: %d\n", *pointer); // Pointer orqali sonning qiymati
printf("Sonning manzili: %p\n", pointer); // Sonning manzili
return 0;
}

Pointer va Funksiyalar

Pointerlarni funksiyalarga parametr sifatida yuborish bizga dasturda o‘zgartirishlar kiritish imkonini beradi. Bu, ayniqsa, o‘zgaruvchilarning qiymatlarini o‘zgartirishda juda foydali.

Funksiyaga Pointer Yuborish

Pointerlarni funksiyaga o‘tkazish orqali o‘sha o‘zgaruvchining asl qiymatini o‘zgartirish mumkin. Masalan, swap (qiymatlarni almashtirish) funksiyasini pointer orqali yozamiz:

#include <stdio.h>

void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}

int main() {
int a = 5, b = 10;
printf("Almashtirishdan oldin: a = %d, b = %d\n", a, b);
swap(&a, &b); // Manzillarni yuboramiz
printf("Almashtirilgandan keyin: a = %d, b = %d\n", a, b);
return 0;
}

Yuqoridagi misolda swap funksiyasi a va b o‘zgaruvchilari qiymatlarini almashtiradi. Pointerlar tufayli biz asl o‘zgaruvchilarning qiymatlarini o‘zgartira oldik.


Pointer va Seriyalar (Massivlar)

Massivlar bilan pointerlar birgalikda ishlatilganda juda qulay bo‘ladi. Massivning har bir elementi ketma-ket xotira manzillarida joylashgan. Shu sababli, massivning birinchi elementi manzilini bilsak, qolgan elementlarga ham kirishimiz mumkin.

Massivni Pointer Orqali Boshqarish

Misol:

#include <stdio.h>

int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // Massivning birinchi elementi manzili

for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, *(ptr + i)); // Pointer orqali massiv elementlari
}
return 0;
}

Yuqoridagi kodda *(ptr + i) orqali har bir elementning qiymatini olamiz. Bu usul katta massivlarda samarali ishlaydi.


Pointer Turlari

Oddiy Pointerlar

Oddiy pointerlar biror bir o‘zgaruvchining xotira manzilini saqlaydi. Masalan, int * integer tipidagi o‘zgaruvchi manzilini saqlaydi.

Misol:

int a = 10;
int *ptr = &a; // 'a' ning manzili 'ptr'ga yuklanmoqda

Bu yerda ptr — oddiy integer pointer bo‘lib, a o‘zgaruvchisining xotiradagi manzilini saqlaydi. Agar *ptr deb murojaat qilsak, a o‘zgaruvchining qiymatini qaytaradi.

NULL Pointer

NULL pointer — hech qanday manzilni ko‘rsatmaydigan pointer. U dasturda hali to‘ldirilmagan yoki ishlatilmagan pointerlarni aniqlash uchun foydali. NULL pointerlarni dasturda foydalanilmagan xotira segmentlarini ifodalashda ishlatish mumkin.

int *ptr = NULL;  // 'ptr' hech narsani ko'rsatmaydi

Fakt: Null pointerlarni dasturlashda to‘g‘ri ishlatish xatolardan qochishga yordam beradi. Aks holda, noto‘g‘ri pointerlar dasturda “segmentation fault” yoki xotira xatolariga olib kelishi mumkin.

Void Pointer (Umumiy Pointer)

Void pointer — hech qanday aniq turga ega bo‘lmagan pointer. Bu pointer boshqa turdagi o‘zgaruvchilar manzillarini saqlashi mumkin, ammo unga murojaat qilishdan oldin u aniq turga kasting qilinishi kerak.

void *ptr;
int a = 10;
ptr = &a; // Void pointer int manzilini saqlamoqda

Void pointerlardan foydalanish qulay, chunki u turli xil ma'lumot turlarini saqlay oladi. Ammo, ular bilan ishlashda ehtiyot bo‘lish kerak, chunki noto‘g‘ri kasting qilish dasturda xatolarga olib kelishi mumkin.

Dangling Pointer

Dangling pointer — o‘zgaruvchi yo‘q qilingan (masalan, o‘zgaruvchi yoki massiv xotiradan o‘chirilgan) holda hali ham xotira manzilini ko‘rsatib turgan pointerdir. Bu xotira buzilishiga olib kelishi mumkin.

Misol:

int *ptr;
{
int a = 10;
ptr = &a; // 'ptr' a ning manzilini saqlaydi
}
// Bu yerda 'a' o'chirilgan, ammo 'ptr' hali ham o'sha manzilga ishora qilmoqda.

Esda tuting: Dangling pointerlar dasturda xato keltirib chiqaradi. Shuning uchun pointerlarga hech qanday keraksiz murojaat qilmaslik kerak.


Array Pointerlar

Massivlar pointerlar bilan ishlashda juda qulay, chunki massiv elementlari ketma-ket xotira manzillarida joylashgan. Shuning uchun massivning birinchi elementining manzilini bilsak, qolgan elementlarga ham oddiy matematik amallar yordamida murojaat qilishimiz mumkin.

Oddiy Massiv va Array Pointerlar

Misol:

int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr; // 'arr' ning birinchi elementi manzili 'ptr' ga yuklanadi

Bu yerda ptr massivning birinchi elementini ko‘rsatadi, ammo *(ptr + 1), *(ptr + 2), va hokazo orqali biz massivning keyingi elementlariga kirishimiz mumkin.

Amaliy misol:

#include <stdio.h>

int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // 'arr' massivining birinchi elementi manzili

for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, *(ptr + i)); // Pointer orqali massiv elementlariga kirish
}
return 0;
}

Qiziqarli fakt: Massiv pointerlari dasturda joyni tejashda yordam beradi. Bu dasturda kerakli joydan boshqa joylarni har doim almashtirmasdan ishlatishga imkon beradi.


Array Pointer va Pointer Array

Array Pointer (Massivning Pointeri)

Array pointer — bu bir nechta o‘lchovli massivlarni ko‘rsatish uchun foydalaniladi.

Misol:

int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int (*ptr)[4] = arr; // 'ptr' 4-elementli massivni ko'rsatadi

Bu yerda ptr ko‘p o‘lchamli massivning to‘liq qatorini ko‘rsatadi, ya'ni arr massivining har bir qatoriga murojaat qilishi mumkin.

Pointer Array (Pointerlardan tuzilgan massiv)

Pointer array — bu bir nechta pointerlardan tashkil topgan massivdir. Bu bizga turli xil xotira manzillariga kirishni soddalashtiradi.

Misol:

int a = 1, b = 2, c = 3;
int *arr[] = {&a, &b, &c}; // Har bir element pointer

Bu yerda arr uchta integer pointerdan tashkil topgan massiv va har bir pointer alohida o‘zgaruvchining manzilini saqlaydi.

Amaliy misol:

#include <stdio.h>

int main() {
int a = 5, b = 10, c = 15;
int *arr[] = {&a, &b, &c};

for (int i = 0; i < 3; i++) {
printf("arr[%d] qiymati: %d\\n", i, *arr[i]); // Pointer massiv orqali har bir qiymatga kirish
}
return 0;
}

Xulosa

Pointerlar dastur samaradorligini oshirish va resurslardan tejab foydalanishda juda foydali. Biroq, ular noto‘g‘ri ishlatilsa, dasturda xato va xotira buzilishlariga olib kelishi mumkin.

Pointer turlari va array pointerlar dasturlashda xotira manzillaridan unumli foydalanish imkonini beradi. Ular yordamida o‘zgaruvchilar va massivlarga bevosita kirish qilishimiz va samarali dasturlar yozishimiz mumkin.

Eslatma: Pointerlar bilan ishlashda xatolardan qochish uchun ehtiyotkor bo‘lish kerak, chunki noto‘g‘ri ishlatilgan pointerlar dasturda katta xatolarga olib kelishi mumkin.


Tez-tez Beriladigan Savollar

  1. Pointer bilan oddiy o‘zgaruvchi orasidagi farq nimada?
    • Oddiy o‘zgaruvchi faqat qiymatni saqlaydi, pointer esa xotira manzilini saqlaydi.
  2. Nima uchun pointerlardan foydalanamiz?
  • Pointerlar orqali dasturda o‘zgaruvchilarning asl qiymatlarini o‘zgartirish, xotirani tejash va katta hajmdagi ma'lumotlar bilan samarali ishlash imkoniyatlari paydo bo‘ladi.
  1. Nega pointerlar bilan ishlash xavfli hisoblanadi?
    • Agar pointer noto‘g‘ri manzilga ishora qilsa yoki noto‘g‘ri ishlatilsa, dastur xato xabarlarni chiqarishi yoki xotira buzilishlariga olib kelishi mumkin.
  2. Pointer orqali massiv elementlarini qanday boshqaramiz?
    • Massivning birinchi elementi manzilini olish orqali barcha elementlarga pointer bilan kirish mumkin ((ptr + i) orqali).
  3. Array pointer va pointer array o'rtasidagi farq nimada?
    • Array pointer — bu ko‘p o‘lchamli massivlarning qatorini ko‘rsatadi, pointer array esa bir nechta pointerlardan tashkil topgan massivdir.
  4. Null pointer nima uchun kerak?
    • Null pointer ishlatilmayotgan yoki noto‘g‘ri ishlatilmasligi kerak bo‘lgan xotira manzillarini ifodalash uchun foydali. Bu dastur xavfsizligini ta’minlashda yordam beradi.
  5. Nima uchun pointer arraylardan foydalanamiz?
    • Pointer arraylar bizga ko‘plab o‘zgaruvchilar yoki massiv elementlariga kirishni soddalashtiradi va har bir elementning aniq manzilini saqlash imkonini beradi.