logo

Aqlli ko'rsatkichlar va harakat semantikasi

Yuklangan vaqt:

12.08.2023

Ko'chirishlar soni:

0

Hajmi:

34.427734375 KB
Aqlli ko'rsatkichlar va harakat semantikasi
Reja :
I. Kirish.
II. Asosiy qism:
a. Ko’rsatkichlar tushunchasi.
b. Funksiyadagi ko’rsatkichlar.
c. Obyektlarda ko’rsatkichlar .
III. Xulosa Kirish
Ko’p dasturlash tillaridan farqli o’laroq C++ ishlash tezligi bln ajralib turadi.
Bu dasturlash tili Bern Straustrup tomonidan yaratilingan bo’lib 1985 – yil 
oktabrda taqdim etilib,  xuddi shu yili B.Straustrupning «C++ dasturlash tili» (The 
C++ Programming Language) kitobi bosilib chiqdi.
C++ dasturi ishlash tezligi yuqori bo’lishiga sabablardan biri xotira bilan 
ishlash tizimidir yani dastur uchun xotiradan kerakli joyni olib qolib ortiqcha 
narsalar bilan to’ldirmaydi. Bunga misol qilib Ko’rsatkichlarni aytsak bo’ladi.
Ko’rsatkichlar tushunchasi.
Ko’rsatkich - xotira uyasining unikal adresini saqlaydigan o’zgaruvchi. 
Ko’rsatkich operativ xotiradagi biron-bir o’zgaruvchi mavjud bo’lishi mumkin 
bo’lgan biron-bir joyni belgilaydi . Ko’rsatkichlarning qiymatlarini o’zgartirishni 
shunday turli variantlarda qo’llash mumkinki, bu dasturning moslashuvchanligini 
oshiradi. Ko’rsatkich odatda turga ega bo’lib quyidagicha e’lon qilinadi:
<ma’lumot turi>*<identifikator> = <qiymat>
Misol uchun:
int *num;
char *belgi;
Bu holda ko’rsatkichlar noaniq qiymatga ega bo’ladi. Ko’rsatkichlar 
ta’riflanganda ularning turlari ko’rsatilishi shart. Ko’rsatkichlarni inisializasiya 
qilish, ya’ni boshlang’ich qiymatlarini kiritish mumkin. Ma’lum turdagi biron-bir 
o’zgaruvchi adresi yoki NULL qiymat dastlabki qiymat bo’lishi mumkin. 
Ko’rsatkichlarga boshlang’ich maxsus NULL qiymati berilsa, bunday ko’rsatkich 
bo’sh ko’rsatkich deb ataladi.
Biron-bir o’zgaruvchi adresini olish hamda uni ko’rsatkichga qiymat sifatida
berish uchun «&» operatori qo’llanadi. Misol uchun:
#include <stdio.h>
int main() {
int i = 123;
int *p = &i;
printf("\n i = %d p = %p", i, p);
int j = 456;
p = &j; printf("\n j = %d p = %p", j, p);
return 0; 
}
Natija:
i = 123 p = 0012FF60
j = 456 p = 0012FF48
Teskari operator - «*» bo’lib, ko’rsatkichda saqlanayotgan adres bo’yicha 
uya qiymatiga murojaat qilish imkonini beradi. Misol:
#include <stdio.h>
int main() {
int i = 123;
int *si = &i;
printf("\n i = %d *si = %d",i,*si);
i = 456;
printf("\n i = %d *si = %d",i,*si);
*si = 0;
printf("\n i = %d *si = %d",i,*si);
return 0;
}
Natija:
i = 123 *si = 123
i = 456 *si = 456
i = 0 *si = 0
Ko’rsatkichlar ustida o’tkaziladigan operasiyalar. Ko’rsatkichlar ustida unar 
operasiyalar bajarish mumkin: inkrement (++) va dekrement (--) operasiyalarini 
bajarishda, ko’rsatkich qiymati ko’rsatkich murojaat qilgan tur uzunligiga 
ko’payadi yoki kamayadi. Masalan:
int*ptr, a[10];
ptr = &a[5]; ptr++; */ = a[6]*/ elementining adresiga
ptr--; */ = a[5]*/ elementining adresiga
Qo’shish va ayirish binar operasiyalarida ko’rsatkich va int turining qiymati 
ishtirok etishi mumkin. Bu operasiya natijasida ko’rsatkich qiymati dastlabkisidan 
ko’rsatilgan elementlar soniga ko’proq yoki kamroq bo’ladi.
Masalan:
int*ptr1, *ptr2, a[10];
int i = 2;
ptr1 = a+(i+4); /* = a[6]*/ elementining adresiga
ptr2 = ptr1-i; /* = a[4]*/ elementining adresiga
Ayirish operasiyasida bitta turga mansub bo’lgan ikkita ko’rsatkich ishtirok 
etishi mumkin. Operasiya natijasi int turiga ega hamda kamayuvchi va ayiruvchi 
o’rtasidagi dastlabki tur elementlarining soniga teng, bundan tashqari agar birinchi 
adres kichikroq bo’lsa, u holda natija manfiy qiymatga ega bo’ladi.
Masalan:
int *ptr1, *ptr2, a[10];
int i;
ptr1 = a + 4;
ptr2 = a + 9;
i = ptr1 - ptr2; /* = 5 */
i = ptr1 -ptr2; /* = -5 */
Bir turga taalluqli bo’lgan ikkita ko’rsatkich qiymatlarini = = , ! = , <, < = , 
>,  > = amallari yordamida o’zaro qiyoslash mumkin. Bunda ko’rsatkichlarning 
qiymatlari shunchaki butun sonlar sifatida olib qaraladi, qiyoslash natijasi esa 0  
(yolg’on) yoki 1 (rost) ga teng bo’ladi.
Masalan:
int *ptr1, *ptr2, a[10];
ptr1 = a + 5;
ptr2 = a + 7;
if(ptr1 > ptr2) a[3] = 4; Bu misolda ptr1 ning qiymati ptr2 ning qiymatidan kamroq, shuning uchun 
a[3] = 4 operatori bajarilmay qoladi. Konstanta ko’rsatkich va konstantaga 
ko’rsatkichlar. Konstanta ko’rsatkich quyidagicha ta’riflanadi:
<ma’lumot turi>* const<identifikator> = <konstant qiymat>
Misol uchun: char* const key_byte = (char*)0x0417. 
Bu misolda konstanta ko’rsatkich klaviatura holatini ko’rsatuvchi bayt bilan 
bog’langandir.
Konstanta ko’rsatkich qiymatini o’zgartirish mumkin emas, lekin * amali 
yordamida xotiradagi ma’lumot qiymatini o’zgartirish mumkin. Misol uchun: 
*key_byte = ’Yo’ amali 1047(0x0417) adres qiymati bilan birga klaviatura holatini
ham o’zgartiradi.
Konstantaga ko’rsatkich quyidagicha ta’riflanadi:
<ma’lumot turi> const* <identifikator> = <konstant qiymat>  
Misol uchun: const int zero = 0; int const* p = &zero;
Bu ko’rsatkichga * amalini qo’llash mumkin emas, lekin ko’rsatkichning 
qiymatini o’zgartirish mumkin. Qiymati o’zgarmaydigan konstantaga 
ko’rsatkichlar quyidagicha kiritiladi: 
<ma’lumot turi> const* <identifikator> = <konstant qiymat>
Misol uchun: const float pi = 3.141593; float const* const pp = &pi;
Turlashtirilmagan ko’rsatkich. Turlashtirilmagan (tipiklashtirilmagan)  
ko’rsatkich void turga ega bo’lib, ixtiyoriy turdagi o’zgaruvchi adresi qiymat 
sifatida berilishi mumkin. 
Maxsus void turidagi ko’rsatkichlar ajdodiy ko’rsatkichlar deb atalib har xil 
turdagi ob’ektlar bilan bog’lanish uchun ishlatiladi.
Masalan:
int i = 77;
float euler = 2.18282;
void *vp;
vp = &I;
printf(“%d”, (*(int*)vp);
vp = &euler;
printf(“%f”, (*(float*)vp);
  Quyidagi operatorlar ketma-ketligi xatolikka olib keladi:void *vp;int *ip; ip = vp; Bu xatolik sababi bitta ob’ektga har xil turdagi ko’rsatkichlar bilan murojaat 
qilish mumkin emas.
Ko’rsatkichlar funksiya parametri sifatida. Ko’rsatkichlar yordamida 
parametr qiymatini o’zgartirish mumkin. Misol uchun to’rtburchak yuzi va 
perimetrini berilgan tomonlari bo’yicha hisoblash funksiyasini quyidagicha 
tasvirlash mumkin.
void pr(float a, float b, float* s, float* p) { 
*p = 2(a + b);
*s = a * b;
}
Bu funksiyaga quyidagicha murojaat qilinishi mumkin pr(a, b, &p, &s).   
Funksiyaga p va s o’zgaruvchilarning adreslari uzatiladi. Funksiya tanasida shu 
adreslar bo’yicha 2 * (a + b) va a * b qiymatlar yoziladi. Keyingi misolda berilgan 
ikki o’zgaruvchining qiymatlarini o’zaro almashtirish funksiyasidan foydalaniladi:
#include <stdio.h>
void change(int*a, int*b)//manzil bo'yicha uzatish {
int r = *a; *a = *b; *b = r;
}
int main() {
int x = 1,y = 5;
change(&x, &y);
printf("x = %d y = %d", x, y);
return 0;
}
Natija
x = 5 y = 1 
Agar funksiya ichida parametrning o’zgarishini taqiqlash lozim bo’lib qolsa,
bu holda const modifikatori qo’llanadi. Bu modifikatorni funksiyada o’zgarishi 
ko’zda tutilmagan barcha parametrlar oldidan qo’yish tavsiya qilinadi (undagi 
qaysi parametrlar o’zgaradiyu, qaysilari o’zgarmasligi sarlavhadan ko’rinib turadi). Funksiyadagi ko’rsatkichlar.
Funksiyalarni chaqirishda foydalanish. C tili sintaksisiga ko’ra funksiyaga 
ko’rsatkich funksiya adresini aks ettiruvchi o’zgaruvchi yoki ifodadir. Funksiyaga 
ko’rsatkich bajariluvchi qiymati funksiya kodining birinchi bayti adresidir. 
Funksiyaga ko’rsatkichlar ustida arifmetik amallar bajarish mumkin emas. Eng 
keng qo’llanuvchi funksiyaga konstanta ko’rsatkich funksiyaning nomidir.  
Funksiyaga o’zgaruvchi ko’rsatkich funksiya ta’rifi va prototipidan alohida 
kiritiladi. Funksiyaga o’zgaruvchi ko’rsatkich quyidagicha tasvirlanadi:
<funksiya turi> (* ko’rsatkich nomi)(parametrlar spesifikasiyasi).
Misol uchun: int (*point) (void).
Bu ta’rifda qavslar muhim ahamiyatga ega, chunki qavslar yozilmasa bu 
ta’rif parametrsiz funksiya prototipi deb qaraladi. Funksiyaga o’zgaruvchi 
ko’rsatkich qiymatlari sifatida, bir xil turga ega bo’lgan har xil funksiyalar 
adreslari berilishi mumkin.
Qiymati biror funksiya adresiga teng bo’lgan funksiyaga o’zgaruvchi 
ko’rsatkich shu funksiyaga murojaat qilish uchun ishlatilishi mumkin. Quyidagi 
misolda funksiyaga uch xil murojaat qilish ko’rsatilgan: 
#include<stdio.h>
void f1() {
printf("\nf1 funksiya bajarildi");
};
void f2() {
printf("\nf2 funksiya bajarilmadi");
};
int main() {
void (*ptr) (void);
ptr = f1;
(*ptr)();
ptr = f2;
(*ptr)();
return 0;
} Dasturda funksiyaga konstanta ko’rsatkich, ya’ni nomlari orqali va 
o’zgaruvchi ko’rsatkichlar yordamida murojaat qilishning hamma usullari 
ko’rsatilgandir. Shuni ta’kidlash lozimki, adres olish * amali qo’llanilganda 
qavslar ishlatish shartdir.
Funksiyaga o’zgaruvchi ko’rsatkich ta’riflanganda insializasiya qilish, ya’ni 
boshlang’ich qiymat sifatida o’zgaruvchi ko’rsatkich bilan bir xil turga ega bo’lgan
funksiya adresini ko’rsatish mumkin. Misol uchun:
int fic (char);
int (*pfic) (char) = fic;
Funksiyaga ko’rsatkichlar massivlari. C tilida funksiyalar massivlarni 
yaratish mumkin emas, lekin funksiyaga ko’rsatkichlar massivlarini kiritish 
mumkin. Bunday massivlar quyidagicha ta’riflanadi:
<tur>(*massiv_nomi[hajm])(parametrlar spesifikasiyasi).
Tur  – funksiyalar qaytaradigan qiymatlar turlari;
Massiv  - nomi ixtiyoriy identifikator;
Hajm  – massiv elementlari soni;
Parametrlar spesifikasiyasi - funksiyalar parametrlari nomlari va turlarini 
aniqlaydi.
Misol uchun int (*parray [4]) (char); 
Bu massiv elementlari qiymatlari quyidagi prototiplarga ega bo’lgan 
funksiyalar adreslaridir: int funksiya_nomi (char). Funksiyaga ko’rsatkichlar 
massivlari inisializasiya qilinishi mumkin. Misol uchun:
int f1(void);
int f2(void);
int (*pf[])() = {f1,f2};
Bu ta’rifni typedef ta’riflovchisi yordamida soddalashtirish mumkin: 
typedef int(*array_fync)(void);
array_func pf[] = {f1,f2};
Indeks konkret qiymati bo’yicha massiv elementlariga va konkret 
funksiyalarga murojaat quyidagi shaklda amalga oshiriladi:  
Massiv_nomi[indeks] (xaqiqiy parametrlar_ro’yxati);
(* Massiv_nomi[indeks]) (xaqiqiy parametrlar_ro’yxati); Funksiyaga ko’rsatkichlar massivlari menyular yaratishda qulaydir. Quyida 
shunday menyu misolini ko’ramiz:
#include <stdio.h>
#include <stdlib.h>
#define n 2
void act0(char* name ) {
printf("%s: Ish tugadi!\n", name);
}
void act1(char* name) {
printf("%s: Ish 1\n", name);
}
void act2(char* name ) {
printf("%s: Ish 2\n", name);
}
int main() {
void (*pact[])(char*) = {act0, act1, act2};
char string[12] = "Bajarildi";
int number;
printf("\n Ish nomerini kiriting 0 dan %d gacha", n);
while(1) {
scanf("%d", &number);
pact[number](string);
if (number == 0) break;
}
return 0;
}
Funksiyaga ko’rsatkichlar parametr sifatida. Funksiyaga ko’rsatkichlarni 
funksiyalarga parametr sifatida uzatish mumkin. Bunday uzatish nomi oldindan 
belgilanmagan funksiyalar bilan ishlashga imkon beradi. Misol uchun 
to’rtburchaklar usuli yordamida integral hisoblash funksiyasidan foydalanilgan  dasturni qarab chiqamiz. Dasturda x/(x 2
+1) 2
 funksiyasi integrali -1 va 2 oraliqda 
hisoblanadi. 
#include<stdio.h>
double ratio(double x) {
double z;
z = x * x + 1;
return x / (z * z);
};
double rectangle(double (*pf)(double), double a, double b) {
int n = 20;
int i;
double h, s = 0.0;
h = (b - a) / n;
for (i = 0; i < n; i++)
s+ = pf(a + h/2 + i * h);
return h * s;
};
int main() {
double a, b, c;
a = -1;
b = 2.0;
c = rectangle(ratio, a, b);
printf("%f", c);
return 0;
}
Bu dasturda integralni hisoblash rectangle funksiyasini chaqirish orqali 
bajariladi. Bu funksiya quyidagi parametrlarga ega: pf – double turli parametrga 
ega va shu turdagi qiymat qaytaruvchi funksiyaga ko’rsatkich, a va b parametrlari 
integrallash chegaralaridir. Integrallanuvchi funksiya qiymatlari ratio() funksiyani 
chaqirish orqali hisoblanadi. Dasturda rectangle() funksiyasi chaqirilib, pf 
ko’rsatkich qiymati ratio() funksiyasi adresiga teng.  Funksiyaga ko’rsatkich funksiya qiymati sifatida. Menyular tashkil qilganda 
funksiyaga ko’rsatkichlarni qiymat sifatida qaytaruvchi funksiyalardan foydalanish
qulaydir. Shu usulda menyu tashkil qilishni ko’rsatuvchi dasturni ko’rib chiqamiz. 
Dasturda uchta funksiya kiritilgan: int f(void) prototipiga ega bo’lgan f1() va f2() 
funksiyalari va int (*menu(void)) (void) prototipiga ega bo’lgan menu() funksiyasi.
Menu() funksiyasi bajarilganda f1() va f2()  funksiyalarga mos keluvchi menyu 
punktlaridan birini tanlash imkoni beriladi. Shu punktlardan biri tanlanganda mos 
funksiya adresi qaytariladi, agar punktlar noto’g’ri tanlangan bo’lsa NULL qiymati
qaytariladi. Bu qiymatlar asosiy dasturda r ko’rsatkichga uzatiladi. 
Agar qiymat NULL bo’lsa “The End” ma’lumoti chiqarilib dastur bajarilishi
to’xtatiladi, aks holda t = (*r)() murojaat adresi qaytarilgan funksiya bajarilishiga 
olib keladi.
#include <stdio.h>
int f1(void) {
  printf("The first actions: ");
return 1;
}
int f2(void) {
printf("The second actions: ");
return 2;
}
int (*menu(void))(void) {
int choice;
int (*menu_items[])() = {f1,f2};
printf("\n Pick the menu item (1 or 2): ");
scanf("%d",&choice);
if (choice<3&&choice>0)
return menu_items[choice-1];
else
return NULL;
}
int main() { 
int (*r)(void); int t;
while(1) {
 r = menu();
if (r == NULL) {
printf("\nThe End!");
return;
}
t = (*r)();
printf("|tt = %d",t);
}
return 0;
}
Obyektlarda ko’rsatkichlar
Strukturaga ko’rsatkichlar. Strukturaga ko’rsatkichlar oddiy ko’rsatkichlar 
kabi tasvirlanadi:
complex *cc,*ss; goods *p_goods;
Strukturaga ko’rsatkich ta’riflanganda inisializasiya qilinishi mumkin. Misol
uchun ekrandagi rangli nuqtani tasvirlovchi quyidagi strukturali tur va strukturalar 
massivi kiritiladi. Strukturaga ko’rsatkich qiymatlari inisializasiya va qiymat 
berish orqali aniqlanadi:
struct point{
int color;
int x,y;
} a,b;
point *pa = &a,pb; pb = &b;
Ko’rsatkich orqali struktura elementlariga ikki usulda murojaat qilish 
mumkin. Birinchi usul adres bo’yicha qiymat olish amaliga asoslangan bo’lib 
quyidagi shaklda qo’llaniladi: 
(* strukturaga ko’rsatkich).element nomi;
Ikkinchi usul maxsus strelka (->) amaliga asoslangan bo’lib quyidagi 
ko’rinishga ega: strukturaga ko’rsatkich->element nomi
Struktura elementlariga quyidagi murojaatlar o’zaro tengdir:
(*pa).color == a.color == pa->color
Struktura elementlari qiymatlarini ko’rsatkichlar yordamida quyidagicha 
o’zgartirish mumkin:
(*pa).color = red;
pa->x = 125;
pa->y = 300;
Dasturda nuqtaviy jismni tasvirlovchi particle strukturali turga tegishli 
m_point strukturasi aniqlangan bo’lsin. Shu strukturaga pinta ko’rsatkichini 
kiritamiz:
struct particle * pinta = &m_point;
Bu holda m_point struktura elementlarini quyidagicha o’zgartirish mumkin:
pinta->mass = 18.4;
for (i = 0;i<3;i++)
pinta->coord[i] = 0.1*i;
Obyektlarga ko’rsatkichlar. Strukturalar kabi ob’ektlar aniqlangandan so’n 
shu ob’ektlarga ko’rsatkichlar belgilash mumkin. Masalan:
complex A(5.2,2.7);
complex* PA = &A;
Obyektning umumiy elementlariga murojaat uchun -> operasiyani yoki ism
almashtirish va nuqta operasiyasidan foydalanish mumkin:
(*PA).real() yoki PA->real;
Misol:
#include <iostream>
#include <string>
using namespace std;
class complex{
float x;
float y;
public: complex(float x1 = 0,float y1 = 0):x(x1),y(y1){};
void show(){ 
cout<<"x = "<<x<<" y = "<<y<<endl;
}
};
int main() {
complex a(1.0,2.0);
complex *pa = &a;
pa->show();
complex b;
complex *pb = &b;
(*pb).show();
return 0;
}
Dastur bajarilishi natijasi:
x = 1.0 y = 2.0
y = 0.0 y = 0.0
This ko’rsatkichi. Agarda konkret ob’ektga ishlov berish uchun sinf a’zosi – 
funksiya chaqirilsa, unda shu funksiyaga ob’ektga belgilangan ko’rsatkich 
avtomatik va ko’rsatilmagan holda uzatiladi. Bu ko’rsatqich this ismiga ega va x*  
this kabi har bir funksiya uchun ko’rsatilmagan holda belgilanadi.
Masalan x sinfni ekvivalent ko’rinishda shunday tavsiflash mumkin: 
class x {
int m;
public:
int readm() { return this->m; }
};
A’zolarga murojaat etishda this dan foydalanish ortiqcha. Asosan this  
bevosita ko’rsatkichlar bilan manipulyasiya qilish uchun a’zo funksiyalarini 
yaratilishida foydalaniladi.
#include <iostream> using namespace std;
class Pair {
int N;
double x;
friend Pair& operator ++(Pair&);
friend Pair& operator ++(Pair&, int);
public:
Pair (int n, double xn) {
N = n; x = xn;
}
void display (){
cout<<"\n Koordinatalar: N = "<<N<<"\tx = "<<x;
} 
Pair& operator --(){
N/ = 10; x/ = 10; 
return*this;
}
Pair& operator --(int k) {
N/ = 2; 
x/ = 2.0; 
return*this;
}
};
Pair& operator ++(Pair& P) {
P.N* = 10; P.x* = 10;
return P;
}
Pair& operator ++(Pair& P, int k) {
P.N = P.N*2+k;
P.x = P.x*2+k; return P;
}
int main () {
Pair Z(10,20.0);
Z.display();
++Z;
Z.display();
--Z;
Z.display();
Z++;
Z.display();
Z--;
Z.display();
return 0; }
Virtual usullar va ko’rsatkichlar. Ajdod sinf ko’rsatkichiga avlod sinf ob’ekti
adresini qiymat sifatida berish va bu ko’rsatkich orqali avlod sinf usullarini 
chaqirish mumkin. Quyidagi misolda ajdod sinf va avlod sinf bir xil usulga ega 
bo’lgan xol ko’rilgan:
Misol:
#include <iostream>
using namespace std;
class base {
public:
virtual void print(){cout<<"\nbase";}
};
class dir : public base {
public:
void print(){
cout<<"\ndir";
}
}; int main()  {
base B;
dir D;
base *bp = &B;
bp->print(); // base
bp = &D;
bp->print(); // dir
return 0;
}
Natija:
base
dir
Bu misolda avlod sinfi ob’ektiga adres qiymat sifatida berilgan ajdod sinf 
turidagi ko’rsatkich yoki ilova orqali avlodda qo’shimcha yuklangan usulni 
chaqirishga e’tibor berish lozim. Agar funksiya novirtual bo’lsa ajdod sinf usuli,  
virtual bo’lsa avlod sinf usuli chaqiriladi. Shunday qilib ajdod sinf turidagi 
ko’rsatkich orqali virtual usul chaqirish natijasi shu ko’rsatkich qiymati ya’ni 
chaqiriq bajarilayotgan ob’ekt turi bilan aniqlanadi.
Qaysi virtual funksiyani chaqirish ko’rsatkich turiga emas shu ko’rsatkich 
qaratilgan(dastur bajarilish jarayonida) ob’ekt turiga bog’liq.  Masalan yuqoridagi 
misol quyidagicha ta’riflanish mumkin:
#include <iostream>
using namespace std;
class superbase {
public:
virtual void print() = 0;
};
class base:public superbase {
public:
void print(){
cout<<"\nbase"; }
};
class dir : public superbase {
public:
void print(){
cout<<"\ndir";
}
};
int main()  {
base B;
dir D;
superbase *bp = &B;
bp->print(); // base
bp = &D;
bp->print(); // dir
return 0;
}
Xulosa
Ko’rsatkich bu operativ xotiradagi biron-bir o’zgaruvchi mavjud bo’lishi 
mumkin bo’lgan biron-bir joyni belgilab berar ekan. Ko’rsatkichlarning 
qiymatlarini o’zgartirishni turli variantlari mavjud bo’lib, bu bizning dasturni 
moslashuvchanligini oshib berak ekan.Xulosa qilib shuni aytish mumkin-ki 
ko’rsatkichlar bilan ishlash operativ xotirani samarali ishlatishga yordam berar 
ekan.

Aqlli ko'rsatkichlar va harakat semantikasi Reja : I. Kirish. II. Asosiy qism: a. Ko’rsatkichlar tushunchasi. b. Funksiyadagi ko’rsatkichlar. c. Obyektlarda ko’rsatkichlar . III. Xulosa

Kirish Ko’p dasturlash tillaridan farqli o’laroq C++ ishlash tezligi bln ajralib turadi. Bu dasturlash tili Bern Straustrup tomonidan yaratilingan bo’lib 1985 – yil oktabrda taqdim etilib, xuddi shu yili B.Straustrupning «C++ dasturlash tili» (The C++ Programming Language) kitobi bosilib chiqdi. C++ dasturi ishlash tezligi yuqori bo’lishiga sabablardan biri xotira bilan ishlash tizimidir yani dastur uchun xotiradan kerakli joyni olib qolib ortiqcha narsalar bilan to’ldirmaydi. Bunga misol qilib Ko’rsatkichlarni aytsak bo’ladi. Ko’rsatkichlar tushunchasi. Ko’rsatkich - xotira uyasining unikal adresini saqlaydigan o’zgaruvchi. Ko’rsatkich operativ xotiradagi biron-bir o’zgaruvchi mavjud bo’lishi mumkin bo’lgan biron-bir joyni belgilaydi . Ko’rsatkichlarning qiymatlarini o’zgartirishni shunday turli variantlarda qo’llash mumkinki, bu dasturning moslashuvchanligini oshiradi. Ko’rsatkich odatda turga ega bo’lib quyidagicha e’lon qilinadi: <ma’lumot turi>*<identifikator> = <qiymat> Misol uchun: int *num; char *belgi; Bu holda ko’rsatkichlar noaniq qiymatga ega bo’ladi. Ko’rsatkichlar ta’riflanganda ularning turlari ko’rsatilishi shart. Ko’rsatkichlarni inisializasiya qilish, ya’ni boshlang’ich qiymatlarini kiritish mumkin. Ma’lum turdagi biron-bir o’zgaruvchi adresi yoki NULL qiymat dastlabki qiymat bo’lishi mumkin. Ko’rsatkichlarga boshlang’ich maxsus NULL qiymati berilsa, bunday ko’rsatkich bo’sh ko’rsatkich deb ataladi. Biron-bir o’zgaruvchi adresini olish hamda uni ko’rsatkichga qiymat sifatida berish uchun «&» operatori qo’llanadi. Misol uchun: #include <stdio.h> int main() { int i = 123; int *p = &i; printf("\n i = %d p = %p", i, p); int j = 456; p = &j;

printf("\n j = %d p = %p", j, p); return 0; } Natija: i = 123 p = 0012FF60 j = 456 p = 0012FF48 Teskari operator - «*» bo’lib, ko’rsatkichda saqlanayotgan adres bo’yicha uya qiymatiga murojaat qilish imkonini beradi. Misol: #include <stdio.h> int main() { int i = 123; int *si = &i; printf("\n i = %d *si = %d",i,*si); i = 456; printf("\n i = %d *si = %d",i,*si); *si = 0; printf("\n i = %d *si = %d",i,*si); return 0; } Natija: i = 123 *si = 123 i = 456 *si = 456 i = 0 *si = 0 Ko’rsatkichlar ustida o’tkaziladigan operasiyalar. Ko’rsatkichlar ustida unar operasiyalar bajarish mumkin: inkrement (++) va dekrement (--) operasiyalarini bajarishda, ko’rsatkich qiymati ko’rsatkich murojaat qilgan tur uzunligiga ko’payadi yoki kamayadi. Masalan: int*ptr, a[10]; ptr = &a[5];

ptr++; */ = a[6]*/ elementining adresiga ptr--; */ = a[5]*/ elementining adresiga Qo’shish va ayirish binar operasiyalarida ko’rsatkich va int turining qiymati ishtirok etishi mumkin. Bu operasiya natijasida ko’rsatkich qiymati dastlabkisidan ko’rsatilgan elementlar soniga ko’proq yoki kamroq bo’ladi. Masalan: int*ptr1, *ptr2, a[10]; int i = 2; ptr1 = a+(i+4); /* = a[6]*/ elementining adresiga ptr2 = ptr1-i; /* = a[4]*/ elementining adresiga Ayirish operasiyasida bitta turga mansub bo’lgan ikkita ko’rsatkich ishtirok etishi mumkin. Operasiya natijasi int turiga ega hamda kamayuvchi va ayiruvchi o’rtasidagi dastlabki tur elementlarining soniga teng, bundan tashqari agar birinchi adres kichikroq bo’lsa, u holda natija manfiy qiymatga ega bo’ladi. Masalan: int *ptr1, *ptr2, a[10]; int i; ptr1 = a + 4; ptr2 = a + 9; i = ptr1 - ptr2; /* = 5 */ i = ptr1 -ptr2; /* = -5 */ Bir turga taalluqli bo’lgan ikkita ko’rsatkich qiymatlarini = = , ! = , <, < = , >, > = amallari yordamida o’zaro qiyoslash mumkin. Bunda ko’rsatkichlarning qiymatlari shunchaki butun sonlar sifatida olib qaraladi, qiyoslash natijasi esa 0 (yolg’on) yoki 1 (rost) ga teng bo’ladi. Masalan: int *ptr1, *ptr2, a[10]; ptr1 = a + 5; ptr2 = a + 7; if(ptr1 > ptr2) a[3] = 4;

Bu misolda ptr1 ning qiymati ptr2 ning qiymatidan kamroq, shuning uchun a[3] = 4 operatori bajarilmay qoladi. Konstanta ko’rsatkich va konstantaga ko’rsatkichlar. Konstanta ko’rsatkich quyidagicha ta’riflanadi: <ma’lumot turi>* const<identifikator> = <konstant qiymat> Misol uchun: char* const key_byte = (char*)0x0417. Bu misolda konstanta ko’rsatkich klaviatura holatini ko’rsatuvchi bayt bilan bog’langandir. Konstanta ko’rsatkich qiymatini o’zgartirish mumkin emas, lekin * amali yordamida xotiradagi ma’lumot qiymatini o’zgartirish mumkin. Misol uchun: *key_byte = ’Yo’ amali 1047(0x0417) adres qiymati bilan birga klaviatura holatini ham o’zgartiradi. Konstantaga ko’rsatkich quyidagicha ta’riflanadi: <ma’lumot turi> const* <identifikator> = <konstant qiymat> Misol uchun: const int zero = 0; int const* p = &zero; Bu ko’rsatkichga * amalini qo’llash mumkin emas, lekin ko’rsatkichning qiymatini o’zgartirish mumkin. Qiymati o’zgarmaydigan konstantaga ko’rsatkichlar quyidagicha kiritiladi: <ma’lumot turi> const* <identifikator> = <konstant qiymat> Misol uchun: const float pi = 3.141593; float const* const pp = &pi; Turlashtirilmagan ko’rsatkich. Turlashtirilmagan (tipiklashtirilmagan) ko’rsatkich void turga ega bo’lib, ixtiyoriy turdagi o’zgaruvchi adresi qiymat sifatida berilishi mumkin. Maxsus void turidagi ko’rsatkichlar ajdodiy ko’rsatkichlar deb atalib har xil turdagi ob’ektlar bilan bog’lanish uchun ishlatiladi. Masalan: int i = 77; float euler = 2.18282; void *vp; vp = &I; printf(“%d”, (*(int*)vp); vp = &euler; printf(“%f”, (*(float*)vp); Quyidagi operatorlar ketma-ketligi xatolikka olib keladi:void *vp;int *ip; ip = vp;