Читайте также: |
|
int *px;
бізге таныс емес, жаңа нәрсе болып табылады, және ол мнемоникалық сипаттау ретінде қарастырылуы қажет; бұл *px комбинациясының типі int екенін білдіреді. Егер px *px контекстінде кездесетін болса, бұл int типті айнымалыға пара-пар деген сөз.
Негізінде айнымалыны сипаттау синтаксисі осы айнымалының пайда болуы мүмкін өрнектердің синтаксисіне ұқсайды. Бұл ескерту күрделі сипаттаулармен байланысты барлық жағдайлар үшін тиімді. Мысалы,
double atof(), *dp;
atof() және *dp өрнектердің ішінде double типті мәнге ие екенін білдіреді.
Осы сипаттаудан шығатыны, көрсеткіш тек белгілі бір объект түріне ғана сілтей алады. Көрсеткіштер өрнектердің ішінде бола алады. Мысалы, егер px бүтін санды x- ке сілтейтін болса, онда *px x кездесіп қалуы мүмкін кез келген контекстте қолданыла алады. Сонымен,
y = *px + 1
операторы y- ке x -тің мәнінен 1 мән артық мәнді меншіктейді;
printf("%d\n", *px)
операторы x- тің ағымдағы мәнін баспаға шығарады;
d = sqrt((double) *px)
операторы d- ға x- тің квадрат түбірін меншіктейді, бұл жерде sqrt функциясын орындамастан бұрын x айнымалысы double типіне түрлендіріледі.
Келесі түрдегі өрнектерде
y = *px + 1
* және & унарлы операциялары арифметикалық операциялармен емес, өз операндымен тығыз байланыста болады, сондықтан мұндай өрнек px- тің сілтейтін мәнін алады, 1-ді қосады да, нәтижені y айнымалысына меншіктейді.
y = *(px + 1).
өрнегінің нені білдерітініне қайта оралып, түсініктеме береміз.
Көрсеткіштерге сілтемелер меншіктеу операторының сол жақ бөлігінде де кездесуі мүмкін, егер px x -ке сілтейтін болса, онда
*px = 0
x- ті нөлге тең деп алады, ал
*px += 1.
оны 1-ге арттырады, келесі өрнек те дәл осылай
(*px)++
Соңғы мысалдағы жай жақша міндетті түрде керек; егер оны жазбаса, онда * және ++ сияқты унарлы операциялар оңнан солға қарай орындалатын болғандықтан, бұл өрнек PX сілтеп тұрған айнымалыны емес, PX- тің өзін арттырады.
Және де көрсеткіштер айнымалы болып табылатындықтан, олармен басқа айнымалыларға қатынас жасағандай қатынас жасауға болады. Егер py – int типті айнымалының басқа көрсеткіші болса, онда
py = px
px- тің ішіндегіні py- ке көшіреді, нәтижесінде px қайда сілтесе, py те сол жаққа сілтейді.
Көрсеткіштер және массивтер. "C" тілінде көрсеткіштер мен массивтердің арасында тығыз байланыс бар, оның тығыздығы сонша, көрсеткіштер мен массивтерді бірге қарастыру керек. Массивтің индекстері арқылы орындалатын кез келген операцияны көрсеткіштердің де көмегімен орындауға болады. Көрсеткіштерді қолданған жағдайда операция жылдамырақ орындалады, бірақ оны бірден түсіну қиынға соғады.
int a[10]
сипаттамасы өлшемі 10-ға тең массивті анықтайды, яғни a[0], a[1],..., a[9] деп аталатын тізбектеле орналасқан 10 объекттің жиынтығы. a[i] жазуы массивтің басынан бастап санағанда, i-ші элементіне сәйкес келеді. Егер pa – төмендегідей сипатталған бүтін санның көрсеткіші болса,
int *pa,
онда
pa = &a[0]
меншіктеу операторы pa- ның a массивінің нөлінші элементіне сілтейтінін білдіреді; бұл дегеніміз – pa көрсеткішінде a[0] элементінің адресі сақталады. Енді
x = *pa
меншіктеу операторы a[0]- дың мәнін x- ке көшіретін болады.
Егер pa көрсеткіші a массивінің қандай да бір анықталған элементіне сілтейтін болса, онда анықтама бойынша pa+1 келесі элементке сілтейді, және жалпы pa-i көрсеткіші – pa сілтейтін элементтен i позиция бұрын орналасқан элементке сілтейді, ал pa+i көрсеткіші – i позиция кейін орналасқан элементке сілтейді. Осылайша, егер pa көрсеткіші a[0]-ге сілтейтін болса, онда
*(pa+1)
a[1] құрамындағысына, pa+i - a[i] адресіне, ал *(pa+i) - a[i] құрамындағысына сілтейді.
Бұл ескертулер a массивіндегі айнымалылардың типіне қарамастан дұрыс болып табылады. «Көрсеткішке 1-ді қосу» анықтамасының, сондай-ақ оның толықтай көрсеткіштер арифметикасына таралуының мәні мынада: көрсеткіштің сілтейтін объектісінің алып тұрған жады көлемі осы өсімді масштабтайды. Осылайша, pa+i- дегі i қосылудың алдында pa сілтейтін объекттердің өлшеміне көбейтіледі.
Көрсеткіштердің индекстелуі мен арифметикасы арасында сәйкестік бар екені анық, шындығында компилятор массивке сілтемені массивтің басындағы көрсеткішке түрлендіреді. Осының нәтижесінде массив аты көрсеткіштік өрнек болып табылады. Осыдан бірнеше пайдалы салдар шығады. Массив аты оның нөлінші элементінің орнына синоним болып табылатындықтан, онда pa=&a[0] меншіктеу операторын келесідей жазуға болады:
pa = a.
Тағы да бір таңғаларлық жайт, A[i]- ге сілтемені *(a+i) түрінде жазуға болатыны. a[i] өрнегін талдау кезінде "C" тілінде ол дереу *(a+i) түріне келтіріледі; бұл екі форма бір-біріне эквивалентті. Егер осы эквиваленттілік қатынасының екі бөлігіне де & операциясын қолданатын болсақ, онда біз &a[i] мен a+i –дің де бірдей екендігін байқаймыз: a+i – a массивінің элементтерін басынан бастап санағанда i - ші элемент адресі. Екінші жағыман, егер pa көрсеткіш болып табылса, онда өрнектерде оны индекспен қолдануға болады: pa[i] мен *(pa+i) пара-пар. Қысқасы, массивтер мен индекстері бар кез келген өрнек көрсеткіштер мен жылжытулар арқылы жазылуы мүмкін.
Массив аты мен көрсеткіш арасында бір айырмашылық бар, оны әрдайым есте сақтау қажет: көрсеткіш айнымалы болып табылады, сондықтан pa=a және pa++ операцияларының мағымасы бар. Бірақ массив аты айнымалы емес, константа болып табылады: a=pa немесе a++, немесе p=&a конструкциялары қате болып табылады.
Массив аты функцияға берілетін кезде, негізінен оған осы массив басының орны беріледі. Шақырылған функцияның ішінде мұндай аргумент кез келген басқа айнымалы сияқты айнымалы болып табылады, сондықтан массив аты аргумент ретінде шынымен де көрсеткіш болып, яғни ішінде адрес бар айнымалы болып табылады. Біз бұл жағдайды жолдың ұзындығын есептейтін STRLEN функциясының жаңа нұсқасын жазу үшін қолдана аламыз.
strlen(s) /* return length of string s */
char *s;
{
int n;
for (n = 0; *s!= '\0'; s++)
n++;
return(n);
}
s- ті арттыру операциясы дұрыс болып табылады, себебі бұл айнымалы көрсеткіш болып табылады; s++ strlen- ге қатынас жасаған функциядағы символдық жолға мүлдем әсер етпейді, ол тек strlen функциясы үшін локальды болып табылатын адрес көшірмесін арттырады. Функция анықтамасында формальды параметрлерді сипаттаудың келесі түрлері
char s[];
char *s;
бір-біріне эквивалентті; сипаттаудың қай түрін қолдану керектігі функцияны жазу кезінде қандай өрнектердің қолданылатынымен анықталады. Егер функцияға массив аты берілетін болса, онда ненің ыңғайлы екендігіне байланысты, функцияның массивпен немесе көрсеткішпен жұмыс істейтінін болжауға болады, ары қарай сәйкесінше әрекет ету керек. Егер қажет деп табылса, онда операцияның екі түрін де қолдануға болады.
Егер аргумент ретінде ішкі массив басының көрсеткіші берілетін болса, онда функцияға массивтің бір бөлігін беруге болады. Мысалы, егер a – массив болса, онда төмендегі екі өрнек те
f(&a[2]),
f(a+2)
f функциясына a[2] элементінің адресін береді, өйткені &a[2] де, a+2 де үшінші a элементіне сілтенетін көрсеткіштік өрнектер болып табылады. f функциясының ішінде аргументтердің сипаттамалары келесі түрде болуы мүмкін:
немесе
f функциясына келетін болсақ, оның аргументінің шындығында үлкен массивтің бөлігіне сілтенетіні оған ешқандай әсер етпейді.
Адрестік арифметика. Егер p көрсеткіш болса, онда ол сілтейтін объектінің сорты қандай болса да, p++ операциясы p-ны осы объектілер жиынының келесі элементіне сілтейтіндей етіп арттырады, ал p+=i операциясы p-ны ол ағымдағы элементтен i элементке қалып жүретін элементке сілтейтіндей етіп арттырады. Осы және осыған ұқсас конструкциялар көрсеткіштер арифметикасы мен адрестік арифметиканың ең қарапайым және ең кең таралған формалары болып табылады.
Негізгі әдебиет: 1 [161-181], 2[312-344], 3[186-190], 5[94-124]
Бақылау сұрақтары:
1. Көрсеткіштермен жұмыс істеуге арналған операцияларды атаңыз?
2. Көрсеткіштен бүтін санды қосу кезінде көрсеткіш мәні қандай мәнге артады?
3. Айнымалы-көрсеткішті инициалдау мысалын келтіріңіз.
4. Айнымалы-көрсеткішті жариялау мысалын келтіріңіз.
5. Сілтеме бойынша шақыруды құру үшін қандай операция қолданылады?
Дата добавления: 2015-07-08; просмотров: 554 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Дәріс. Массивтер. Бірөлшемді және екіөлшемді массивтерді өңдеуге арналған программаларды құру | | | Дәріс. Массивтер және көрсеткіштер |