8.4  Указатели на структуры

Указатели на структуры описываются точно так же, как и  указатели на другие типы  данных.  Существуют, по крайней мере, три причины использования указателей на структуры:

1) указателями проще управлять (например, при сортировке), чем самими структурами;

2) в некоторых версиях языка структура не может передаваться функции в качестве аргумента, но это возможно для указателя на структуру;

3) во многих эффективных представлениях данных используются структуры, которые содержат указатели на другие структуры данных.

Указатели на структуры используются при создании различных динамических структур  данных, связанных списков, элементами которых, в свою очередь, являются структуры данных и т.д. Например, пусть необходимо создать объект, описывающий информацию о звезде: ее имя,  спектральный класс, координаты, расстояние. Можно создать тип данных пользователя следующим образом: 

struct star

{

char   name[25];

char   clas;  

short  subclass;

float  decl,RA,dist; 

} ;

Затем можно использовать созданный тип пользователя в программе:

#include <stdlib.h>

#include<string.h>

void main(void)

{

star *mystar;      // создан указатель на структуру star

mystar = (star *) malloc(sizeof(star));   // выполняется инициализация указателя

strcpy(mystar -> name,"Эпсилон Лебедя")

mystar -> clas    = ‘N‘;  

mystar -> subclass =  2;

mystar -> decl     =  3.5167

mystar -> RA       = -9.633

mystar -> dist     =  0.303;

….

free (mystar); 

}

В этом варианте mystar объявлен как указатель типа  star, а не   как переменная типа star.  Память для mystar резервируется путем обращения к функции malloc().  Для ссылки на элементы структуры mystar вместо прямого метода доступа (.) использован косвенный метод доступа, т.е. символ ->. Обе операции, "->" и ".", ассоциируются слева направо, так что эти конструкции эквивалентны.

Операции работы со структурами "->" и "." наряду с круглыми скобками () для списка аргументов и квадратными скобками [ ] для индексов находятся на самом верху иерархии старшинства операций и, следовательно, связываются очень крепко. Если, например, имеется описание

struct {

int x;

int *y;

} *p;

то выражение  ++p->x  увеличивает х, а не р до доступа к х, так как оно эквивалентно выражению ++(p->х).

Для изменения порядка выполнения операций можно использовать круглые скобки: выражение  (++p)->х увеличивает p до доступа к х, а выражение  (p++)->x увеличивает p после доступа к х (круглые скобки в последнем случае необязательны). Аналогично выражение  *p->y извлекает то, на что указывает y; выражение  *p->y++ увеличивает y после того, на что он указывал.