теория-билеты экзамен по информатике. Система счисления это совокупность приемов и правил, по которым числа записываются и читаются
Скачать 144.81 Kb.
|
Операторы передачи управления (break , continue , goto , return ) Оператор break |
Оператор return Оператор return завершает выполнение функции, в которой он задан, и возвращает управление в вызывающую функцию, в точку, непосредственно следующую за вызовом. Функция main передает управление операционной системе. Формат оператора: return [выражение]; Значение выражения, если оно задано, возвращается в вызывающую функцию в качестве значения вызываемой функции. Если выражение опущено, то возвращаемое значение не определено. Выражение может быть заключено в круглые скобки, хотя их наличие не обязательно. Если в какой-либо функции отсутствует оператор return, то передача управления в вызывающую функцию происходит после выполнения последнего оператора вызываемой функции. При этом возвращаемое значение не определено. Если функция не должна иметь возвращаемого значения, то ее нужно объявлять с типом void. Таким образом, использование оператора return необходимо либо для немедленного выхода из функции, либо для передачи возвращаемого значения. Пример: int sum (int a, int b) { renurn (a+b); } Функция sum имеет два формальных параметра a и b типа int, и возвращает значение типа int, о чем говорит описатель, стоящий перед именем функции. Возвращаемое оператором return значение равно сумме фактических параметров. Оператор goto Использование оператора безусловного перехода goto в практике программирования на языке СИ настоятельно не рекомендуется, так как он затрудняет понимание программ и возможность их модификаций. Формат оператора: goto имя-метки; ... имя-метки: оператор; Оператор goto передает управление на оператор, помеченный меткой имя-метки. Помеченный оператор должен находиться в той же функции, что и оператор goto, а используемая метка должна быть уникальной, т.е. одно имя-метки не может быть использовано для разных операторов программы. Имя-метки - это идентификатор. Любой оператор в составном операторе может иметь свою метку. Используя оператор goto, можно передавать управление внутрь составного оператора. Но нужно быть осторожным при входе в составной оператор, содержащий объявления переменных с инициализацией, так как объявления располагаются перед выполняемыми операторами и значения объявленных переменных при таком переходе будут не определены. | |
Билет 8, 20, 34
Функции в С. Формальные и фактические параметры. Механизм передачи параметров. Возвращаемые значения. Использование указателей в качестве аргументов функции. Предварительное описание функций.
Ответ
Всякая программа на языке Си представляет собой совокупность функций, выполняющих основную работу по реализации некоторого алгоритма
Функции это независимый набор описаний и операторов, заключенных между заголовком функции и ее концом.
Функция, с которой начинается выполнение программы, называется главной функцией и должна иметь предопределенное имя
void main()
{ }
Все остальные функции, входящие в программу, запускаются в работу путем их прямого или опосредованного (через другие функции) вызова из главной функции.
В языке Си определение функции имеет следующий формат:
)
function-body
Например,
void work(n, beta) void work(int n, float beta)
int n; float beta;
{ ................. { .................
................. .................
................. .................
} }
sc-specifier - описатель класса памяти (static или extern)
type-specifier - тип возвращаемого функцией значения
declarator – имя (идентификатор) функции, перед которым может стоять символ звездочка (*), если эта функция возвращает указатель на элемент данных соответствующего типа.
Для организации связи между независимыми функциями в языке Си используется либо аппарат формальных/фактических параметров, либо набор глобальных или внешних переменных
Формальными параметрами мы будем называть аргументы функции, стоящие в ее заголовке и имена которых используются для построения тела функции при ее определении
Фактическими же параметрами являются произвольные выражения, значения которых передаются формальным параметрам при обращении к функции. Таким образом реализуется возможность передачи необходимой информации от вызывающей функции к вызываемой непосредственно в момент ее вызова
Выполнение инструкций в теле функции начинается с самого первого оператора и продолжается до тех пор, пока не встретится оператор возврата return, либо пока не будет достигнут конец внешнего блока ( } )
Возвращаемое функцией значение равно значению выражения в операторе return, а при его отсутствии считается неопределенным. В случае необходимости тип результата преобразуется к типу функции стандартным образом
Инструкция вызова функции в общем случае имеет следующий формат:
expression (
Например:
void work(int n, float beta) void main()
{ ................. {
................. ...
................. int n; float b;
work(n,b);
} }
Вызов функции может представлять собой выражение, которое может играть роль операнда в составе более сложного выражения
Таким образом, в языке Си реализован механизм передачи параметров по значению.
При вызове функции ей при помощи аргументов (формальных параметров) могут быть переданы некоторые значения (фактические параметры), используемые во время выполнения функции. Функция может возвращать некоторое (одно !) значение. Это возвращаемое значение и есть результат выполнения функции, который при выполнении программы подставляется в точку вызова функции, где бы этот вызов ни встретился. Допускается также использовать функции не имеющие аргументов и функции не возвращающие никаких значений. Действие таких функций может состоять, например, в изменении значений некоторых переменных, выводе на печать некоторых текстов и т.п.
Всякая функция работает лишь с копиями значений своих аргументов, поэтому никакие изменения значений формальных параметров в теле функции не могут отразиться на значениях фактических параметров
Это в свою очередь означает, что аргументы функции являются носителями лишь входной информации и не могут быть использованы для передачи результатов ее работы вызвавшей функции
Для преодоления этого ограничения необходимо использовать указатели в качестве аргументов функций, передавая тем самым числовые значения соответствующих адресов. Таким же образом решается проблема передачи массивов, функций и некоторых других структурированных данных
Любая функция может быть вызвана раньше, чем она определена в текущем файле, быть внешней или библиотечной функцией
В такой ситуации компилятор не имеет возможности следить за правильностью вызова
В подобных случаях компилятор пытается интерпретировать вызов некоторым стандартным образом, присваивая возвращаемому функцией значению тип int и не выполняя проверки правильности списка аргументов
В то же время, возможное несоответствие типов и количества формальных и фактических параметров или отличие типа реально возвращаемого функцией значения от int могут привести к трудно обнаруживаемым ошибкам в программе
Простой выход из этого положения заключается в составлении предварительного описания, или прототипа, вызываемой функции, в котором будут определены основные ее атрибуты
В самом общем случае такое предварительное описание имеет следующий формат:
<, declarator(
Здесь sc-specifier задает класс памяти (static или extern), который имеет вызываемая функция, type-specifier устанавливает тип возвращаемого ей значения, а arg-list определяет количество и тип аргументов, declarator в приведенной схеме является идентификатором функции, возможно модифицированным при помощи круглых скобок и символа звездочка для указателей на функции и функций, возвращающих указатели
double sin(float a);
double cos(float);
Введенное таким образом понятие предварительного описания функции дает возможность компилятору построить некоторый шаблон этой функции до ее фактического определения в текущем или внешнем файле
Этот шаблон может быть использован для контроля правильности типа возвращаемого функцией значения и соответствия формальных и фактических параметров
Ниже приведены несколько характерных примеров построения предварительных описаний
1. В этом примере описана функция с именем add , возвращающая значение типа double и оба аргумента которой являются указателями на тип float:
double add(float*, float*);
2. Если функция с именем sum имеет два аргумента типа double и возвращает указатель на массив трех элементов типа double, то ее предварительное описание должно иметь следующий вид:
double (*sum(double, double))[3];
3. В том случае, когда функция не имеет аргументов и возврашает указатель неопределенного типа, в ее предварительном описании необходимо использовать ключевое слово void на месте имени типа возвращаемого значения и списка аргументов:
void *draw(void);
Билет 9, 19, 33
Адреса и указатели. Операции получения адреса и косвенная адресация. Отождествление массивов и указателей. Адресная арифметика.
Указатель — переменная, содержащая адрес объекта. Указатель не несет информации о содержимом объекта, а содержит сведения о том, где размещен объект. Указатели широко используются в программировании на языке Си.
Указатели часто используются при работе с массивами.
Память компьютера можно представить в виде последовательности пронумерованных однобайтовых ячеек, с которыми можно работать по отдельности или блоками.
Каждая переменная в памяти имеет свой адрес - номер ячейки, где она расположена, а также свое значение. Указатель — это тоже переменная, которая размещается в памяти. Она тоже имеет адрес, а ее значение является адресом некоторой другой переменной. Переменная, объявленная как указатель, занимает 4 байта в оперативной памяти (в случае 32-битной версии компилятора).
Указатель, как и любая переменная, должен быть объявлен.
Общая форма объявления указателя
тип *имя_объекта;
Тип указателя— это тип переменной, адрес которой он содержит.
Для работы с указателями в Си определены две операции:
операция * (звездочка) — позволяет получить значение объекта по его адресу - определяет значение переменной, которое содержится по адресу, содержащемуся в указателе; (косвенная адресация)
операция & (амперсанд) — позволяет определить адрес переменной.
char c; // переменная
char *p; // указатель
p = &c; // p = адрес c
В языке СИ между указателями и массивами существует тесная связь. Например, когда объявляется массив в виде int array[25], то этим определяется не только выделение памяти для двадцати пяти элементов массива, но и для указателя с именем array, значение которого равно адресу первого по счету (нулевого) элемента массива, т.е. сам массив остается безымянным, а доступ к элементам массива осуществляется через указатель с именем array. С точки зрения синтаксиса языка указатель arrey является константой, значение которой можно использовать в выражениях, но изменить это значение нельзя.
Поскольку имя массива является указателем допустимо, например, такое присваивание:
int arrey[25];
int *ptr;
ptr=array;
Здесь указатель ptr устанавливается на адрес первого элемента масcива, причем присваивание ptr=arrey можно записать в эквивалентной форме ptr=&arrey[0].
Для доступа к элементам массива существует два различных способа. Первый способ связан с использованием обычных индексных выражений в квадратных скобках, например, array[16]=3 или array[i+2]=7. При таком способе доступа записываются два выражения, причем второе выражение заключается в квадратные скобки. Одно из этих выражений должно быть указателем, а второе - выражением целого типа. Последовательность записи этих выражений может быть любой, но в квадратных скобках записывается выражение следующее вторым. Поэтому записи array[16] и 16[array] будут эквивалентными и обозначают элемент массива с номером шестнадцать. Указатель используемый в индексном выражении не обязательно должен быть константой, указывающей на какой-либо массив, это может быть и переменная. В частности после выполнения присваивания ptr=array доступ к шестнадцатому элементу массива можно получить с помощью указателя ptr в форме ptr[16] или 16[ptr].
Второй способ доступа к элементам массива связан с использованием адресных выражений и операции разадресации в форме *(array+16)=3 или *(array+i+2)=7. При таком способе доступа адресное выражение равное адресу шестнадцатого элемента массива тоже может быть записано разными способами *(array+16) или *(16+array).
При реализации на компьютере первый способ приводится ко второму, т.е. индексное выражение преобразуется к адресному. Для приведенных примеров array[16] и 16[array] преобразуются в *(array+16).
Для доступа к начальному элементу массива (т.е. к элементу с нулевым индексом) можно использовать просто значение указателя array или ptr. Любое из присваиваний
*array = 2;
array[0] = 2;
*(array+0) = 2;
*ptr = 2;
ptr[0] = 2;
*(ptr+0) = 2;
присваивает начальному элементу массива значение 2, но быстрее всего выполнятся присваивания *array=2 и *ptr=2, так как в них не требуется выполнять операции сложения.
Билет 10, 18, 32.
Указатели на массивы. Массивы указателей и многомерные массивы. Динамическое выделение памяти под массивы. Инициализация указателей
float (*vector)[15];
определяет имя vector как указатель на массив пятнадцати элементов типа float, причем круглые скобки в этой записи являются существенными. Обращение к i-ому элементу такого массива будет выглядеть следующим образом:
(*vector)[i]
Массивы указателей - структура данных в Си, в котором построен ограниченный вектор элементов-указателей на некоторый базовый тип данных.
Пример:
char *text[300];
определяет массив трехсот указателей на элементы данных типа char
Элементы массива указателей могут быть инициализированы подобно тому, как инициализировались отдельные указатели и обычные массивы:
char *week[] = { "Понедельник",
"Вторник",
"Среда",
"Четверг",
"Пятница",
"Суббота",
"Воскресенье"
};
char table[10][20];
определяет массив десяти массивов, каждый из которых содержит по двадцать элементов типа char
Отличие массива указателей от массива массивов состоит, главным образом, в том, что в первом случае резервируются лишь ячейки памяти для хранения адресов строк двумерной таблицы, в то время как реальная память под размещение элементов каждой строки не выделяется. Во втором же случае полностью определен объем памяти, занимаемой всей таблицей
alloca - резервирует size байт памяти из ресурса программного стека; выделенная память освобождается по завершении работы текущей программной компоненты.
Формат и описание аргументов:
void *alloca(size)
int size; /* Требуемое количество байт памяти */
Возвращаемое значение является указателем типа char на первый байт зарезервированной области программного стека и равно NULL при отсутствии возможности выделить память требуемого размера. Для получения указателя на тип данных, отличный от char, необходимо применить к возвращаемому значению операцию явного преобразования типа