Процедурное программирование на языке С. Часть 1. Основные понятия языка С: Методические указания к лабораторным работам по курсам «Алгоритмические языки и программирование» и «Процедурное программирование», страница 14

Замечание. После выделения (изменения) динамической памяти и адресации ее переменной-указателем ptr с помощью  функций  mаlloc(), саlloc()  и reаlloc(), значение указателя ptrможно менять как угодно в соответствии с правилами адресной арифметики. При этом допускается и выход за границы выделенных участков памяти, однако о содержимом этих участков памяти ничего неизвестно, поэтому в такой ситуации результат работы программы не предсказуем.

5. Функция free() предназначена для освобождения выделенного ранее в программе участка динамической памяти.

Заголовок функции free() :   void free(void *ptr) . В соответствии с заголовком функция имеет единственный  формальный параметр. После вызова функции участок памяти, адресуемый указателем ptr, становится доступным для выделения  в следующей части программы.

3.6. «ПЕРЕДАЧА» НЕСКОЛЬКИХ ЗНАЧЕНИЙ ИЗ ОДНОЙ ФУНКЦИИ В ДРУГУЮ

Любая функция в соответствии со своим типом может вернуть значение только одного объекта. Однако если вызываемая функция вычисляет значения нескольких объектов, представляющих интерес для вызывающей функции, то все эти полученные значения могут быть переданы из вызываемой функции в вызывающую за счет использования указателей в качестве формальных параметров. При вызове в функцию передаются адреса нескольких объектов (или адрес одного объекта); в процессе работы функции эти адреса (аргументы функции) не изменяются, но в соответствующие им участки памяти записываются новые данные – вычисленные значения объектов. Тем самым и вызываемая, и вызывающая функции имеют доступ к одним и тем же объектам за счет использования адресов этих объектов.

В примере 3.5 используются 2 функции: главная и функция Vvod_Z(), которая  осуществляет ввод значений 3-х переменных, записывая эти значения по 3-м адресам – своим аргументам, тем самым передавая введенные значения в   главную функцию.

В главной функции объявлены 3 переменные:     intn; floatrpcharhc;

В соответствии с этими операторами в оперативной памяти выделяется 7 байт, при этом переменные значений не имеют, но адрес переменной n – 32000,  адрес переменной rp – 32002, адрес переменной hc – 32006.

n rphc

32000  32001 32002 32003 32004 32005 32006     

Указанные адреса можно использовать в качестве аргументов Vvod_Z() при ее вызове из главной функции: Vvod_Z(32000,32002,32006). Для этого достаточно вспомнить 3 правила:

·  Правило 3.1. Обратиться к  адресу переменной можно, используя знак ‘&’.

·  Правило  3.2. Если функция в качестве  i-го фактического параметра (аргумента) получает адрес некоторого объекта, то в заголовке функции i-й формальный параметр должен быть указателем на тип объекта, адрес которого передается. 

·  Правило 3.3. Для записи значения по адресу, который хранится в некоторой переменной, используется операция разыменования, знак которой  – ‘ * ’; знак ставится перед именем этой переменной в левой части оператора присваивания.

Применение этих правил к данной задаче приведет к следующему.

·  Оператор  вызова функции имеет вид:             Vvod_Z (&n,&hc,&rp)  .

·  Заголовок функции имеет вид:voidVvod_Z(int *m,char *ch,float *pr), т.е. функция имеет 3 формальных параметра-указателя с именами  mch, pr, значениями этих переменных  могут быть только  адреса.

·  Запись значений по адресам имеет вид: *m = 10;  *ch =’D’; *pr = 1.8. После выполнения данных операторов в функции Vvod_Z ()  оперативная память преобразуется следующим образом.

n rphc

10

1.8

D

32000  32001 32002 32003 32004 32005 32006     

Переменные nrphc получают значения в процессе работы функции Vvod_Z (), а главная функция, «зная» значения адресов этих переменных, выводит значения переменных на экран. Таким образом, программа, осуществляющая рассмотренные действия, имеет вид.

Пример 3.5.

#include <stdio.h>