sem02 (1114910)
Текст из файла
1Занятие №21.1 ФункцииНа прошлом занятии нами был рассмотрен пример простой программы на языке Си.Было сказано, что программа является совокупностью функций и глобальных переменных.Кроме того, в программе должна присутствовать функция main, с которой начинается выполнение программы.Рассмотрим более подробно способы определения новых функций.
Замечу, что в языкеСи нет разделения на процедуры и функции, всякий объект, который может исполняться,называется функцией.Простейшее определение функции в общем виде выглядит следующим образом:<result type> name(<params>) <compound-stmt>Для обозначения того, что функция не возвращает значения, используется ключевое слово void. Например,void f(void){/* ... */}В телах void-функций может отсутствовать оператор return, тогда возврат из функциипроизойдёт после того, как будут выполнены все операторы.
Либо оператор return можетприсутствовать, но тогда не должен содержать возвращаемого выражения. Например,1 void doprnt(int x)2 {3if (!x) return;4printf("ERROR: %d\n", x);5 }Не void-функции должны завершаться оператором return содержащим выражение.Если вы на какой-то ветке забыли return, вам может быть выдано предупреждение, а может и нет, тогда в этом случае будет возвращено неопределённое значение.Функция может возвращать значения произвольного типа, кроме массива. Допустимыетипы результата - это целые и вещественные типы, структуры (будем рассматривать), указатели, перечислимые типы — кроме массива. Как мы позже увидим, массивы вообще являются «необычным» типом в Си.Для обозначения того, что функция не имеет никаких аргументов, используется то жесамое ключевое слово void, которое записывается вместо параметров функции.
Например,int f(void){/* ... */}Это функция, которая не имеет параметров и возвращает целое значение.Обратите внимание, что пустой список параметров (т. е. int f()) обозначает функцию, число и тип параметров которой неизвестны. Это не имеет смысла, если1мы рассматриваем только определения функций, но очень заметно, когда функции, так объявленные, вызываются. В этом случае, компилятор не будет проверять соответствие количества и типов фактических параметров количеству и типам формальных параметров. Применяются специальные правила приведения типов.
В одном месте программы такая функцияможет быть вызвана, скажем, с двумя целыми параметрами, а в другом месте — с тремя вещественными. Такое истолкование пустого списка параметров отличается от языка Си++, вкотором это обозначает функцию без параметров.Определения функций в «старом стиле» мы вообще не будем рассматривать.Типы формальных параметров функции задаются следующим образом:(<type1> <par1>, <type2> <par2>, ..., <typen> <parn>)причём для каждого параметра каждый раз указывается его тип.
f(int a,b) — неправильная запись.Все параметры передаются по значению. Передачи параметров по ссылке не существует. Для получения нужного эффекта используются указатели. Единственное исключение — массивы, которые и здесь ведут себя по-другому.Функции не могут быть определены внутри других функций. Поэтому программана Си состоит из «плоских» функций и глобальных переменных.Вызов функции в теле другой функции записывается естественным образом:<имя>(<факт. параметры>)Если у вызываемой функции нет параметров, пара скобок все равно должна бытьуказана. Если функция не void, полученное значение может дальше использоваться в выражении, но может и игнорироваться. а если void, то попытка использовать значениефункции будет считаться ошибкой.Когда в теле некоторой функции компилятор встречает конструкцию name(<pars>), онсчитает это вызовом функции (не всегда!).
Возможны три случая, в зависимости от кого, какбыло ранее определено имя name.1. Если name была объявлена как функция с явным списком параметров, то проверяетсясоответствие количества и типов фактических параметров количеству и типу формальных параметров, при необходимости производится приведение типов. Тип возвращаемого значения определён самой функцией.2. Если name была объявлена как функция с неявным (пустым) списков параметров, никакие проверки типов фактических параметров не производятся, делаются стандартные приведения типов.
Тип возвращаемого значения определён самой функцией.3. Если name вообще не была раньше объявлена, предполагается, что эта функцияимеет определение int name(), то есть возвращает тип int, c неопределённымсписком параметров. Если впоследствии функция будет объявлена с типом int и явным списком параметров, компилятор может выдать предупреждение. Если она будетобъявлена не как int — ошибка.Случай 3, рассмотренный выше, считается очень плохим стилем программирования.
Мыбудем полагать, что функция должна быть всегда описана перед её использованием. Дляслучая рекурсивных функций, или если желательно разместить функции в определённом порядке в файле, функцию перед использованием не обязательно полностью определять, т. е.описывать её тело, а достаточно описать. Для этого нужно задать имя функции, формальныепараметры, возвращаемое значение, а тело функции опустить. Например,2int gcd(int a, int b);Описание функции также называется прототипом. После такого описания функцию можно использовать. Имена формальных параметров могут быть здесь опущены, или могут несовпадать с именами формальных параметров в месте действительного определения функции — это не имеет значения. Например,int gcd(int, int);1.2 Определение глобальных переменныхЕсли переменная описана вне тела функции, эта переменная является глобальной, тоесть доступна из всех точек программы, которые расположены ниже точки определения этойпеременной.
Глобальная переменная может перекрываться локальной переменной с тем жеименем.Переменная в момент определения может быть инициализирована начальным значением.Например,int a = 10;double b = 1.0, c = 1.34e-4;Переменная, описанная вне тела функции может быть инициализирована только константным выражением, то есть выражением, значение которого может быть вычислено наэтапе компиляции. Такие переменные по умолчанию получают значение 0 соответствующеготипа. Блочные переменные могут инициализироваться произвольным выражением, но если переменная не была инициализирована явно, её начальное значение не определено.Блочная переменная существует все время, пока выполняется блок.
Как только управлениепокидает блок, переменная уничтожается и память под неё освобождается.1 int x(int a)2 {3int y = a + 2;4return g(y);5 }Для объектов языка Си действуют правила перекрытия имён, когда имя, объявленное всамом вложенном блоке относительно текущей точки определения, перекрывает имена, находящиеся в объемлющих блоках или глобальные имена. Пример:12345678910111213int x = 10;void f(int y){printf("%d\n", x);}int main(void){int x = 15;printf("%d\n", x);{int x = 20;printf("%d\n", x);f(x);314}15printf("%d\n", x);16return 0;17 }Для переменных разделяют два понятия: время существования (жизни) и областьвидимости. Область видимости — это все точки в исходном коде программы, в которыхданная переменная может быть использована.
Время жизни переменной — это отрезки времени при выполнении программы, когда под данную переменную выделена память. Например, переменная x, определённая в строке 8, существует, когда выполняются строки 8—16(с учётом вызова вложенных функций), но видима только в строках 8, 9, 15, 16 исходнойпрограммы.На одном и том же уровне вложенности не может быть определено двух объектов с одинаковым именем. Вопрос. Допустимы ли следующие определения:int a(int a) { ... }int a() { int a; ... }int a(int a) { int a; ...
}1.3 МассивыРассмотрим первый составной тип — массив. Определение простейшего одномерногомассива записывается следующим образом:<тип> <имя> [ <число элементов> ]В квадратных скобках указывается число элементов в массиве. Такое определение отводитпамять для массива из заданного числа элементов заданного типа, напримерdouble val[40];отводит память под массив из 40 элементов типа double.Если определяется глобальный массив, то число элементов в массиве должно быть константным, то есть вычислимым при компиляции программы. Другими словами, оно не должно использовать значений переменных и результатов вызовов функций. Стандарт C90 и длялокальных массивов допускал только массивы константного размера, но в новом стандартеC99 локальные массивы могут быть переменного размера, определяемого значением выражения в момент выделения памяти под переменную.
Выражение должно принимать положительное целое значение.1 int main(void)2 {3int n;4scanf("%d", &n);5// ОШИБКА: обязательно нужно проверить n на допустимость6double v[n];7n = n + 1;8v[n - 1] = 0; // ОШИБКА: нет столько элементов9 }Обратите внимание, что если уже после создания массива значение выражения, определяющего его размер, изменилось, размер массива не изменится!4Для доступа к массиву используется запись вида <имя массива>[<индекс>], индексможет быть произвольным выражением.
Характеристики
Тип файла PDF
PDF-формат наиболее широко используется для просмотра любого типа файлов на любом устройстве. В него можно сохранить документ, таблицы, презентацию, текст, чертежи, вычисления, графики и всё остальное, что можно показать на экране любого устройства. Именно его лучше всего использовать для печати.
Например, если Вам нужно распечатать чертёж из автокада, Вы сохраните чертёж на флешку, но будет ли автокад в пункте печати? А если будет, то нужная версия с нужными библиотеками? Именно для этого и нужен формат PDF - в нём точно будет показано верно вне зависимости от того, в какой программе создали PDF-файл и есть ли нужная программа для его просмотра.