Масиви и указатели на символни низове
Показатели
Указателят се декларира по следния начин:
Операции върху указатели.Има две специални операции, свързани с указатели & И *. И двете операции са унарни, т.е. имат един операнд, пред който се поставят.
В указателя базовият тип е много важен, т.к той определя колко байта заема обектът, към който сочи показалецът. Ако int е 2 байта, char е един байт и т.н. Ще демонстрираме най-простите действия с указатели, използвайки следната програма.
printf("x = %f y= %f", x, y); // Резултат: x=10.1; y=10.1; pf=632
printf("x = %f y = %f", x, y); // Резултат: x=10.1; y=10.1; pf=636
printf("x = %f y = %f", x, y); // Резултат: x=10.1; y=1; pf=636
Както при другите типове променливи, аритметични операции събиране и изваждане, както и операции (++) и (--) могат да се извършват върху указатели. Указателите могат да се сравняват. Приложими са шест операции:
Ако показалецът е зададен на 0, това означава, че показалецът не сочи към никакъв обект. Опитът да се използва тази стойност при достъп до динамичен обект ще доведе до грешка. По конвенция името NULL се използва за обозначаване на константа със стойност нула.
1.2.1 Динамични обекти
Указателите се използват при създаване и обработка на динамични обекти.
Динамичните обекти, за разлика от предварително дефинираните, се създават по време на изпълнение на програмата.
Има специални функции за това:
malloc() и calloc().
Спецификации на тези функции:
размер без знак (количеството памет за разпределяне в байтове);
char *calloc(nelem, elsize);
unsigned nelem (брой елементи за разпределяне на паметта)
unsigned elsize (томпамет, която трябва да бъде разпределена за всеки елемент)
И двете функции връщат указател, сочещ към създадения динамичен обект (към областта на паметта, разпределена за него).
За да определите необходимото количество памет, можете да използвате оператора sizeof (T), който връща броя байтове, необходими за съхраняване на стойностите на обекта T в паметта.
int P=(int *) malloc(sizeof (int));
Паметта се разпределя за една цяло число. Адресът на тази област от паметта се присвоява на p, след като е преобразуван от char* в int*.
Деклариране на едномерен масив:
Деклариране на двуизмерен масив с помощта на указатели:
int **r = (int**) malloc(n*sizeof(int*));
Така че действието за писане
може да се обясни така
// следните операции ще дадат същия резултат:
// следната операция ще добави 2 към първия елемент:
При това трябва да се има предвид, че
Има някои ограничения за операции с постоянни указатели. По-конкретно, следният пример показва невалидна конструкция:
mas=ptr; // невалиден израз, защото mas е постоянен указател и не може да бъде променен.
Освен това, например, операциите за единично нарастване ++ могат да се прилагат само към променливи. Следователно ptr++ е валидна конструкция, докато mas++ е незаконна. И в двата случая обаче е възможно да се използват операции за добавяне с указател, т.е. ptr+i; и mas + i; - разрешени строежи.
Указатели и многомерни масиви.Помислете за двумерен масив и операции с указатели.
ptr сега сочи към първата колона на първия ред, т.е.
ptr+3 = = &mas[1][1] и т.н.
Двумерният масив може да се разглежда като масив от масиви. В нашия случай имамеМасив от четири елемента с два елемента. Трябва да се отбележи, че този масив от четири елемента може да бъде представен като едномерен mas[0],…,mas[3]. В този случай името на масива все още е указател към първия му елемент, т.е. mas[0]= =&mas[0] [0] . Какво ще посочи mas[i]? В този случай mas[i] сочи към i-тия ред, т.е. към първия елемент на i -тия ред. По този начин
Масиви и указатели на символни низове
Често се налага да се работи със символни низове. Няма специален тип "низ" в езика C. Вместо това всеки символен низ в паметта на компютъра се представя като едномерен масив от тип char, чийто последен елемент е знакът '\0'.
Възможни са следните типове дефиниции на символен масив:
1) "праволинеен", т.е. масив от тип char е посочен със специфична стойност за ограничение на размера, съответстваща на максималния брой знаци в низ. Например, нека дефинираме масив от знаци за съхранение на 10 низа, всеки от които може да съдържа не повече от 20 знака:
2) Когато дефинирате масив, един от неговите максимални размери (най-левият индекс) може да бъде пропуснат. В този случай броят на елементите на масива се определя, например, по време на инициализацията:

И в първия, и във втория случай се наблюдава нерационално използване на паметта. Дори за къси низове винаги се разпределя същият брой байтове, предварително зададени като гранични стойности в първия и втория случай при дефиниране на масиви string_1 и string_2.
3) Използване на масив от указатели от тип char*: