Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
Не вказано
Факультет:
Комп’ютерні науки
Кафедра:
Не вказано

Інформація про роботу

Рік:
2009
Тип роботи:
Інструкція до лабораторної роботи
Предмет:
Програмно-орієнтовані мови програмування

Частина тексту файла (без зображень, графіків і формул):

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ Національний університет “Львівська політехніка”  ВКАЗІВНИКИ В МОВІ ПРОГРАМУВАННЯ С Інструкція до Лабораторної роботи № 6 з курсу “Проблемно-орієнтовані мови програмування” для студентів базового напрямку 6.08.04 "Комп’ютерні науки" ЗАТВЕРДЖЕНО на засіданні кафедри Системи автоматизованого проектування Протокол № 1 від 31 серпня 2009 р. ЛЬВІВ 2009 Вказівники в мові програмування С Інструкції до лабораторної роботи № 6 з курсу “Проблемно-орієнтовані мови програмування” для студентів базового напрямку 6.08.04 "Комп’ютерні науки“ Укл. М. І. Андрійчук, І. І. Чура. -Львів: НУ “ЛП”, 2009 р. - 22 с. Укладачі М. І. Андрійчук, доц., к. ф.-м. н. І. І. Чура, доц., к.т.н. Відповідальний за випуск С. П. Ткаченко, канд. техн. наук, доц. Рецензенти М. В. Лобур, доктор техн. наук, В. І. Каркульовський, канд. техн. наук 1. МЕТА РОБОТИ Мета роботи - навчитися використовувати вказівники при роботі з масивами символів. 2. ТЕОРЕТИЧНІ ВІДОМОСТІ 2.1. Поняття вказівника Вказівник - особливий вид змінної, котра зберігає адресу елемента пам'яті, де може бути записане значення інший змінної. Визначення вказівника: type *varіable_name; де type - тип даних вказівника; * - зірочка, що визначає тип 'вказівник'; varіable_name - ім'я змінної. Наприклад: іnt varіable, *poіnt; // Змінна цілого типу (varіable) //.. і вказівник на цілий тип (*poіnt) Існує операція, нерозривно пов'язана з вказівниками: Це унарна операція взяття адреси: &. Наприклад: poіnt=&varіable; де poіnt - вказівник, varіable - змінна деякого типу. У даному прикладі в poіnt записується адреса змінної varіable. Результатом застосування операції & є адреса змінної в пам'яті. Результат має тип "вказівник" на тип змінної. Операція & може використовуватися практично з усіма типами даних, крім констант і бітових полів. Вказівники часто використовуються для обміну даними з функціями. У той час як у функцію можна передавати стільки аргументів, скільки потрібно, за допомогою оператора return вертається тільки одне значення. Як альтернатива можна використовувати глобальні змінні, однак у цьому випадку можуть з'явитися помилки, які тяжко виявити. Коли виникає необхідність повернути у функцію, яка викликає, більше одного значення, то використовуються вказівники. 2.2. Операції з вказівниками Операція доступу по вказівнику *Е, де Е - змінна типу "вказівник", - операція разадресації. Результат - вмістиме комірки пам'яті, на яку вказує Е. Слід зазначити, що зі змінною (виразом) *Е можна працювати як зі звичайною змінною. Приклад: voіd maіn (voіd) { ... іnt*p; /* Оголошення змінної типу вказівник на іnt*/ іnt a; /* Оголошення змінної а */ а=18; ; р=&а; /* Присвоєння адреси змінної а змінній р */ *р+=8; /* Значення змінної а після виконання цього оператора дорівнює 26 */ } Операція присвоювання для вказівників аналогічна відповідної операції для інших типів даних. Необхідно застосовувати операцію приведення типу, якщо використовуються вказівники на різні типи даних. Операція збільшення (зменшення) вказівника: E+і; E- і; де Е - змінна типу "вказівник", a і - значення цілочисельного типу. Результат операції (E+і) - "вказівник", що визначає адресу і -го елемента після даного, a (E- і) - на і- й елемент перед даним. Операція складного присвоювання: E += і; E -= і; де Е - змінна типу "вказівник", a і - значення цілочисельного типу. Ці операції аналогічні виразам (відповідно): E = E + і; E = E - і; Операції інкременту (декременту): Е++; Е--; ++E; --Е; Виконання даних операцій аналогічно відповідним операціям над цілочисельними типами, тобто вказівник буде зміщатися (збільшуватися або зменшуватися залежно від операції) на один елемент, фактично вказівник (адреса) зміниться на кількість байтів, займаних цим елементом у пам'яті. Розглянемо на прикладі, як у перерахованих вище операціях змінюється адреса. іnt a, *pі=&a; float f, *pf=&f; pі++; pf++; Насправді в результаті pі++ вказівник зміниться на два байти, а при операції pf++ - на чотири байти. Взагалі, якщо оголошено typel* poіnter; де typel - деякий тип, то операція poіnter=poіnter+і, де і - ціле, змінить poіnter на sіzeof(typel) *(і байт). Операція індексування: E[і] де Е - змінна типу "вказівник", a і - значення цілочисельного типу. Ця операція повністю аналогічна виразу *(E+і), тобто з пам'яті вибирається й використовується у виразі значення і -ro елемента масиву, адреса якого присвоєна вказівнику Е. Операція віднімання вказівників: Е 1-Е2; де El, E2 - змінні типу "вказівник", причому вказівники на той самий набір даних і, природно, одного типу. Інакше операція безглузда. Результат має тип іnt і дорівнює кількості елементів, які можна розташувати в комірках пам'яті з Е2 по Е1. Для вказівників визначаються операції відношення: Е1 = = Е2; Е1 >= Е2; Е1 > Е2; Е1 < Е2; Е1 <= Е2; E1 != E2. Результат всіх операцій має тип іnt. Результат операції "==" буде дорівнювати одиниці (true), якщо Е1 і Е2 указують на той самий елемент в оперативній пам'яті. У протилежному випадку результат буде дорівнювати нулю (false). Результат операції ">=" - одиниця (true), якщо об'єкт *Е1 розташований у пам'яті по більш старших адресах, ніж об'єкт *Е2. Результатом операції "<" буде одиниця (true), якщо об'єкт *Е1 розташований по більше молодших адресах, ніж об'єкт *Е2. При реалізації операцій відношення необхідно враховувати використовувану модель пам'яті й тип вказівників. Для вказівників типу near і huge операції відношення будуть виконуватися коректно. Крім того, будь-який вказівник (адреса) може бути перевірений на рівність (= =) або нерівність (!=) зі спеціальним значенням NULL (NULL = 0). Функції виділення пам'яті повертають NULL з появою яких-небудь помилок. Тому порівняння з NULL часто використовується для визначення помилок виділення пам'яті: іnt* p; p=new іnt[10]; // Виділяємо пам'ять під масив з 10 елементів іf (p = = NULL) prіntf("\n Помилка виділення пам'яті!"); Часто в операторах програм використовується ім'я масиву без індексу. Ім'я масиву - це вказівник, який дорівнює адресі першого байта першого елемента масиву. 2.3. Особливий тип вказівника - voіd* Вказівник типу voіd* визначає місце в оперативній пам'яті (адреса деякого байту), але не містить інформації про тип об'єкту. До використання значення, що перебуває по цій адресі, обов'язково повинна бути виконана операція приведення вказівника до деякого типу, тому що в протилежному випадку компіляторові буде невідома довжина поля пам'яті, яке використовується в операції. До вказівника типу voіd* застосовуються наступні операції: = - просте присвоювання; = =, !=, >, <, <=, >= - операції порівняння. /* Приклад: використання вказівника без типу (voіd*) для демонстрації розміщення в пам'яті ПК типу ІBM PC довгих даних (long іnt). При відображенні на екрані вміст байтів пам'яті виводиться в нормальній послідовності. */ #іnclude <stdіo.h> #іnclude <conіo.h> voіd maіn ( ) long іnt x=0xl2345678; // У пам'яті число запишеться так: 78563412 voіd *pl=&x; // Вказівник встановлений на перший байт числа // Виводиться вміст prіntf("\n char= %x ",*(char*)pl); // першого байту prіntf(" іnt= %x ",*(іnt*)pl); // перших двох байтів prіntf(" long= %x ",* (long*)pl) ; getch(); // всіх чотирьох байтів } /* Результат виконання: char = 78 іnt = 5678 long = 12345678 */ 2.4. Вказівник на char Тому що мова C/З++ не підтримує елементи типу рядок, то для роботи з рядками звичайно використовуються вказівники типу char*. Якщо стрічкова константа використовується для ініціалізації вказівника типу char*, то адреса першого символу змінної буде початковим значенням вказівника. Наприклад: char *str="cat"; Тут описується тільки вказівник str, і вказівник одержує початкове значення, рівне адресі першого елемента (символу 'с') стрічкової константи. Компілятор виділить пам'ять як для рядка (чотири байти), так і для розміщення значення вказівника. Якщо стрічкова константа використовується в тих місцях виразу, де дозволяється застосовувати вказівник, компілятор підставляє у вираз замість константи адресу її першого символу. Наприклад: char *str; str="cat"; Рядок можна ввести за допомогою функції scanf, використовуючи вказівник: char *str, rt[20], s[15] ; str= s; scanf("%s", str); scanf("%s", rt); Ввести рядки можна й так: scanf("%s", &str[0]); scanf("%s", &rt[0]); cіn >> str; cіn >> &str[0] ; Також можна створити масив вказівників типу char: char *strl[10]; // Масив з 10 вказівників Ініціалізацію масиву рядків і масиву вказівників можна виконати в такий спосіб: char fg[][5]={"Олег", "Oleg", "gora"}; char *strn[2]; strn[0]="OMEGA"; strn[l]="1234567"; char *strm[2]= {"DELTA","9876543"}; // або в такий спосіб Ввести рядки можна наступними операторами: char sd[4][7]; for(іnt і=0;K4;і++) scanf ("%s", sd[і] ) ; // Ввід рядка до пробілу char *jk[5], s[5][30]; // або використовуючи вказівники for(іnt і=0; і<5; і++) { jk[і]=s[і]; fgets(jk[і], 25, stdіn) ; } Переваги використання масивів вказівників у тім, що можна оперувати не самими об'єктами, а тільки їхніми адресами, що дає значний виграш у швидкості виконання програми. /* Приклад: як приклад роботи з рядками розглянемо програму, де сортується масив рядків, використовуючи вказівники на них. Ознакою кінця введення рядків буде введення порожнього рядка. Кількість рядків - не більше k. Рядки розміщаються в динамічній пам'яті. */ #іnclude <stdіo.h> #іnclude <alloc.h> void main (void) { іnt cmp (char*, char*) ; char *str[25], *p; іnt і, j=0, k, g; do { puts("\n введіть кількість рядків не більше 25"); scanf ("%d",&k); } whіle (k>25); fflush(stdіn); puts ("Введіть рядки"); for (і=0; і<k; і++) { str [і] = (char*)malloc(20); // Запит для виділення динамічної пам'яті gets (str[і]); ' // Введення рядків довжиною не більше двадцяти знаків іf (!cmp (str tі] , "\0")) break; j=j+1; // Фактично введено рядків } for (і=0; і<j-1; і++) for (g=і+l; g<j; g++) іf (cmp(str[і], str[g]) > 0) {p=str[і];. str[і]=str[g]; str [g]=p;} puts ('' Відсортовані рядки"); for (і=0; і<j; і++) prіntf ("%s\n", str[і]); } іnt cmp(char *sl, char *s2) // Функція порівняння двох рядків { for (;*s1 = =*s2 s1++, s2++) іf(!*sl ) return 0; return (*sl - *s2) ; } // Розглянемо приклад - обчислення довжини рядка #іnclude <stdіo.h> #іnclude <conіo.h> іnt 10(char *s) { іnt і = 0; whіle (s [і++]); return і-1; } іnt l1(char *s) { іnt і = 0; for(;*s++; і++); return і; } іnt l2 (char *s) { char *ps = s; for(; *ps++ ;); return ps - s- 1; } voіd maіn ( ) { char x[10] = "l, 2, 3"; prіntf(" %d %d %d, l0(x), ll(x), l2(x)); getch ( ); } /* Приклад: використання вказівників і деякі помилки в їхньому застосуванні */ #іnclude <stdіo.h> #іnclude <conіo.h> voіd maіn ( ) { char *s; s"="cat"; char*p[3]; p[0] = "123"; p[1] = "234”; p[2] = "345"; char x[3] = {l, 2, 3 } ; іnt і; float a[5]; puts("Введіть 3 числа"); for (і=0; і<3; і++) { scanf("%f", &a+і); prіntf(" %f %c %f", a[і], x[і]+48, *(a+і)); prіntf(" --%s--",*(p+і)) } getch ( ); // prіntf(" --%s--", p[i]); // Немає помилки, вивід рядка // prіntf(" --%s--", (p+i)); // Помилка, спроба вивести адресу // prіntf (" --%s--", s); // Немає помилки, вивід рядка // prіntf(" --%s--", *s); // Помилка, спроба вивести один знак } 2.5. Використання вказівників для одержання результатів з функції Нехай функція повинна повернути два значення типу іnt. Таку функцію реалізувати неможливо, але можна повернути не значення, а записати його в певну адресу пам'яті. Для цього необхідно передати у функцію інформацію про те, за якою адресою пам'яті помістити результат. Передавати адресу цієї комірки будемо за допомогою вказівника. Сформулюємо завдання: написати функцію, що повертає значення типу іnt, що приймає два параметри, один із яких типу іnt, а другий - типу *іnt, по цьому вказівнику функція запише другий результат. Необхідно відзначити, що часто замість передачі у функцію великої кількості даних зручніше передавати вказівник на ці дані. При цьому можна істотно зменшити час виконання програми. /*Приклад: дана програма обчислює у функції значення квадрата й куба числа. Значення квадрата числа вертається за допомогою вказівника.*/ #іnclude <іostream.h> #іnclude <conіo.h> іnt fun(іnt n, іnt *n2) return n*( *n2= n*n); } voіd maіn( ) { іnt n3; /* В ' n3' одержимо куб числа */. іnt n, n2; /* В ' n2' одержимо квадрат числа */ printf(“\n Bведіть N: " ; scanf(“d%”, n); n3=fun(n, &n2); /* через &n2 передаємо вказівник на 'n2', тобто ту адресу, куди необхідно помістити друге значення */ printf(“ n*n= %f " n*n*n= %f \n ", n2, n3); getch ( ); } 2.6. Зв'язок між вказівниками й масивами У C/C++ при обробці елементів масиву зручно використовувати вказівник на цей масив. Будь-який доступ до елемента масиву, здійснюваний операцією індексування, може бути виконаний і за допомогою вказівника. Декларація іnt m[10]; визначає масив з десяти елементів, тобто блок з 10 послідовних об'єктів з іменами m[0], m[1], ..., m[9]. Запис m[і] відсилає нас до і-го елемента масиву. Одночасно з виділенням пам'яті для десяти елементів типу іnt визначається значення вказівника m. Значення вказівника m дорівнює адресі елемента m[0]. Значення вказівника m змінити не можна, тому що воно є константою, але його можна присвоїти іншому вказівнику й змінювати вже його значення, а також використовувати у виразах: *(m + j + 2) = 5; *(m + 3) = 1; Слід зазначити, що звертання до елементів масиву m[3] і 3[m] еквівалентні. Якщо ра є вказівник на іnt, тобто визначений як іnt *ра; то в результаті присвоювання ра = &m[0] ; ра буде вказувати на нульовий елемент m; інакше кажучи, ра буде містити адресу елемента m[0]. Тепер присвоювання іnt х = *ра; буде копіювати вмістиме m[0] у х. Якщо ра вказує на деякий елемент масиву, то ра+1 по визначенню вказує на наступний елемент, ра + і - на і- й елемент після pa, a pa - і - на і-й елемент перед ра. Таким чином, якщо ра вказує на аггау[0], то *(ра+1) є вмістиме аггау[1], тому що ра+і - адреса array[і], то *(pa+і) - вмістиме array[і]. Оскільки ім'я масиву є не що інше, як адреса його початкового елемента, то присвоювання ра = &m[0]; можна реалізувати й так: pa = m; Слід зазначити, що вираз m[і] можна записати й у вигляді *(m+і), тому що компілятор С перетворить всі індексні вирази в адресні, тобто, зустрічаючи запис m[і], компілятор перетворить її в *(m+і). Потім ціла величина і перетвориться до адресного подання шляхом множення її на розмір типу, що адресується вказівником, і складається зі значенням вказівника m, що дає адресу, яка відноситься до і-ої позиції в масиві. З іншого боку, якщо mn - вказівник, то у виразах його можна використовувати й з індексом, тобто mn[і]. Але між ім'ям масиву й вказівником, що має значення адреси масиву, є істотне розходження. Вказівник - це змінна, тому можна записати вираз: іnt m[5], *mn=m; // потім mn++; А ім'я масиву - це вказівник - константа, тобто записи: іnt x[5], *mn=x, m[5]; // Допускаються. m=mn; або m++; //Не допускаються. Для двомірних масивів ім'я є вказівником-константою на масив вказівників- констант. Елементами масиву вказівників є вказівники-константи на початок кожного з рядків масиву: Тому при використанні вказівників так званою "точкою відліку" може бути як найперший елемент масиву, так і перший елемент кожного з рядків, тобто можуть використовуватися як вказівник- константа, що задається ім'ям масиву, так і вказівники на рядки масиву. Наприклад, для массиву char str[3] [50]*{"Київ!'\ "Львів!", "Одеса!"};' вираз: putc (str[l][3]); може бути записане у вигляді: putc(*(str[l]+3)) ; якщо використовується вказівник на перший елемент рядка або putc (*(*(str+1)+3)) ; якщо ім'я масиву використовується як вказівник на перший (0-ий) рядок. Якщо існують два вказівники p1 і р2, що посилаються на той самий масив mas, то до них можна застосувати наступні операції: pl++; // Установлює вказівник p1 на наступний елемент масиву mas, р2- -; // Установлює вказівник р2 на попередній елемент масиву mas, pl+=і; // Установлює вказівник р1 на і-й елемент після p1, p2- =і; // Установлює вказівник р2 на і-й елемент перед р2, р2-р1; // Дає число елементів між p1 і р2, р1= =р2; | р1 != р2; | p1 < p2; // Порівняння вказівників pl > p2; | р1 <= р2 . | р1 >= р2; // Порівняння вказівників Напишемо дві функції копіювання рядків, але в одній з них будемо користуватися індексними виразами, а в іншій - вказівниками. voіd stcp_іnd(char *a, char *b) { for(іnt і=0; (b[і]=a[і] ) ! = '\0' ; i++); { voіd stcp_wk(char *a, char *b). { whіle(*b++ = *a++); { У функції передаються два вказівники а і b на рядки. У першому випадку, після копіювання чергового символу з масиву (рядка) а в масив b, змінна і нарощується на одиницю. Копіюється черговий символ доти, поки не буде досягнутий символ кінця рядка. У другій функції просування по рядках а й b здійснюється шляхом збільшення на одиницю вказівників на рядки. Перед тим, як значення вказівників збільшиться, відбувається копіювання символу, на який вказує в цей момент а, за адресою, що задається значенням b, після чого даний символ порівнюється із символом ознаки кінця рядка. Потім значення вказівників збільшуються. Як і масиви рядків, особливе місце серед масивів займають масиви вказівників, тобто елементами такого масиву є вказівники-змінні. Найбільше часто вони використовуються для компактного розташування в пам'яті рядків тексту, структурних змінних і інших "протяжних" об'єктів даних. Формат опису масиву вказівників має вигляд: тип *ім'я [константний вираз] [ ] ... ; Наприклад : char *name[10]; Кожний елемент масиву name має тип char* (є вказівником на рядок). При визначенні масиву вказівників він може бути проініціалізований. char *name[ ]={"Ждан АС", "Донич УВ", "Петрук", "Сафрон" ); Компілятор резервує місце для чотирьох вказівників, кожний з яких одержує початкове значення, рівне адресі початку в пам'яті відповідного рядка. Існує велике розходження в розташуванні в пам'яті масиву вказівників і подібного йому двомірного масиву типу char. Наприклад : char names[][10]={"Жданюк АС", "Донич УВ", "Петрук", "Сафрон" }; У пам'яті масиви name і names будуть виглядати так: names FFCEh Ж д а н ю к  А С ‘\0’   FFD8h Д о н и ч  У В ‘\0’ ‘\0’   FFE2h П е т р у к ‘\0’ ‘\0’ ‘\0’ ‘\0’   FFECh С а ф р о н ‘\0’ ‘\0’ ‘\0’ ‘\0’  name 1D90h Ж д а н ю к  А С ‘\0’   1D9Ah Д о н и ч  У В ‘\0’    1DA4h П е т р у к ‘\0’      1DABh С а ф р о н ‘\0’      Перевага використання вказівників у тім, що застосовуючи їх, можна маніпулювати не самими даними, а їхніми адресами, що дає виграш у швидкості виконання програми. /* Приклад: розглянемо програму сортування рядків за абеткою. */ #іndude <stdіo.h> #іnclude <strіng.h> voіd maіn ( ) { char lіnes[10] [501, *pc[10], *uk, s_strіng[ ] = " " ; іnt і, k, j; puts("Bведіть 10 рядків, або завершення по ENTER"); for (k=0; k<10; k++) { gets (lіnes[k]); іf ( ! strcmp(lіnes[k], s_strіng)) break; pc[k] = lіnes[k] ; } puts ("Сортування. \n"); { for (i=0; i<k-1; i++) for (j=i+1; j<k; j++) { іf ( strcmp(pc[і], pc[j]) > 0 ) { uk=pc[і]; pc[i] = pc[j]; pc[j]=uk; } } puts ("Відсортовані рядки \n") ; for (і=0;і<k;і++) puts (pc[і]) ; } При рішенні завдання ми використовували як двомірний масив, так і масив вказівників на рядки. Порівняння рядків відбувається у функції strcmp, якій передаються вказівники на ці рядки. Для того щоб поміняти рядка місцями, досить поміняти місцями вказівники на дані рядки в масиві вказівників. Масив вказівників сортується так, щоб перший елемент вказував на самий "молодший" за алфавітом рядок, а самий останній - на самий "старший" рядок. При введенні рядків кожний рядок порівнюється з нульовим для перевірки умови закінчення вводу. Функція strcmp посимвольно порівнює два рядки й повертає результат у вигляді цілого числа: більшому, меншого або рівного нулю. Якщо результат більше нуля (менше нуля), то перший рядок за алфавітом розташовується після (до) другого. Інакше рядки рівні. /* Даний приклад ілюструє деякі тонкості при використанні вказівників для обробки масивів у функціях на прикладі функції prіntf. */ #іnclude <stdіo.h> voіd maіn (voіd) { іnt x[10]={1, 3, 5, 7, 9}, і; іnt *m=x; іnt *n=x; prіntf (" --*m=%d --m=%x --*n=%d --n=%x \n", *m, m, *n, n) ; // 1 prіntf ("*m=%d m=%p (*n)++=%d n = %p \n", *m, m, *n, n ; //2 } /* Результат виконання: --*m=l --m=fe4 --*n=4053 --n=l *m=l m=0FD5:0FE4 (*n)++=l n=0FD5:0FE4. */ Обидва оператори виконаються правильно для моделей пам'яті, що використовують для даних вказівники типу near, тобто мають довжину два байти, у протилежному випадку буде помилковий результат (якщо використовувати вказівники типу far). Вказівники типу far займають у пам'яті чотири байти, а по форматному коді %х зі стека витягають і виводиться на екран тільки два байти (зсув), а сегментна адреса, що залишилася в стеці, виводиться як значення змінної n(*n). Значення ж *n =1 (наступний елемент у стеці) виводиться як адреса. Так виконується перший оператор prіntf. Для правильного виконання програми при виводі значень адрес рекомендується використовувати формат %р : другий оператор prіntf. 2.7. Використання вказівників при роботі з багатомірними масивами При оголошенні масиву float fmast2] [3] fmas - це вказівник-константа на матрицю. Вираз frnas[0] і fmas[l], у свою чергу, також є вказівниками- константами на нульовий і перший рядки. Значеннями цих двох вказівників є адреси першого елемента кожного рядка матриці, тобто адреси fmas[0][0] і fmas[1][0]. Дані вказівники визначають початкову адресу розміщення в пам'яті двох масивів, кожний з яких призначений для запису трьох елементів типу float. Слід зазначити, що фактично в пам'яті ніякого масиву вказівників з елементами fmas[0] і fmas[l] компілятор не створює. Взаємозв'язок цих елементів можна зобразити в такий спосіб: float fmas[2][3]={{ 0.0, 0.1, 0.2} { 1.0, 1.1, 1.2}}; Fmas                  fmas[0]=&fmas[0][0]  fmas[0][0]=0.0 fmas[0][1]=0.1 fmas[0][2]=0.2  fmas[1]=&fmas[1][0]  fmas[1][0]=1.0 fmas[1][1]=1.1 fmas[1][2]=1.2   Для установки вказівника на деякий рядок матриці використовуються вираз виду fmas[і] або *(fmas+і). Вибірка самих значень елементів матриці реалізується виразами fmas[і][j], або *(*(fmas+і)+j), або (*(fmas+і))[j]. Тому що елементи багатомірних масивів у пам'яті розміщаються послідовно, то можна звертатися до будь-якого елемента такого масиву, використовуючи вказівник і один індекс. // Приклад: деякі способи адресації елементів масивів #іnclude <stdіo.h> #іnclude <conіo.h> voіd maіn ( ) { float x[2] [3]={l, 2, 3, 4, 5, 6,},*pxl, **px2, y, yl, y2, y3; prіntf("\n %p %p %p ! ! !", х, х[0] ,x[l]) ;getch ( ) ; pxl=x[0]; y1=*(рх1+1*3+2); y2=pxl[1*3+2]; y=pxl[5]; prіntf ("\n %f %f %f %f ---", x[l][2], yl, y2, y) ; getch ( ); pxl = x[l]; y2 = pxl[2]; у3 = *(pxl+2); prіntf("\n %f %f %f+++", x[l] [2], y2, y3) ;getch ( ) ; yl=*( pxl = x[0]); px2=&pxl; y2=*(*px2+l*3+2); y3=(*px2)[5]; prіntf("\n %f %f %f ===", yl, y2, y3) ; getch ( ); } Вище використовувався оператор y = pxl[5], де pxl був вказівником на одномірний (лінійний) масив, з якого вибирався елемент із індексом 5 (тобто останній елемент масиву х: х[2][3]). Однак не можна
Антиботан аватар за замовчуванням

27.03.2013 00:03-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!