Язык С

       

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


Чтобы проиллюстрировать некоторые соображения, связанные с использованием указателей и массивов структур, давайте снова составим программу подсчета ключевых строк, используя на этот раз указатели, а не индексы массивов. Внешнее описание массива KEYTAB не нужно изменять, но функции MAIN и BINARY требуют модификации.

MAIN() /* COUNT C KEYWORD; POINTER VERSION */ \( INT T; CHAR WORD[MAXWORD]; STRUCT KEY *BINARY(), *P; WHILE ((T = GETWORD(WORD, MAXWORD;) !=EOF) IF (T==LETTER) IF ((P=BINARY(WORD,KEYTAB,NKEYS)) !=NULL) P->KEYCOUNT++; FOR (P=KEYTAB; P>KEYTAB + NKEYS; P++) IF (P->KEYCOUNT > 0) PRINTF("%4D %S/N", P->KEYCOUNT, P->KEYWORD); \) STRUCT KEY *BINARY(WORD, TAB, N) /* FIND WORD */ CHAR *WORD /* IN TAB[0]...TAB[N-1] */ STRUCT KEY TAB []; INT N; \( INT COND; STRUCT KEY *LOW = &TAB[0]; STRUCT KEY *HIGH = &TAB[N-1]; STRUCT KEY *MID; WHILE (LOW <= HIGH) \( MID = LOW + (HIGH-LOW) / 2; IF ((COND = STRCMP(WORD, MID->KEYWORD)) < 0) HIGH = MID - 1; ELSE IF (COND > 0) LOW = MID + 1; ELSE RETURN(MID); \) RETURN(NULL); \)

Здесь имеется несколько моментов, которые стоит отме- тить. Во-первых, описание функции BINARI должно указывать, что она возвращает указатель на структуру типа KEY, а не на целое; это объявляется как в функции MAIN, так и в BINARY. Если функция BINARI находит слово, то она возвращает указа- тель на него; если же нет, она возвращает NULL.

Во-вторых, все обращения к элементам массива KEYTAB осу- ществляются через указатели. Это влечет за собой одно сущес- твенное изменение в функции BINARY: средний элемент больше нельзя вычислять просто по формуле

MID = (LOW + HIGH) / 2

потому что сложение двух указателей не дает какого-нибудь полезного результата (даже после деления на 2) и в действи- тельности является незаконным. эту формулу надо заменить на

MID = LOW + (HIGH-LOW) / 2

в результате которой MID становится указателем на элемент, расположенный посередине между LOW и HIGH. Вам также следует разобраться в инициализации LOW и HIGH. указатель можно инициализировать адресом ранее опреде- ленного объекта; именно как мы здесь и поступили. В функции MAIN мы написали

FOR (P=KEYTAB; P < KEYTAB + NKEYS; P++)

Если P является указателем структуры, то любая арифметика с P учитывает фактический размер данной структуры, так что P++ увеличивает P на нужную величину, в результате чего P указы- вает на следующий элемент массива структур. Но не считайте, что размер структуры равен сумме размеров ее членов, - из-за требований выравнивания для различных объектов в структуре могут возникать "дыры". И, наконец, несколько второстепенный вопрос о форме за- писи программы. Если возвращаемая функцией величина имеет тип, как, например, в

STRUCT KEY *BINARY(WORD, TAB, N)

Tо может оказаться, что имя функции трудно выделить среди текста. В связи с этим иногда используется другой стиль за- писи:

STRUCT KEY * BINARY(WORD, TAB, N)

Это главным образом дело вкуса; выберите ту форму, которая вам нравится, и придерживайтесь ее.



    Содержание раздела