теория-билеты экзамен по информатике. Система счисления это совокупность приемов и правил, по которым числа записываются и читаются
Скачать 144.81 Kb.
|
calloc - резервирует память для размещения n элементов массива, каждый из которых имеет длину size байт, инициализируя все элементы нулями; выделенная память освобождается по завершении работы программы или при помощи функции free() Формат и описание аргументов: void *calloc(n, size) int n; /* Общее количество элементов в массиве */ int size; /* Длина в байтах каждого элемента */ Возвращаемое значение является указателем неопределенного типа на первый байт зарезервированной области статической памяти и равно NULL при отсутствии возможности разместить требуемое количество элементов заданной длины. Для получения указателя на конкретный тип данных, необходимо применить к возвращаемому значению операцию явного преобразования типа malloc - резервирует блок памяти размером size байт; затребованная память освобождается по завершении работы программы или при помощи функции free() Формат и описание аргументов: void *malloc(size) int size; /* Требуемое количество байт памяти */ Пусть необходимо разместить простую переменную или массив на фиксированных адресах оперативной памяти. Для этого указатель на соответствующий элемент или структуру данных должен быть инициализирован числовым значением, определяющим абсолютный физический адрес Поскольку такая потребность чаще всего возникает при работе с видеопамятью компьютера IBM PC, рассмотрим способ обращения к ячейкам видеопамяти в алфавитно-цифровом режиме Учитывая, что интересующая нас область памяти имеет сегментный адрес 0xB800 и каждой позиции экрана отвечают два байта этой памяти, достаточно определить массив элементов типа int, расположив его по требуемому адресу В том случае, когда видеосистема установлена в режим 25 строк по 80 символов, соответствующее описание должно иметь следующий вид: (*vmem_16)[25][80] = 0xB8000000; После этого занесению какой-либо информации во всякий элемент массива (*vmem_16) будет соответствовать определенный эффект на экране видеотерминала 11 Всякая программа на языке Си представляет собой совокупность одной или более функций, каждая из которых есть независимый набор описаний и операторов, заключенных между заголовком функции и ее концом. void function1() { } int function2() { return 0 } Программа на языке Си состоит из одной или более подпрограмм, называемых функциями. Язык Си является блочно-структурированным. Каждый блок заключается в фигурные скобки {}. Основным блоком в программе консольного приложения на языке Си является главная функция, имеющая имя main(). Каждое действие в языке Си заканчивается символом "точка с запятой" “;”. В качестве действия может выступать вызов функции или осуществление некоторых операций. Имя функции — это коллективное имя группы описаний и операторов, заключенных в блок (фигурные скобки). За именем функции в круглых скобках указываются параметры функции. Комментарии в языке Си В языке Си для многострочных комментариев используются символы: /* - начало комментария; */ - конец комментария. Для однострочных: // - начало комментария; Главная функция При выполнении консольного приложения, написанного на языке Си, операционная система компьютера передаёт управление функции с именем main(). Функцию main() нельзя вызывать из других функций программы, она является управляющей. Следующие за именем функции круглые скобки предназначены для указания параметров (аргументов), которые передаются в функцию при обращении к ней. В данном случае операционная система не передаёт в функцию main()никаких аргументов, поэтому список аргументов в круглых скобках пустой. Существует два основных вида области видимости: локальная область видимости и глобальная область видимости. Переменная, объявленная вне всех функций, помещается в глобальную область видимости. Доступ к таким переменным может осуществляться из любого места программы. Такие переменные располагаются в глобальном пуле памяти, поэтому время их жизни совпадает со временем жизни программы. Переменная, объявленная внутри блока (часть кода, заключенная в фигурные скобки), принадлежит локальной области видимости. Такая переменная не видна (поэтому и недоступна) за пределами блока, в котором она объявлена. Самый распространенный случай локального объявления – переменная, объявленная внутри функции. Переменная, объявленная локально, располагается на стеке, и время жизни такой переменной совпадает со временем жизни функции. Так как областью видимости локальной переменной является блок, в котором она объявлена, то существует возможность объявлять переменные с именем, совпадающим с именами переменных, объявленных в других блоках; а также объявленных на более верхних уровнях, вплоть до глобального Переменная в этих языках должна принадлежать ровно к одному классу памяти, что указывается с помощью ключевого слова, который пишется перед типом переменной. auto — автоматическая (локальная). Автоматические переменные создаются при входе в функцию и уничтожаются при выходе из неё. Они видны только внутри функции или блока, в которых определены. static — статическая переменная (локальная). 1) Если static - внутри функции. Статические переменные имеют такую же область действия, как локальные(автоматические), но они не исчезают, когда содержащая их функция закончит свою работу. Их значения сохраняются от одного вызова функции до другого. 2) static вне функции имеет другое значение. extern — внешняя (глобальная) переменная. Внешние переменные доступны везде, где описаны, а не только там, где определены. Включение ключевого слова extern позволяет функции использовать внешнюю переменную, даже если она определяется позже в этом или другом файле. register — регистровая переменная (локальная). Это слово является всего лишь «рекомендацией» компилятору помещать часто используемую переменную в регистры процессора для ускорения программы. Класс памяти можно не указывать, тогда действуют следующие умолчания: переменные, описанные внутри функции или блока, считаются локальными (auto) переменные, описанные вне всех функций, считаются внешними. функции считаются внешними. Статическая переменная, описанная вне любой функции, становится внешней статической. Разница между внешней переменной и внешней статической переменной заключается в области их действия. Обычная внешняя переменная может использоваться функциями в любом файле, а внешняя статическая переменная может использоваться только функциями того же самого файла, причем после определения переменной. Билет 12,30. Структура. Под структурой в языке Си понимается набор одной или большего числа переменных, возможно имеющих различный тип и объединенных под единым именем, называемым именем структуры Описание всякой структуры в программе начинается с ключевого слова struct и в простейшем случае имеет следующий формат: struct {member-declaration list} identifier <,identifier ... >; struct есть ключевое слово языка Си, а в угловые скобки (<>) заключена необязательная часть конструкции member-declaration list - одно или более описаний переменных, каждая из которых называется элементом структуры, а identifier - имя переменной, определяемой как имеющей тип структура Так, например, инструкция struct { char name[30]; int group; } student; определяет структуру с именем student , элементами которой являются массив символов name и целочисленная переменная group Обозначение: student.group - задает элемент group в составе структуры student, в то время как ссылка student.name[9] - выделяет десятый элемент массива name той же структуры Следующие два адресных выражения &student и &student.name[0] - полностью эквивалентны и их значения равны адресу размещения структуры student в памяти компьютера Более общий способ описания структур в программе имеет следующий формат: struct -где tag является именем, присваиваемым шаблону структуры, а все остальные обозначения сохраняют свой прежний смысл Объединения. Объединение - это средство, позволяющее размещать данные различных типов в одном и том же месте оперативной памяти Описания объединений имеют тот же самый формат, что и описания структур только вместо ключевого слова struct используется union Память, выделяемая под объединения, определяется длиной наибольшего элемента в составе данного объединения. При этом все члены объединения хранятся в одной и той же области памяти с неизменным начальным адресом Например: union { char c; int a; float f } number; Здесь элементы внутренних структур c,a и f размещены в одной и той же области памяти Перечисления. Тип данных перечисление позволяет определить набор символических имен, связав с каждым из них числовое значение целого типа Описания объединений имеют тот же самый формат, что и описания структур только вместо ключевого слова struct используется enum Каждый идентификатор в этом списке именует один элемент из множества перечисляемых значений. По умолчанию первый из них получает значение нуль, второй - значение единица и т. д. Опция = constant-expression позволяет нарушить стандартное правило назначения числовых значений именам из этого списка, причем константное выражение должно иметь тип int. Допустимым также является совпадение числовых значений различных имен в списке В следующем примере определяется перечисление с именем day и объявляется переменная workday, имеющая тип перечисление: enum day { saturday, sunday = 0, monday, tuesday, wednesday, thursday, friday } workday; Значение нуль связывается с идентификатором saturday по умолчанию, а идентификатору sunday оно же присваивается явным образом. Остальные пять имен в этом списке последовательно получают значения от 1 до 5 (Полная информация в презентациях Гужова В.И. – “Структуры”) Билет 14, 29 Рекурсивные вызовы функций. Аргументы командной строки. Рекурсивные вызовы функций Всякая функция в языке Си имеет реентерабельный (повторно входимый) код, что позволяет ей обращаться к самой себе непосредственно или через другие функции Такие обращения называются рекурсивными вызовами или рекурсией При каждом очередном рекурсивном вызове создается новая копия параметров функции, а также определенных в ее теле автоматических и регистровых переменных. Внешние и статические переменные, имеющие глобальное время существования, сохраняют при этом свои прежние значения и размещение памяти Несмотря на то, что ни стандарт языка Си, ни компилятор формально не налагают никакого ограничения на количество рекурсивных обращений, тем не менее оно практически всегда существует для любых типов компьютеров, ибо каждый новый вызов требует дополнительной памяти из ресурса программного стека Если количество вызовов излишне велико, возникает переполнение сегмента стека и операционная система уже не может создать очередного экземпляра локальных объектов функции, что ведет, как правило, к аварийному завершению программы В качестве примера реализации рекурсивного алгоритма рассмотрим функцию printd() , печатающую целое число в виде последовательности символов ASCII (т.е. цифр, образующих запись этого числа): void printd(int num) { int i; if (num < 0) { putchar('-'); num = -num; } if ((i = num/10) != 0) printd(i); putchar(num % 10 + '0') ; } Если значение переменной value равно 123, то в случае вызова void printd(value); эта функция дважды обратится сама к себе для печати цифр заданного числа Классическим примером написания рекурсивной функции является вычисление факториала целого числа. Разумеется, эту задачу легко решить при помощи обычного цикла, но на этом простом примере наглядно видна идея рекурсивного алгоритма Текст такой функции достаточно прост: /* Рекурсивное вычисление n! */ int fact(int n) { if (n==0) return (1); else return(n*fact(n-1)); } Если обратиться к этой функции, например, так: int m; ... m = fact(5); то, прежде чем получить значение 5!, функция должна вызвать самое себя как fact(4) , та, в свою очередь, вызывает fact(3) . Так будет продолжаться до вызова fact(0) . Лишь после этого вызова будет получено конкретное число (единица). Затем все пойдет в обратном порядке, и в конце концов мы получим результат от обращения fact(5) : 120 Порядок вызовов ¦ Порядок возвратов | Возвращаемое ¦ | значение fact(5) ¦ return(1) | 1 fact(4) ¦ return(1*0!) | 1 fact(3) ¦ return(2*1!) | 2 fact(2) ¦ return(3*2!) | 6 fact(1) ¦ return(4*3!) | 24 fact(0) ¦ return(5*4!) | 120 Последнее возвращаемое значение будет присвоено переменной m. Обратите внимание на то, что при каждом новом вызове предыдущий еще не закончил работу, поэтому параметры, переданные функции при прежнем обращении, еще хранятся в стеке При очередном вызове стек наращивается, т.к. в него загружаются копии других параметров. Очистка стека будет происходить постепенно, и он полностью будет очищен лишь после возврата окончательного результата Аргументы командной строки Те, кому хоть раз приходилось работать с командной строкой операционной среды, видимо обратили внимание на то, что большинство команд пользовательского интерфейса могут иметь один или более параметров, называемых аргументами командной строки Так, например, обращение к команде copy, выполняющей копирование файлов, обычно выглядит следующим образом: copy oldfile.txt newfile.txt где параметры oldfile.txt и newfile.txt определяют имена файла-источника и файла-приемника соответственно. Эти параметры обрабатываются командным процессором и передаются в тело программы copy, в результате чего последняя узнает о файлах, над которыми должна быть выполнена операция копирования Поскольку язык Си часто применяется при разработке системного программного обеспечения, он имеет встроенные средства для получения аргументов команды непосредственно от командного процессора Любая функция, входящая в состав Си-программы, может иметь параметры, через которые она получает необходимую информацию от вызывающей ее функции Совершенно аналогично, главная функция main(), с которой начинается выполнение всякой программы, могла бы в момент вызова получать исходные данные через аргументы командной строки. Для этого достаточно снабдить функцию main() набором параметров, которые обычно имеют имена argc и argv : main(argc, argv) { } Параметр argc (ARGument Count) является переменной типа int , получающей от командного процессора информацию о количестве аргументов, набранных в командной строке, включая и имя самой команды Второй параметр argv (ARGument Vector) обычно определяется как массив указателей типа char , каждый из которых хранит адрес начала отдельного слова командной строки. Их описание в программе может выглядеть следующим образом: int argc; char *argv[]; В соответствии с принятым соглашением, нулевой элемент argv[0] массива указателей ссылается на строку символов, содержащую имя самой команды и поэтому параметр argc всегда имеет значение большее или равное единице. Следующий элемент argv[1] задает адрес размещения в памяти первого аргумента команды, также представленного последовательностью символов, и т.д. Обращаясь к очередному элементу массива argv нетрудно получить доступ ко всем аргументам командной строки В качестве примера, иллюстрирующего работу с параметрами функции main() , рассмотрим программу, выводящую на экран терминала свои собственные аргументы и реализующую команду echo: #include main(argc, argv) int argc; char *argv[]; |