Программирование >>  Процедурные приложения 

1 ... 55 56 57 [ 58 ] 59 60 61 ... 150


пропускается и активным становится следующий аргумент. Выражение с инкрементом взято в круглые скобки, так как идущий следом оператор индексации (квадратные скобки) имеет более высокий приоритет, и без скобок выражение возвращало бы второй символ имени программы.

Поскольку значение указателя argvбыло изменено и он теперь ссылается на второй аргумент командной строки, выражение argv[0] возвращает адрес первого символа этого аргумента. Путем прибавления единицы мы перемещаем указатель ко второму символу, записывая его адрес в переменную psz:

psz = argv[0] + 1;

Анализируя значение этого символа, программа определяет, какую задачу ставит перед ней пользователь: поиск минимального или максимального чисел из списка. При этом в переменной iwhich extreme устанавливается флаг режима

(IFIND SMALLEST - ПОИСК МИНИМAЛЬНОГО ЧИСЛA,IFIND LARGEST - МAКСИМAЛЬНОГО),

а в переменную irange boundary записывается начальное значение, с которым будут сравниваться числовые аргументы. Из соображений совместимости мы предполагаем, что неотрицательные числа типа int попадут в диапазон 0-32767, что соответствует 16-разрядным системам. В случае, если пользователь задаст неверную опцию, скажем, -d или -su, в ветви default будет выведено соответствующее сообщение. Проверка

if(--argc ==0)

позволяет убедиться, что после опции указан хотя бы один числовой аргумент. В противном случае программа завершит свою работу. Последняя строка данного блока

argv++;

необходима для того, чтобы переместить указатель argv на аргумент, идущий после опции.

Функция atoi() в цикле while преобразовывает каждый из аргументов в целое число (не забывайте, что на данный момент все они представлены в виде массивов символов) и сохраняет результат в переменной present value. Опять-таки после выполнения этой функции указатель argv будет перемещен на следующий аргумент командной строки. В оставшихся двух инструкциях if впеременную irange boundагу записывается текущее минимальное или максимальное значение из списка в зависимости от содержимого флага iwhichextreme.

Дополнительные сведения об указателях на указатели

В следующей программе также демонстрируется применение указателей на указатели. Мы не рассмотрели ее раньше, когда обсуждали соответствующую тему, по той причине, что в этой программе используется динамическая память.

* dblptr.c

* Эта программа на языке С демонстрирует работу с указателями на указатели.

#include <stdio.h> #include <stdlib.h> #define IMAXELEMENTS 3

void voutputdnt (**ppiresult a, int **ppiresult b, int **ррiresult с)

void vassignfint (*pivirtual array[], int *pinewblock); void main ()

int **ppiresult a, **ppiresult b, **ppiresult c; int *pivirtual array[IMAXELEMENTS]; int *pinewblock, *pioldblock;

ppiresult a = &pivirtual array[0]; ppiresult b = &pivirtual array[l]; ,ppiresult c = &pivirtual array[2];

pinewblock = (int *) malloc(IMAXELEMENTS * sizeof(int)); pioldblock =

pinewblock;

vassign(pivirtual array, pinewblock);



**ppiresult a = 7; **ppiresult b = 10; **ppiresult c =15;

voutput(ppiresult a, ppiresult b, ppiresult c); pinewblock = (int *) malloc(IMAXELEMENTS * sizeof(int)); *pinewblock = **ppiresult a; *(pinewblock +1)= **ppiresult b; *(pinewblock +2)= **ppiresult c; free (pioldblock) ;

vassign(pivirtual array, pinewblock); voutput(ppiresult a, ppiresult b, ppiresult c); void yassign(int *pivirtual array [] , int *pinewblock) pivirtual array [0] = pinewblock;

pivirtual af ray [1] = pinewblock + 1;

pivirtual array [2] = pinewblock + 2;

void voutput (int **ppiresult a, int **ppiresult b, int **ppiresult c){ printf ( %d\n ,**ppiresult a) printf ( %d\n ,**ppiresult b) printf ( %d\n ,**ppiresult c)

В этой программе указатели ppiresult a, ppiresult b иppiresult c ссылаются на указатели с постоянными адресами (&pivirtual array[0], spivirtual array[l] , &pivirtual array [2]), но содержимое последних может меняться динамически.

Рассмотрим блок объявлений в функции main(). Переменные ppiresult a, ppiresult b и ppiresult c объявлены как указатели на указатели, содержащие адреса значений типа int. Переменная pivirtual array является массивом указателей типа int с числом элементов, заданным константой imaxelements. Последние две переменные, pinewblock и pioldblock, являются одиночными указателями такого же типа, что и массив pivirtual array. Взаимоотношения между всеми переменными после того, как указателям ppiresult a, pplresult b и ppiresult c были присвоены адреса соответствующих элементов массива pivirtual array, показаны на рис. 9.15.





Рис. 9.15. Взаимоотношения межжду переменными программы после инициализации указателей ppiresult a, pplresult b и ppiresult c

Идея программы заключается в том, чтобы в упрощенной форме проиллюстрировать процессы, на самом деле происходящие в многозадачной среде. Программа считает, что содержит действительный адрес переменной, хотя на самом деле она имеет в своем распоряжении лишь фиксированный адрес ячейки массива, в которой хранится текущий адрес переменной. Когда операционная система в соответствии со своими потребностями перемещает данные, хранимые в оперативной памяти, она автоматически обновляет ссылки на эти данные в массиве указателей. Используемые в программе указатели при этом сохраняют прежние адреса.

На рис. 9.16 показано, что произойдет после того, как в динамическую память будет помещен массив pinewblock, переменной pioldblock будет присвоен его адрес и выполнена функция vassign(). Обратите внимание на соответствие адресов, хранящихся в физическом массиве pinewblockи виртуальном массиве pivirtual array.

В функцию vassign() в качестве аргументов передаются массив pivirtual arгау и адрес только что созданного динамического блока, представленного переменной pinewblock. В теле функции каждому элементу массива присваивается соответствующий ему адрес динамической ячейки памяти. Поскольку обращение к массиву из функции осуществляется по адресу, все изменения вступают в силу и в теле функции main().

На рис. 9.17 показано состояние переменных после присвоения ячейкам динамической памяти трех целочисленных значений.

Далее ситуация становится интереснее. С помощью функции malloc() в динамической памяти создается еще один блок ячеек, адрес которого записывается в указатель pinewblock. А указатель pioldblock по-прежнему связан с созданным ранее блоком. Все это сделано для того, чтобы примерно смоделировать процесс перемещения блока ячеек в новую позицию.


Рис.9.16. Динамическое создание блока ячеек и инициализация массива pivirtual array



1 ... 55 56 57 [ 58 ] 59 60 61 ... 150

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика