Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
o. ocenka2 = 4;
Структуры битовых полей могут содержать и знаковые компоненты. Такие компоненты автоматически размещаются на соответствующих границах слов, при этом некоторые биты слов могут оставаться неиспользованными. Ссылки на поле битов выполняются точно так же, как и компоненты общих структур. Само же битовое поле рассматривается как целое число, максимальное значение которого определяется длиной поля.
Переменные с изменяемой структурой
Очень часто некоторые объекты программы относятся к одному и тому же классу, отличаясь лишь некоторыми деталями. Рассмотрим, например, представление геометрических фигур. Общая информация о фигурах может включать такие элементы, как площадь, периметр. Однако соответствующая информация о геометрических размерах может оказаться различной в зависимости от их формы.
Рассмотрим пример, в котором информация о геометрических фигурах представляется на основе комбинированного использования структуры и объединения.
struct figure
{
double area, perimetr; /* общие компоненты */
int type; /* признак компонента */
//enum FIG type; //лучше
union /* перечисление компонент */
{
double d; /* квадрат */
double a[2]; /* прямоугольник */
double radius; /* окружность */
double b[3]; /* треугольник */
};
geom_fig;
В общем случае каждый объект типа figure будет состоять из 4 компонентов: area, perimetr, type, одного из полей объединения union. Компонент type называется меткой активного компонента, так как он используется для указания, какой из компонентов объединения geom_fig является активным в данный момент. Такая структура называется переменной структурой, потому что ее компоненты меняются в зависимости от значения метки активного компонента (значение type).
Отметим, что вместо компоненты type типа int, целесообразно было бы использовать перечисляемый тип. Например, такой
enum FIG = KV, PR, KR, TR;
Константы KV, PR, KR, TR получат значения соответственно равные 0, 1, 2 и 3. Переменная type может быть объявлена как имеющая перечисляемый тип:
enum FIG type;
Теперь type может принимать только значения KV, PR, KR, TR.
void main()
figure f1, f2;
f1.d=20;
f1.type=KV;
count_pl(f1);
f2.a[1]=10;
f2.a[2]=20;
f2.type = PR;
count_pl(f2);
void count_pl(figure & f1);
if (f1.type==KV) f1.area=f1.d*f1.d;
if (f1.type==PR) f1.area=f1.a[1]*f1.a[2];
if (f1.type==KR) f1.area=M_PI*f1.R*f1.R/2;
if (f1.type==TR) ......
Лекция 11. Функции
Алгоритм решения задачи проектируется путем декомпозиции всей задачи в отдельные подзадачи. Обычно подзадачи реализуются в виде подпрограмм.
Функция — это именованная последовательность описаний и операторов, выполняющая какое-либо законченное действие. Функцию можно вызвать для выполнения из одной или нескольких точек программы. Функция может принимать параметры и возвращать значение.
Благодаря функциям программа делится на функционально независимые части.
Стремятся к тому, чтобы программа состояла из большого количества подпрограмм. Каждая подпрограмма должна быть не более 20-30 строк кода.
Каждая функция должна иметь имя, которое используется для ее объявления, определения и вызова.
Любая функция должна быть объявлена и определена. Как и для других величин, объявлений может быть несколько, а определение только одно.
Объявление должно находиться ранее ее вызова для того, чтобы компилятор мог осуществить проверку правильности вызова.
Объявление обычно помещается в файл с расширением *.h и подключается к программе с помощью команды препроцессора
#include "имя_файла"
Объявление функции (прототип) задает ее имя, тип возвращаемого значения и список передаваемых параметров.
Определение функции содержит, кроме объявления, тело функции, представляющее собой последовательность операторов и описаний в фигурных скобках.
[<класс>] <тип_возвр_знач> <имя> ([<список_параметров>])[throw (<исключения>)]
{
<тело функции>
}
Определение состоит из:
— класс =
extern - глобальная видимость во всех модулях (по умолчанию)
static - видимость только в пределах модуля, где определена функция.
— тип_возвр_знач — может быть любым за исключением массива и функции. Если функция не должна возвращать значение, то указывается void.
— список_параметров — определяет величины, которые необходимо передать в функцию при ее вызове. Элемениы списка параметров разделяются запятыми.
Тип возвращаемого значения и типы параметров совместно определяют тип функции.
При вызове функции ей при помощи аргументов (формальных параметров) могут быть переданы некоторые значения (фактические параметры), используемые во время выполнения функции. Функция может возвращать некоторое (одно!) значение. Это возвращаемое значение и есть результат выполнения функции, который при выполнении программы подставляется в точку вызова функции, где бы этот вызов ни встретился.
Допускается также использовать функции, не имеющие аргументов, и функции,
не возвращающие никакие значения. Действие таких функций может состоять, например, в изменении значений некоторых переменных, выводе на печать некоторых текстов и т. п.
Функция начинает выполняться в момент вызова.
Для вызова функции в простейшем случае нужно указать ее имя, за которым в круглых скобках через запятую перечисляются имена передаваемых аргументов.
Вызов функции может находиться в любом месте программы, где по синтаксису
допустимо выражение того типа, который формирует функция.
Если функция возвращает void, то функция не может входить в состав выражения. Она вызывается аналогично процедуре.
double Inp(void)
{
double a;
cin >>a;
return a;
}
void Pri(double a)
{
cout << a;
}
double Kv(double a)
{
return a*a;
}
void main(void)
{
double s;
s = Inp();
s = Kv(s)+Kv(3);
Pri(s);
Pri( 3 );
Pri( Kv(6) );
s=Pri(s); //нельзя т. к. Pri возвращает void
}
Все величины, описанные внутри функции, а также ее параметры являются локальными. При вызове функции, как и при входе в любой блок, в стеке выделяется память под локальные автоматические переменные. Кроме того в стеке сохраняется содержимое регистров процессора на момент, предшествующий вызову функции, и адрес возврата из функции для того, чтобы при выходе из нее можно было продолжить выполнение вызывающей функции.
При выходе из функции соответствующий участок стека освобождается, поэтому значения локальных переменных между вызовами одной и той же функции не сохраняются. Если этого необходимо избежать, при объявлении локальных переменных используется модификатор static.
void f(void)
{
int i=0; //выполняется 2 раза
static n = 0; //выполняется 1 раз
++i;
++n;
cout << "i=" << i;
cout << "n=" << n;
}
void main(void)
{
f();
f();
}
i=1 n=1
i=1 n=2
Статическая переменная n размещается в сегменте данных (не в стеке как все локальные переменные) и инициализируется один раз при первом выполнении оператора, содержащего ее определение. Автоматическая переменная i инициализируется при каждом входе в функцию.
Способы обмена информацией между функциями
При совместной работе функции должны обмениваться информацией.
Это можно осуществить:
1) с помощью глобальных переменных (не рекомендуется),
2) через возвращаемое функцией значение,
3) через параметры.
Глобальные переменные видны во всех функциях, где не описаны локальные переменные с теми же именами, поэтому использовать их для передачи данных между функциями очень легко. Тем не менее, это не рекомендуется, поскольку затрудняет отладку программы и препятствует помещению функций в библиотеки общего пользования.
Возвращаемое значение возвращается из функции оператором return [выражение];. При этом происходит возврат из функции. Функция может содержать несколько операторов return (это определяется потребностью алгоритма). Если функция возвращает void, то параметр не указывается.
Нельзя возвращать из функции указатель на локальную переменную, поскольку память, выделенная локальным переменным при входе в функцию. Освобождается после возврата из нее.
int *f()
{
int a=5;
return &a; //нельзя
}
Можно возвращать из функции значение локальной переменной, поскольку в этом случае осуществляется передача копии и при уничтожении локальной переменной копия сохранится.
int f()
{
int a=5;
return a; //можно
}
Параметры функции — основной способ обмена информацией между вызываемой
и вызывающей функциями. Параметры, перечисленные в заголовке описания функции, называются формальными, а записанные в операторе вызова функции — фактическими.
При вызове функции в первую очередь вычисляются выражения, стоящие на месте фактических параметров; затем в стеке выделяется память под формальные параметры функции в соответствии с их типом, и каждому из них присваивается значение соответствующего фактического параметра. При этом проверяется соответствие типов и при необходимости выполняется их преобразования. При несоответствии типов выдается сообщение.
Существует 3 способа передачи параметров в функцию: по значению, по адресу и по ссылке.
1) При передаче по значению в стек заносятся копии значений фактических параметров, и операторы функций работают с этими копиями. Доступа к исходным значениям параметров у функции нет, а, следовательно, изменение копии не влияет на значение оригинала в операторе вызова. Это предотвращает случайный побочный эффект изменения значений. Один из недостатков вызова по значению состоит в том, что если передается большой элемент данных, то создание копии этих данных может привести к значительным потерям времени выполнения.
При передаче по адресу в стек заносятся копии адресов параметров, а функция осуществляет доступ к ячейкам памяти по этим адресам и может изменять исходные значения параметров.
При передаче по ссылке в функцию передается адрес указанного при вызове параметра, а внутри функции все обращения к параметру неявно разадресовываются. Поэтому использование ссылок вместо указателей улучшает читаемость программы, избавляя от операции получения адреса и разыменования.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |


