Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Не фиксированное число аргументов




Язык программирования С допускает использование пе­ременного числа аргументов. Признаком функции с перемен­ным числом аргументов является многоточие в списке па­раметров прототипа функции. Встретив «...», компилятор прекращает контроль соответствия типов параметров для та­кой функции. Естественно, что функция с переменным числом аргументов должна иметь способ определения точного их числа при каждом вызове. Функции с переменным числом аргументов должны иметь как минимум один фиксированный (1-й) аргумент для того, чтобы была возможность «привязаться» к адресу копии этого аргумента в стеке. Для определения действительного числа переданных в вызове аргументов предлагается использовать следующие 2 метода:

· число действительно переданных аргументов в вызове содержится в 1-м аргументе,

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

Пример

void example(int, …);

…………………………….

void example(int argl,...)

{

int * рtr = &argl; /* установка yказaтeля на первый аргумент */

рrintf("\nФункции ЕХАМРLE передано всего %d аргумента(ов):\n",

argl);

/* Печать всех пеpeдaнных в функцию фактических apгyмeнтoв */

for (; argl; argl--)

{

printf (" %d", * рtr);

ptr++;

}

}

Дополнительные возможности по использованию функций с переменным числом аргументов открывaют специальные типы и макро, включенные в заголовочный файл stdarg.h. Используется рассмотренный ранее метод определения. конца списка по заранее известному значению. Для упрощения работы с переменным числом apгyмeнтов в айле stdarg.h определен особый тип

typedef void *va_list;

Тип va_list используется для описания указателя на нача­ло списка переданных функции фактических аргументов, на­пример:

void example(int argl,...)

{va_list ptr;... }

Для задания начального значения указателю типа va_list ис­пользуется макро va_start(). Макро описано в stdarg.h так:

#define va_start(ap, parmN) (ар=…)

Формальный аргумент parmN - это имя последнего фикси­рованного параметра в списке параметров функции с пере­менным числом аргументов, т. е. значение, к адресу которого осуществляется "привязка" указателя ptr. Особенность такой "привязки" заключается в том, что указатель устанавливает­ся на адрес памяти после фиксированного аргумента. Напри­мер, для приведенной ранее функции example() инициализа­ция указателя ptr выполняется так:

va_start (ptr, argl);

Доступ к значениям в списке фактических параметров вы­полняется через макро va_arg(), которое описано в файле <stdarg. h так:.

#define va_arg(ар, tуре)(*((type *)(ap))++)

Формальный аргумент ap – это имя указателя, используемого для доступа к элементам списка фактических параметров; type – тип переменных (неявно предполагается, что все элементы списка имеют один и тот же тип). Тип возвращаемого макро va_arg(ap, type) значения совпадает с type.

Признаком завершения списка параметров служит зара­нее определенное значение, не совпадающее ни с одним из передаваемых фактических аргументов.

Приведем переработанный пример, где в функции example() с переменным числом аргументов ис­пользуются paccмoтpeнныe макро va_list, va_start(), vф_аrg().

Пример

void example(int,…);

…………………………………………………

void example(int arg1,...)

{

int number = 1, value;

va_list рtr; /* указатель для доступа к списку параметров */

printf(" %d", arg1); /* печать фиксированного аргументa */

/* установка указателя на первый nocлe фиксированного аргумент */

va_staгt(ptr, arg1);

/* Печать переданных в функцию фактических аргументов */

while((value = va_arg(ptr, int))!= EOL)

{

printf(" %d", value); number++;

}

рrintf("\n Функции EXAМPLE пеpeдaнo всего %d аргумента(ов):\n",

number);

}

 

 

Внешние переменные

Любая программа на языке С есть множество внешних объектов, - ли­бо переменных, либо функций. Определение «внешние» используется глав­ным образом для того, чтобы подчеркнуть отличие от «внутренних» объ­ектов – аргументов, автоматических статических или регистровых переменных, определяемых внутри функции. Внешние переменные определены вне любой из функций и, сле­довательно, доступны для многих функций. Сами функции всегда внешние, так как язык не позволяет определять функции внутри других функций.

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

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

Вторая причина использования внешних переменных связана с иници­ацией. В частности, внешние массивы можно инициировать, а автоматиче­ские массивы - нет.

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

Пример

Ввод строк, определение самой длинной строки и ее распечатка.

#include..

#define MAXLINE 1000 /* максимальная длина строки*/

char line [MAXLINE]; /* входная строка – внешняя переменная*/

char save [MAXLINE]; /*самая длинная строка – внешняя переменная */

int max; /* внешняя переменная – длина максимальной строки*/

main() /*поиск самой длинной строки*/

{

int len, getline(), copy();

extern int max; // две необязательные декларации, поскольку max, line, save

extern char save[]; // декларированы выше по тексту

max = 0;

while ((len = getline())>0)

if (len>max)

{

max = len; copy();

}

if (max>0) /* строка вводилась*/

printf (“%s”, save);

return 0;

}

getline() /* ввод строк в line; должно быть описано в getline() */

{

int c,i;

extern char line[];

…………………….

Посимвольный ввод в массив line и добавление в конце строки символа ‘\0’; для ввода используется getchar()

return (длина введенной строки);

}

void copy() /*копирование строки из line в save*/

{

int i;

extern char line[], save[]; //избыточные декларации

i=0;

while ((save[i]) = line[i])!= ’\0’)

++i;

}

Разработку getline() предлагается выполнить самостоятельно.

Копирование строк выполняется до обнаружения символа ‘\0’ в массиве line. Формат «%s» используется для распечатки строк, полученных из массива строк. Здесь, в примере, переменные line, max, save – внешние переменные.






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных