|
Программирование >> Процедурные приложения
пропускается и активным становится следующий аргумент. Выражение с инкрементом взято в круглые скобки, так как идущий следом оператор индексации (квадратные скобки) имеет более высокий приоритет, и без скобок выражение возвращало бы второй символ имени программы. Поскольку значение указателя 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
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |