Целый тип данных (он же скалярный)
Скалярные типы данных
Важное отличие языка СИ от других языков (PL1, FORTRAN, и др.) является отсутствие принципа умолчания, что приводит к необходимости объявления всех переменных используемых в программе явно вместе с указанием соответствующих им типов.
Целый тип данных (он же скалярный)
Для определения данных целого типа используются различные ключевые слова, которые определяют диапазон значений и размер области памяти, выделяемой под переменные
Char1байт от –128 до 127;
Int2/4 байт
Short 2байта от –32768 до 32767
Long4байта от -2147483648 до 21474836647
Unsigned char 1байт от 0 до 255
Unsigned int 2/4 байта
Unsigned short 2байта от 0 до 65535
Unsigned long4байта от 0 до 21294967295
signed и unsigned указывают, как интерпретируется нулевой бит объявляемой переменной, т.е., если указано ключевое слово unsigned, то нулевой бит интерпретируется как часть числа, в противном случае нулевой бит интерпретируется как знаковый. В том случае, если спецификатор типа состоит из ключевого типа signed или unsigned и далее следует идентификатор переменной, то она будет рассматриваться как переменная типа int. Например: unsigned int n; unsigned int b; int c; (подразумевается signed int c );
unsigned d; (подразумевается unsigned int d ); signed f; (подразумевается signed int f ). Отметим, что модификатор типа char используется для представления символа (из массива представление символов) или для объявления строковых литералов. Следует сделать следующее замечание: в языке СИ не определено представление в памяти и диапазон значений для идентификаторов с модификаторами типа int и unsigned int. Размер памяти для переменной с модификатором типа signed int определяется длиной машинного слова, которое имеет различный размер на разных машинах. Так, на 16-ти разрядных машинах размер слова равен 2-м байтам, на 32-х разрядных машинах соответственно 4-м байтам
Векторные типы данных
Указатель –переменная, хранящая адрес другой переменной. В том случае, если переменная объявлена как указатель, то она содержит адрес памяти, по которому может находится скалярная величина любого типа. При объявлении переменной типа указатель, необходимо определить тип объекта данных, адрес которых будет содержать переменная, и имя указателя с предшествующей звездочкой (или группой звездочек). Размер переменной объявленной как указатель, зависит от архитектуры компьютера и от используемой модели памяти, для которой будет компилироваться программа. Указатели на различные типы данных не обязательно должны иметь одинаковую длину.
Для модификации размера указателя можно использовать ключевые.
unsigned int * a; /* переменная а представляет собой указатель на тип unsigned int (целые числа без знака) */double * x;/ переменная х указывает на тип данных с плавающей точкой удвоенной точности */char * fuffer ;/объявляется указатель с именем fuffer который указывает на переменную типа char */double nomer;void *addres;addres = & nomer;(double *)addres ++;/* Переменная addres объявлена как указатель на объект любого типа. Поэтому ей можно присвоить адрес любого объекта (& - операция вычисления адреса).
Массивы.Массивы - это группа элементов одинакового типа (double, float, int и т.п.). Из объявления массива компилятор должен получить информацию о типе элементов массива и их количестве. В языке СИ определены только одномерные массивы, но поскольку элементом массива может быть массив, можно определить и многомерные массивы. Они формализуются списком константных выражений, следующих за идентификатором массива, причем каждое константное выражение заключается в свои квадратные скобки. Каждое константное выражение в квадратных скобках определяет число элементов по данному измерению массива. В языке СИ первый элемент массива имеет индекс равный 0.
Примеры:
int a[2][3]; /представлено в виде матрицыa[0][0] a[0][1] a[0][2]a[1][0] a[1][1] a[1][2]/double b[10]; /* вектор из 10 элементов имеющих тип double */Пример объявления символьного массива.
char str[] = "объявление символьного массива";
Следует учитывать, что в символьном литерале находится на один элемент больше, так как последний из элементов является управляющей последовательностью '\0'.
Структура языка Си это векторный тип данных для хранения элементов, преимущественно разного типа.
Использование структур приводит к необоснованным затратам памяти, следовательно использовать реже.
Объединение – это структура данных, когда определяется самое длинное поле и все остальные поля разделяют с ней один и тот же адрес, т.е. это средство, позволяющее запоминать данные различных типов в одном и том же месте памяти. Объединение позволяет создавать массив, состоящий из эл-тов одинакового размера, каждый из которых может содержать различные типы данных.
Объединения устанавливаются таким же способом, как и структуры. Есть шаблон и переменные объединения. Они могут определяться одновременно или, если используется имя объединения, последовательно за два шага:
Перечисляемый тип – множество поименованных целых констант.
3. Неявное и явное преобразование типов.
При выполнении операций происходят неявные преобразования типов в следующих случаях:
- при выполнении операций осуществляются обычные арифметические преобразования
- при выполнении операций присваивания, если значение одного типа присваивается переменной другого типа;
- при передаче аргументов функции.
Кроме того, в Си есть возможность явного приведения значения одного типа к другому.
В операциях присваивания тип значения, которое присваивается, преобразуется к типу переменной, получающей это значение. Допускается преобразования целых и плавающих типов, даже если такое преобразование ведет к потере информации.
Преобразование целых типов со знаком. Целое со знаком преобразуется к более короткому целому со знаком, посредством усечения старших битов. Целое со знаком преобразуется к более длинному целому со знаком, путем размножения знака. Когда целое со знаком преобразуется к размеру целого без знака, то результат рассматривается как значение без знака. Преобразование целого со знаком к плавающему типу происходит без потери информации, за исключением случая преобразования значения типа long int или unsigned long int к типу float, когда точность часто может быть потеряна.
Преобразование целых типов без знака. Целое без знака преобразуется к более короткому целому без знака или со знаком путем усечения старших битов. Целое без знака преобразуется к более длинному целому без знака или со знаком путем дополнения нулей слева.
Когда целое без знака преобразуется к целому со знаком того же размера, битовое представление не изменяется. Целые значения без знака преобразуются к плавающему типу, путем преобразования целого без знака к значению типа signed long, а затем значение signed long преобразуется в плавающий тип. Преобразования из unsigned long к типу float, double или long double производятся с потерей информации, если преобразуемое значение больше, чем максимальное положительное значение, которое может быть представлено для типа long.
Преобразования плавающих типов. Величины типа float преобразуются к типу double без изменения значения. Величины double и long double преобразуются к float c некоторой потерей точности. Если значение слишком велико для float, то происходит потеря значимости, о чем сообщается во время выполнения.
При преобразовании величины с плавающей точкой к целым типам она сначала преобразуется к типу long (дробная часть плавающей величины при этом отбрасывается), а затем величина типа long преобразуется к требуемому целому типу. Если значение слишком велико для long, то результат преобразования не определен.
Указатель на тип void может быть преобразован к указателю на любой тип, и указатель на любой тип может быть преобразован к указателю на тип void без ограничений. Значение указателя может быть преобразовано к целой величине. Метод преобразования зависит от размера указателя и размера целого типа следующим образом:
- если размер указателя меньше размера целого типа или равен ему, то указатель преобразуется точно так же, как целое без знака;
- если указатель больше, чем размер целого типа, то указатель сначала преобразуется к указателю с тем же размером, что и целый тип, и затем преобразуется к целому типу.
Целый тип может быть преобразован к адресному типу по следующим правилам:
- если целый тип того же размера, что и указатель, то целая величина просто рассматривается как указатель (целое без знака);
- если размер целого типа отличен от размера указателя, то целый тип сначала преобразуется к размеру указателя (используются способы преобразования, описанные выше), а затем полученное значение трактуется как указатель.
Преобразования, выполняемые над аргументами при вызове функции, зависят от того, был ли задан прототип функции (объявление "вперед") со списком объявлений типов аргументов.
Если задан прототип функции и он включает объявление типов аргументов, то над аргументами в вызове функции выполняются только обычные арифметические преобразования.
Преобразования при приведении типов. Явное преобразование типов может быть осуществлено посредством операции приведения типов, которая имеет формат:
( имя-типа ) операнд .В приведенной записи имя-типа задает тип, к которому должен быть преобразован операнд.
Преобразования при вычислении выражений
При выполнении операций производится автоматическое преобразование типов, чтобы привести операнды выражений к общему типу или чтобы расширить короткие величины до размера целых величин, используемых в машинных командах. Выполнение преобразования зависит от специфики операций и от типа операнда или операндов.
Общие арифметические преобразования.
1. Операнды типа float преобразуются к типу double.
2. Если один операнд long double, то второй преобразуется к этому же типу.
3. Если один операнд double, то второй также преобразуется к типу double.
4. Любые операнды типа char и short преобразуются к типу int.
5. Любые операнды unsigned char или unsigned short преобразуются к типу unsigned int.
6. Если один операнд типа unsigned long, то второй преобразуется к типу unsigned long.
7. Если один операнд типа long, то второй преобразуется к типу long.
8. Если один операнд типа unsigned int, то второй операнд преобразуется к этому же типу.
Таким образом, можно отметить, что при вычислении выражений операнды преобразуются к типу того операнда, который имеет наибольший размер.
4. Понятие истины и логические операции. Сравните с Паскалем, приведите примеры.
Понятие истины языка Си. Любой результат имеющий не нулевое значение является истиной. Любой результат имеющий результат ноль является ложью.
Паскаль. Логический(булев) тип имеет два возможных значения: истина(true) и ложь(false). Эти значение считаются упорядоченными, так что false < true. Под булево значение отводится 1 байт памяти. Булевыми операциями являются: not, end, or, xor. Они используются в логических выражениях, которые включают в себя отношение >,< и т.д. и булевы операции.
Типы циклов
Оператор for
Оператор for - это наиболее общий способ организации цикла. Он имеет следующий формат: for ( выражение 1 ; выражение 2 ; выражение 3 ) тело
Выражение 1 обычно используется для установления начального значения переменных, управляющих циклом. Выражение 2 - это выражение, определяющее условие, при котором тело цикла будет выполняться. Выражение 3 определяет изменение переменных, управляющих циклом после каждого выполнения тела цикла.
Схема выполнения оператора for:
1. Вычисляется выражение 1.
2. Вычисляется выражение 2.
3. Если значения выражения 2 отлично от нуля (истина), выполняется тело цикла, вычисляется выражение 3 и осуществляется переход к пункту 2, если выражение 2 равно нулю (ложь), то управление передается на оператор, следующий за оператором for.
Существенно то, что проверка условия всегда выполняется в начале цикла. Это значит, что тело цикла может ни разу не выполниться, если условие выполнения сразу будет ложным.
Пример:
int main(){ int i,b;for (i=1; i<10; i++)b=i*i;return 0;}В этом примере вычисляются квадраты чисел от 1 до 9.
Так как согласно синтаксису языка Си оператор может быть пустым, тело оператора for также может быть пустым. Такая форма оператора может быть использована для организации поиска.
Пример:
for (i=0; t[i]<10 ; i++) ;
В данном примере переменная цикла i принимает значение номера первого элемента массива t, значение которого больше 10.
Оператор while
Оператор цикла while называется циклом с предусловием и имеет следующий формат:
while (выражение) тело ;
В качестве выражения допускается использовать любое выражение языка Си, а в качестве тела любой оператор, в том числе пустой или составной. Схема выполнения оператора while следующая:
1. Вычисляется выражение.
2. Если выражение ложно, то выполнение оператора while заканчивается и выполняется следующий по порядку оператор. Если выражение истинно, то выполняется тело оператора while.
3. Процесс повторяется с пункта 1.
Оператор do while
Оператор цикла do while называется оператором цикла с постусловием и используется в тех случаях, когда необходимо выполнить тело цикла хотя бы один раз. Формат оператора имеет следующий вид:
do тело while (выражение);
Схема выполнения оператора do while
1. Выполняется тело цикла (которое может быть составным оператором).
2. Вычисляется выражение.
3. Если выражение ложно, то выполнение оператора do while заканчивается и выполняется следующий по порядку оператор. Если выражение истинно, то выполнение оператора продолжается с пункта 1.
Чтобы прервать выполнение цикла до того, как условие станет ложным, можно использовать оператор break.
Операторы while и do while могут быть вложенными.
В Паскале: repeat [тело] until [усл]; while [усл] do [тело]; for i:=1 to [усл] do [тело];
Операторы ветвления
Условный оператор
Есть два вида условных операторов
if ( выражение ) оператор
if ( выражение ) оператор else оператор
В обоих случаях вычисляется выражение, и если оно не ноль, то выполняется первый подоператор. Во втором случае второй подоператор выполняется, если выражение есть 0.
Оператор switch
Оператор switch вызывает передачу управления на один из нескольких операторов в зависимости от значения выражения. Он имеет вид
switch ( выражение ) оператор
Выражение должно быть целого типа или типа указателя. Любой оператор внутри оператора может быть помечен одним или более префиксом case следующим образом:
case константное_выражение :
где константное выражение должно иметь тот же тип что и выражение- переключатель; производятся обычные арифметические преобразования. В одном операторе switch никакие две константы, помеченные case, не могут иметь одинаковое значение. Может также быть не более чем один префикс оператора вида default :
Когда выполнен оператор switch, проведено вычисление его выражения и сравнение его с каждой case константой. Если одна из констант равна значению выражения, то управление передается на выражение, следующее за подошедшим префиксом case. Если никакая case константа не соответствует выражению, и есть префикс default, то управление передается на выражение, которому он предшествует. Если нет соответствующих вариантов case и default отсутствует, то никакой из операторов в операторе switch не выполняется. Префиксы case и default сами по себе не изменяют поток управления, который после задержки идет дальше, перескакивая через эти префиксы. Для выхода из switch используется break, Обычно зависящий от switch оператор является составным. В голове этого оператора могут стоять описания, но инициализации автоматических и регистровых переменных являются безрезультатными.
Оператор goto
Можно осуществлять безусловную передачу управления с помощью оператора
goto идентификатор ;
Идентификатор должен быть меткой , расположенной в текущей функции.
Массивы и указатели
Указатель - это переменная, содержащая адрес другой переменной.
Массив – структурированный тип данных, все элементы которого имеют один и тот же тип и расположены в памяти подряд.
При выделении массива ему выделяется память так же, как и массивам других алгоритмических языков. Но как только память для массива выделена, имя массива воспринимается как константный указатель того типа, к которому отнесены элементы массива, значением которого служит адрес первого элемента массива (с индексом 0).
Раз имя массива есть указатель, то к нему применимы все правила адресной арифметики, связанной с указателями. Т.к. имя массива есть не просто указатель, а указатель константа, то значение имени массива невозможно изменить.
Существует исключения, например, применение имени массива в операции sizeof. В этой операции массив «вспоминает» о своем отличии от обычного указателя, и результатам является размер в байтах участка памяти, выделенного не для указателя, а для массива в целом. Исключением является и применение операции & (получение адреса) к имени массива. Результат – адрес начального (с нулевым индексом) элемента массива.
И к указатели, и к массиву применима индексация, но массив не перемещаемый указатель.
Классы памяти
Спецификатор класса памяти в объявлении переменной может быть auto, register, static или extern. Если класс памяти не указан, то он определяется по умолчанию из контекста объявления. Объекты классов auto и register имеют локальное время жизни. Спецификаторы static и extern определяют объекты с глобальным временем жизни. При объявлении переменной на внутреннем уровне может быть использован любой из четырех спецификаторов класса памяти, а если он не указан, то подразумевается класс памяти auto.
Переменная с классом памяти auto имеет локальное время жизни и видна только в блоке, в котором объявлена. Память для такой переменной выделяется при входе в блок и освобождается при выходе из блока. При повторном входе в блок этой переменной может быть выделен другой участок памяти. Переменная с классом памяти auto автоматически не инициализируется. Она должна быть проинициализирована явно при объявлении путем присвоения ей начального значения. Значение неинициализированной переменной с классом памяти auto считается неопределенным. Спецификатор класса памяти register предписывает компилятору распределить память для переменной в регистре, если это представляется возможным. Использование регистровой памяти обычно приводит к сокращению времени доступа к переменной. Переменная, объявленная с классом памяти register, имеет ту же область видимости, что и переменная auto. Число регистров, которые можно использовать для значений переменных, ограничено возможностями компьютера, и в том случае, если компилятор не имеет в распоряжении свободных регистров, то переменной выделяется память как для класса auto. Класс памяти register может быть указан только для переменных с типом int или указателей с размером, равным размеру int. Переменные, объявленные на внутреннем уровне со спецификатором класса памяти static, обеспечиваю возможность сохранить значение переменной при выходе из блока и использовать его при повторном входе в блок. Такая переменная имеет глобальное время жизни и область видимости внутри блока, в котором она объявлена. В отличие от переменных с классом auto, память для которых выделяется в стеке, для переменных с классом static память выделяется в сегменте данных, и поэтому их значение сохраняется при выходе из блока.
Пример:
/* объявления переменной i на внутреннем уровне с классом памяти static. */
/* исходный файл file1.c */
main()
{ ...
}
fun1()
{ static int i=0; ...
}
/* исходный файл file2.c */
fun2()
{ static int i=0; ...
}
fun3()
{ static int i=0; ...
}
В приведенном примере объявлены три разные переменные с классом памяти static, имеющие одинаковые имена i. Каждая из этих переменных имеет глобальное время жизни, но видима только в том блоке (функции), в которой она объявлена. Эти переменные можно использовать для подсчета числа обращений к каждой из трех функций.
10. Структура и объединение. Доступ к полям. Сходства и отличия. Приведите примеры.
Cтруктуры - это составной объект, в который входят элементы любых типов, за исключением функций. В отличие от массива, который является однородным объектом, структура может быть неоднородной. Тип структуры определяется записью вида:
struct { список определений }
В структуре обязательно должен быть указан хотя бы один компонент. Определение структур имеет следующий вид:
тип-данных описатель;
где тип-данных указывает тип структуры для объектов, определяемых в описателях. В простейшей форме описатели представляют собой идентификаторы или массивы.
Пример: struct { double x,y; } s1, s2, sm[9];
Переменные s1, s2 определяются как структуры, каждая из которых состоит из двух компонент х и у. Существует и другой способ ассоциирования имени с типом структуры, он основан на использовании тега структуры. Тег структуры аналогичен тегу перечислимого типа. Тег структуры определяется следующим образом: struct тег { список описаний; };
где тег является идентификатором.
В приведенном ниже примере идентификатор student описывается как тег структуры:
struct student { char name[25]; int id, age; char prp; };Использование тегов структуры необходимо для описания рекурсивных структур. Ниже рассмотрен пример использования рекурсивных тегов структуры.
struct node { int data; struct node * next; } st1_node;Тег структуры node действительно является рекурсивным, так как он используется в своем собственном описании, т.е. в формализации указателя next. Структуры не могут быть прямо рекурсивными, т.е. структура node не может содержать компоненту, являющуюся структурой node, но любая структура может иметь компоненту, являющуюся указателем на свой тип, как и сделано в приведенном примере.
Доступ к компонентам структуры осуществляется с помощью указания имени структуры и следующего через точку имени выделенного компонента, например:
Объединения (смеси)
Объединение подобно структуре, однако в каждый момент времени может использоваться (или другими словами быть ответным) только один из элементов объединения. Тип объединения может задаваться в следующем виде:
union { описание элемента 1; ... описание элемента n; };Главной особенностью объединения является то, что для каждого из объявленных элементов выделяется одна и та же область памяти, т.е. они перекрываются. Хотя доступ к этой области памяти возможен с использованием любого из элементов, элемент для этой цели должен выбираться так, чтобы полученный результат не был бессмысленным.
Доступ к элементам объединения осуществляется тем же способом, что и к структурам. Тег объединения может быть формализован точно так же, как и тег структуры.
Объединение применяется для следующих целей:
- инициализации используемого объекта памяти, если в каждый момент времени только один объект из многих является активным;
- интерпретации основного представления объекта одного типа, как если бы этому объекту был присвоен другой тип.
Память, которая соответствует переменной типа объединения, определяется величиной, необходимой для размещения наиболее длинного элемента объединения. Когда используется элемент меньшей длины, то переменная типа объединения может содержать неиспользуемую память. Все элементы объединения хранятся в одной и той же области памяти, начиная с одного адреса.
11. объявление, прототип и определение функций. Приведите примеры.
Функция - это совокупность объявлений и операторов, обычно предназначенная для решения определенной задачи. Каждая функция должна иметь имя, которое используется для ее объявления, определения и вызова. В любой программе на СИ должна быть функция с именем main (главная функция), именно с этой функции, в каком бы месте программы она не находилась, начинается выполнение программы. При вызове функции ей при помощи аргументов (формальных параметров) могут быть переданы некоторые значения (фактические параметры), используемые во время выполнения функции. Функция может возвращать некоторое (одно !) значение. Это возвращаемое значение и есть результат выполнения функции, который при выполнении программы подставляется в точку вызова функции, где бы этот вызов ни встретился. Допускается также использовать функции не имеющие аргументов и функции не возвращающие никаких значений. Действие таких функций может состоять, например, в изменении значений некоторых переменных, выводе на печать некоторых текстов и т.п.. использованием функций в языке СИ связаны три понятия - определение функции (описание действий, выполняемых функцией), объявление функции (задание формы обращения к функции) и вызов функции. В языке СИ нет требования, чтобы определение функции обязательно предшествовало ее вызову. Определения используемых функций могут следовать за определением функции main, перед ним, или находится в другом файле. Однако для того, чтобы компилятор мог осуществить проверку соответствия типов передаваемых фактических параметров типам формальных параметров до вызова функции нужно поместить объявление (прототип) функции. Объявление функции имеет такой же вид, что и определение функции, с той лишь разницей, что тело функции отсутствует, и имена формальных параметров тоже могут быть опущены. Если прототип функции не задан, а встретился вызов функции, то строится неявный прототип из анализа формы вызова функции. Тип возвращаемого значения создаваемого прототипа int, а список типов и числа параметров функции формируется на основании типов и числа фактических параметров используемых при данном вызове. Таким образом, прототип функции необходимо задавать в следующих случаях:
1. Функция возвращает значение типа, отличного от int.
2. Требуется проинициализировать некоторый указатель на функцию до того, как эта функция будет определена.
Наличие в прототипе полного списка типов аргументов параметров позволяет выполнить проверку соответствия типов фактических параметров при вызове функции типам формальных параметров, и, если необходимо, выполнить соответствующие преобразования. Функция не может возвращать массив или функцию, но может возвращать указатель на любой тип, в том числе и на массив и на функцию. Тип возвращаемого значения, задаваемый в определении функции, должен соответствовать типу в объявлении этой функции. Функция возвращает значение если ее выполнение заканчивается оператором return, содержащим некоторое выражение. Указанное выражение вычисляется, преобразуется, если необходимо, к типу возвращаемого значения и возвращается в точку вызова функции в качестве результата. Если оператор return не содержит выражения или выполнение функции завершается после выполнения последнего ее оператора (без выполнения оператора return), то возвращаемое значение не определено. Для функций, не использующих возвращаемое значение, должен быть использован тип void, указывающий на отсутствие возвращаемого значения. Если функция определена как функция, возвращающая некоторое значение, а в операторе return при выходе из нее отсутствует выражение, то поведение вызывающей функции после передачи ей управления может быть непредсказуемым.
Основные понятия текстового и графического режимов.
Рабочий режим экрана определяется, когда ваша программа вы-
зывает одну из функций определения режима (textmode, initgraph
или setgraphmode).
В текстовом режиме разметка экрана – кол. строк*кол. Символов в строке.
Textmode(int):
LASTMODE -1 Предыдущий т. режим
BW40 0 Черно-белый, 40 столбцов
C40 1 16 цветов, 40 столбцов
BW80 2 Черно-белый, 80 столбцов
C80 3 16 цветов, 80 столбцов
MONO 7 Монохромный, 80 столбцов
C4350 64 EGA, 80x43; VGA, 80x50 строк
В графическом режиме X*Y пикселов и цвет.
int driver, mode;
driver = VGA;
mode = VGAHI;
initgraph(&driver, &mode, "c:\\borland\\bgi");
if(graphresult() < 0) //Ошибка
x_size = getmaxx();
y_size = getmaxy();
closegraph();
closegraph - Закрывает графическую систему.
detectgraph - Проверяет аппаратное обеспечение и определяет, какие графические драйверы использовать;
graphdefaults - Сбрасывает все переменные графической системы в значения по умолчанию.
_graphfreemem - Отменяет выделенную графикепамять. Используется для определения собственной подпрограммы.
_graphgetmem - Распределяет память графике; используется для определения собственной подпрограммы.
getgraphmode - Возвращает текущий графический режим.
getmoderange - Возвращает минимальный и максимальный допустимые режимы для заданного драйвера.
initgraph - Инициализирует графическую систему и переводит аппаратное обеспечение в графический режим.
installuserdriver - Устанавливает дополнительный драйвер устройства в таблице драйверов устройста BGI.
installuserfont - Загружает поставляемый файл векторного (штрихового) шрифта в таблицу символьных файлов BGI.
registerbgldriver - Регистрирует внешний или загруженный пользователем файл драйвера для включения во время компоновки.
restorecrtmode - Восстанавливает первоначальный (существовавший до Initgraph) режим экрана. setgraphbufsize - Задает размер внутреннего графического буфера.
setgraphmode - Выбирает заданный графический режим, очищает зкран и восстанавливает все умолчания.
19. Использоване модификаторов near, far, huge. Приведите примеры.(АЯиП)
Ближние указатели (near) 16-битовый (near) указатель для вычисления полного адреса связывается с одним из сегментных регистров; например, указатель функции складывает свое 16-битовое значение со сдвинутым влево содержимым регистра кодового сегмента (CS). Аналогичным образом, ближний указатель данных содержит смещение в сегменте данных, адресуемом регистром сегмента данных (DS). С ближними указателями легко манипулировать, поскольку все арифметические операции с ним (например, сложение) можно выполнять безотносительно к сегменту.
Дальние указатели (far)Дальний (32-битовый) указатель содержит не только смещение относительно регистра, но также и (в остальных 16 битах) адрес сегмента, который затем должен быть сдвинут влево и сложен со значением смещения. Использование дальних указателей позволяет иметь в программе несколько кодовых сегментов; это, в свою очередь, позволяет программе превышать 64К. Можно также адресовать более 64К данных. При использовании дальних указателей для адресации данных следует учитывать некоторые потенциальные проблемы, которые могут возникать при манипулировании такими указателями. Может существовать
множество пар типа сегмент: смещение, адресующих одну и ту же точку памяти. Например, если бы были три переменных типа дальнего указателя - a, b и c, содержащих соответственно три указанных значения, то следующие выражения все давали бы значение "ложь":
if (a == b) . . .
if (b == c) . . .
if (a == c) . . .
Аналогичная проблема возникает, когда требуется сравнивать дальние указатели при помощи операций >, >=, < и <=. В этих случаях в сравнении участвует только смещение; при указанных значениях a, b и c следующие выражения дадут значения "истина":
if (a > b) . . .
if (b > c) . . .
if (a > c) . . .
Операции равенства (==) и неравенства (!=) используют 32-битовые значения как unsigned long (а не в виде полного адреса памяти). Операции сравнения (<=, >=, < и >) используют только смещение. Операции == и != требуют все 32 бита, что позволяет компьютеру выполнять сравнение с пустым (NULL) указателем (0000:0000). Если для проверки равенства использовалось только значение смещения, то любой указатель со смещением 0000 будет равен пустому указателю, что явно не совпадает с тем, что вы хотели получить.
Указатели huge также имеют размер 32 бита. как и указатели far, они содержат одновременно адрес сегмента и смещение. Однако, в отличие от дальних указателей, они нормализованы, что позволяет избежать проблем, связанных с дальними указателями. Нормализованный указатель - 32-битовый указатель, который содержит в своем адресе сегмента максимально возможное значение. Поскольку сегмент может начинаться через каждые 16 байт (10 при основании 16), это означает, что величина смещения будет равна числу от 0 до 15 (от 0 до F с основанием 16). Для нормализации указателя он преобразуется к 20-битовому адресу, после чего правые 4 бита берутся в качестве смещения, а левые 16 битов - как адрес сегмента. Существует три причины, заставляющие всегда хранить указатель huge в нормализованном виде:
1. Поскольку в таком случае любому заданному адресу памяти соответствует только один возможный адрес в виде сегмент: смещение типа huge. Это означает, что для указателей huge операции == и != всегда будут возвращать правильное значение.
2. Кроме того, операции >, >=, < и <= работают с полным 32-битовым значением указателя huge. Нормализация гарантирует в данном случае корректность результата.
3. И наконец, вследствие нормализации смещение в указателе huge выполняет автоматический переход через 16 но в отличие от дальних указателей, переход затрагивает и сегмент. Эта особенность указателей huge позволяет манипулировать со структурами данных с размером более 64К.
Гарантируется, например, что если имеется массив структур типа huge, превышающий 64К, индексация этого массива и выбор поля структуры всегда будут выполняться правильно, независимо от размера структуры. Использование указателей huge имеет свою цену: увеличение времени обработки. Арифметические операции с указателями huge выполняются при помощи обращений к специальным подпрограммам. Вследствие этого арифметические вычисления занимают существенно больше времени по сравнению с вычислениями для указателей far или near.
20. Сравнительная характеристика языков С и С++(без классов): ссылки, модификатор const, параметры по умолчанию. (АЯиП)
Язык Си++ вводит новые объекты:
1.Типированные константы - переменные только для чтения, которые обязательно должны получить значение в месте объявления: const unsigned u=3456;
и могут быть только статическими, доступными только в пределах своего файла. Чтобы сделать их доступными из других единиц компиляции, придется объявлять их с ключевым словом extern extern const unsigned u=3456;
Чтобы использовать в другом файле, нужно тоже использовать extern - модификатор и не присваивать значение: extern const unsigned u;
2.Ссылка <тип> & <имя переменной>=<перемен>; Ссылка второе имя переменной для ссылки обязательна инициализация. Они тоже содержат адрес объекта, но при обращении по ссылке не надо применять операцию разадресации, как это необходимо при доступе по указателям. Ссылаться можно только на ранее "прописанный" в памяти объект. Ссылки вводят третий механизм передачи формальных параметров. Так же как и по адресу копирует адрес объекта. int y=16; int& x=y; Нельзя указатель создать на ссылку. Можно использовать независимую ссылку на константу.
3.Управление памятьюК таким функциям, как malloc() и free(), в С++ добавлены 3 встроенных в язык оператора new, delete, delete[]. Оператор new используется для создания объекта в куче: int nf=18; float * fp= new float[nf];
Оператор new позволяет попутно заполнить выделяемую память заданным значением: float * fp= new float[nf] (0); (массив заполняется нулями). new - в отличие от malloc, вернет ненулевой указатель, если по ошибке запросили 0 байтов памяти и запись в эту память имеет непредсказуемые последствия. Освобождение памяти осуществ. операторы delete или delete[] (для массивов).
4.Перегрузка функций - возможность использовать в программе функции с одинаковыми именами, если они имеют отличающиеся списки аргументов. С этой возможностью связано также требование предварительного объявления прототипа функции до ее вызова на выполнение - это объявление используется компилятором для определения правильности передачи аргументов при вызове, особенно для функций с одинаковыми именами.
Появление параметров по умолчанию в функциях которые автоматически будут использованы в том случае, если при вызове функции соответствующий аргум<