Так как в "с" передача аргументов функциям осуществляет-ся "по значению", вызванная процедура не имеет непосредст-венной возможности изменить переменную из вызывающей прог-раммы. Что же делать, если вам действительно надо изменитьаргумент? например, программа сортировки захотела бы поме-нять два нарушающих порядок элемента с помощью функции сименем SWAP. Для этого недостаточно написать SWAP(A, B); определив функцию SWAP при этом следующим образом: SWAP(X, Y) /* WRONG */ INT X, Y; { INT TEMP; TEMP = X; X = Y; Y = TEMP; } из-за вызова по значению SWAP не может воздействовать наагументы A и B в вызывающей функции. К счастью, все же имеется возможность получить желаемыйэффект. Вызывающая программа передает указатели подлежащихизменению значений: SWAP(&A, &B);так как операция & выдает адрес переменной, то &A являетсяуказателем на A. В самой SWAP аргументы описываются как ука-затели и доступ к фактическим операндам осуществляется черезних. SWAP(PX, PY) /* INTERCHANGE *PX AND *PY */INT *PX, *PY;{ INT TEMP; TEMP = *PX; *PX = *PY; *PY = TEMP;} Указатели в качестве аргументов обычно используются вфункциях, которые должны возвращать более одного значения.(Можно сказать, что SWAP вOзвращает два значения, новые зна-чения ее аргументов). В качестве примера рассмотрим функциюGETINT, которая осуществляет преобразование поступающих всвоболном формате данных, разделяя поток символов на целыезначения, по одному целому за одно обращение. Функция GETINTдолжна возвращать либо найденное значение, либо признак кон-ца файла, если входные данные полностью исчерпаны. Эти зна-чения должны возвращаться как отдельные объекты, какое бызначение ни использовалось для EOF, даже если это значениевводимого целого. Одно из решений, основывающееся на описываемой в главе 7функции ввода SCANF, состоит в том, чтобы при выходе на ко-нец файла GETINT возвращала EOF в качестве значения функции;любое другое возвращенное значение говорит о нахождении нор-мального целого. Численное же значение найденного целоговозвращается через аргумент, который должен быть указателемцелого. Эта организация разделяет статус конца файла и чис-ленные значения. Следующий цикл заполняет массив целыми с помощью обраще-ний к функции GETINT: INT N, V, ARRAY[SIZE]; FOR (N = 0; N < SIZE && GETINT(&V) != EOF; N++) ARRAY[N] = V; В результате каждого обращения V становится равным следующе-му целому значению, найденному во входных данных. Обратитевнимание, что в качестве аргумента GETINT необходимо указать&V а не V. Использование просто V скорее всего приведет кошибке адресации, поскольку GETINT полагает, что она работа-ет именно с указателем. Сама GETINT является очевидной модификацией написаннойнами ранее функции ATOI: GETINT(PN) /* GET NEXT INTEGER FROM INPUT */ INT *PN; { INT C,SIGN; WHILE ((C = GETCH()) == ' ' \!\! C == '\N' \!\! C == '\T'); /* SKIP WHITE SPACE */ SIGN = 1; IF (C == '+' \!\! C == '-') { /* RECORD SIGN */ SIGN = (C == '+') ? 1 : -1; C = GETCH(); } FOR (*PN = 0; C >= '0' && C <= '9'; C = GETCH()) *PN = 10 * *PN + C - '0'; *PN *= SIGN; IF (C != EOF) UNGETCH(C); RETURN(C); } Выражение *PN используется всюду в GETINT как обычная пере-менная типа INT. Мы также использовали функции GETCH иUNGETCH (описанные в главе 4) , так что один лишний символ,кототрый приходится считывать, может быть помещен обратно воввод. Упражнение 5-1 --------------- Напишите функцию GETFLOAT, аналог GETINT для чисел сплавающей точкой. Какой тип должна возвращать GETFLOAT в ка-честве значения функции?