|
|
Структуры
6.4. Указатели на структуры
Чтобы проиллюстрировать некоторые соображения, связанные с использованием указателей и массивов структур, давайте снова составим программу подсчета ключевых строк, используя на этот раз указатели, а не индексы массивов.
Внешнее описание массива 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);
}Здесь имеется несколько моментов, которые стоит отметить. Во-первых, описание функции binary должно указывать, что она возвращает указатель на структуру типа key, а не на целое; это объявляется как в функции main, так и в binary. Если функция binary находит слово, то она возвращает указатель на него; если же нет, она возвращает null.
Во-вторых, все обращения к элементам массива keytab осуществляются через указатели. Это влечет за собой одно существенное изменение в функции binary: средний элемент больше нельзя вычислять просто по формуле
mid = (low + high) / 2
потому что сложение двух указателей не дает какого-нибудь полезного результата (даже после деления на 2) и в действительности является незаконным. Эту формулу надо заменить на
mid = low + (high-low) / 2
в результате которой mid становится указателем на элемент, расположенный посередине между low и high.
Вам также следует разобраться в инициализации low и high. указатель можно инициализировать адресом ранее определенного объекта; именно как мы здесь и поступили.
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)
Это главным образом дело вкуса; выберите ту форму, которая вам нравится, и придерживайтесь ее.
