Является ссылкой на переменную с тем же самым именем, определенную на внешнем уровне в любом исходном файле программы. Целью внутреннего объявления Extern является доступ к определению переменной внешнего уровня. Внутреннее объявление Extern не влияет область действия глобальных переменных в любой другой части программы.
main()
static int i=0;
{
func();
}
int func
{
i++;
printf (“%d”,i);
}
Динамическая структура данных. Синтаксическое и динамическое распределение памяти.
При транслировании программы под каждую описанную переменную резервируется определенное количество памяти.
Если требуется хранение информации иного объема, необходимо либо предусмотреть максимально возможное использование памяти, либо произвести выделение памяти во время работы программы. Также к проблемам данного рода относится хранение информации типа разреженных матриц, то есть массивов данных, в которых большинство элементов имеют нулевые значения. Для решения этих проблем в языках высокого уровня присутствуют динамические типы данных, реализуемых с помощью специального вводимого типа «указатель». Это позволяет в ходе выполнения программы в соответствии с информацией от пользователя отводить память под необходимое количество данных.
Пример:
Если производится действия с разреженной матрицей, то память не резервируется, а выделяется заново при вводе нулевого элемента. Данный способ хранения дополнительно требует хранить информацию о положении элемента в матрице. Из этого следует, что, например, для матрицы (двумерного массива) целых чисел, заполненной более чем на 1/3 использование данной методики не приводит к экономии памяти (неэффективно).
При использовании указателей во время трансляции память резервируется для хранения указателя. Собственно участок памяти, предназначенный для хранения данных, определяется с помощью специальных функций, которые реализуют доступ к функциям распределения памяти ОС.
Вместе с функциями выделения памяти, которые позволяют повторно использовать под другие объекты ранее выделенную память под уже неиспользуемые объекты.
При использовании статического варианта распределения памяти она высвобождается из-под переменных в случае окончания блока действия переменной. После закрытия блока, в которой данная переменная была описана.
При динамическом варианте распределения памяти программист самостоятельно должен высвобождать память после окончания жизни переменных. В силу ограниченности доступной программисту памяти. Динамическое выделение памяти осуществляется в соответствие со служебной информацией, хранящейся в таблице сводных блоков памяти, с которыми работает ОС.
Вызов функции распределения памяти в С-программе приводит к вызову функций ОС, которая просматривает таблицу сводных блоков памяти, находит первую подходящую по размерам непрерывную последовательность ячеек, исключает её из таблицы, обновляя информацию о свободных блоках, и возвращает адрес начала в точку вызова.
Вызов функции освобождения памяти влечет за собой действие по включению данной последовательности байт в таблицу свободной памяти.
Данный способ выделения памяти приводит к проблеме фрагментации памяти. Например, освобождение каждого второго 2-байтовогоэлемента из массива из 100 элементов не приведет к возможности выделения памяти под 100-байтовый элемент, если ранее такой возможности не было.
Выполнение самостоятельного распределения памяти без участия ОС потребует самостоятельного выполнения действий с таблицей свободных блоков памяти, что не рекомендуется делать в соответствие с принципами структурного программирования.
Для исключения проблемы фрагментации памяти программист обязан следить за последовательностью выделения и освобождения областей памяти.
Задача.
Написать программу для хранения матрицы целых чисел размером 50х50 элементов. Вводят их значение с клавиатуры и выводит ненулевые по 5 значений в строке с указанием индекса элемента. После чего память освобождается, затем выделяется для хранения вектора из 100 действительных чисел, которые вводятся с клавиатуры, печатается минимальный и максимальный элементы, после чего память освобождается. Функция malloc, возвращаемое значение указатель на выделенную область памяти, NULL если данное количество недоступно. Параметр: количество байт. Free – параметр-указатель, ранее полученный с помощью функции выделения памяти.
#include<malloc.h>
#include<conio.h>
#include<stdio.h>
main()
{
int *A;
int i,j,k,min,max;
A=(int*)malloc (50*sizeof(50 int))
for (i=0;i<50;i++)
{
for (j=0;j<50;j++)
{
A[i*50+j]=(int*)malloc (sizeof(int));
}
}
for (i=0;i<50;i++)
{
for (j=0;j<50;j++)
{
printf (“A[%d][%d]=%d”,i,j);
scanf (“%d”,&A[i][j]);
}
}
for (i=0;i<50;i++)
{
for (j=0;j<50;j++)
{
if (A[i][j]!=0)
for (k=0;k<5;k++)
{
printf (“A[%d][%d]=%d”,A[i][j]);
}
printf (“\n”);
}
}
free A;
A=malloc(200*sizeof(float));
min=A[0], max=A[0]
for (j=0;j<100;j++)
{
printf (“A[%d]=%d”,j);
scanf (“%d”,&A[j]);
if(A[j]<min)min=A[j];
if(A[j]>max)max=A[j];
}
printf (“%f\t%f”,max,min);
free A;
getch();
}
Рекомендуется использование функции освобождения памяти сразу после окончания использования области выделенной памяти для избегания возникновения ситуаций утечки памяти. Теоретически нормальное завершение программы включает в себя освобождение всей динамически выделенной программы памяти, даже если функция free не вызывалась, то при нарушении нормальной процедуры завершения программы автоматический вызов функций освобождения памяти производиться не будет, что приведет к некорректному содержимому таблицы свободных блоков памяти.
Использование указателей.
Список – базовая структура, позволяющая определить любую структуру данных. Указатели вводятся в языки высокого уровня с целью поддержания списковых структур. Элемент списка представляет собой объект, содержащий информационное поле и 1 или несколько адресных полей, предназначенных для связи с другими элементами списка. При отсутствии связи адресное поле равно специальному значению указателя, гарантировано ссылающемуся ни какой объект (NULL – нулевой указатель).
Однонаправленный (односвязный) список.
Элементом является структура, в число полей которой входит поле адреса, в котором хранится ссылка на следующий элемент односвязного списка, относят данную структуру хранения к связным, и поле данных, содержащее информацию, предназначенную для хранения.
Связанный список определяется адресом начала (головы списка), конец списка определяется элементом, в поле адреса которого хранится значение, не ссылающееся ни на какую область памяти (NULL)
Создание связного списка.
1) Выделить память для хранения адреса головы;
2) Выделить память для хранения элементов списка;
3) Обнулить поле адреса;
4) Записать в поле данных содержащую информацию;
5) Сохранить адрес головы списка в переменной, хранящей ссылку на начало списка.
Добавление элемента в конец списка.
1) Присвоить указателю адрес головы списка;
2) Проанализировать значение поля адреса. Пока оно не равно 0, присваивать указателю значение поля адреса.
3) Создать элемент списка и записать его в поле адрес конца списка.
Просмотр связного списка.
1. для всех значений поля адреса, начиная с головы списка, пока не обнаружено нулевое значение адреса, выполнять сравнение поля данных с требуемой информацией.
2. если сравнение дает положительный результат, то выдать элемент списка.
3. если достигнуто значение адреса 0, выдать сообщение, что элемент не найден.
Добавление элемента в произвольное место списка.
Найти заданный элемент, сохранить значение его поля адреса, создать новый элемент, записать адрес нового элемента в поле адреса заданного (найденного) элемента.
Записать в поле адреса добавляемого элемента сохраненный адрес следующего элемента.
Процедура добавления элемента в произвольное место списка показывает преимущество связного хранения перед последовательным (массивы).
Удаление элемента из конца списка.
Найти последний элемент, освободить память, записать в поле адреса предпоследнего элемента значение NULL. В данной процедуре требуется хранить текущее значение адреса и адрес предыдущего элемента.
Удаление произвольного элемента связного списка.
Найти удаляемый элемент, сохранить его адрес. В поле адреса предыдущего элемента записать адрес следующего. Освободить память из-под удаляемого элемента.
Кольцевой односвязный список.
Структура аналогична структуре односвязного однонаправленного списка, за исключением того, что в поле адреса конечного элемента хранится адрес головы списка.
Все процессы взаимодействия со списком аналогичны вышеописанным, за исключением того, что проверка на конец списка осуществляется не с NULL, а со значением адреса головы списка.
Двунаправленный список.
Каждый элемент списка содержит адрес не только следующего элемента, но и предыдущего. Голова списка в адресе предыдущего элемента содержит NULL.
Кольцевой двунаправленный список.
Поле предыдущий элемент головы списка содержит адрес конца списка.
Двусвязный список.
Каждый элемент списка содержит 2 ссылки на 2 следующих элемента.
Двунаправленный (двусвязный) список.
Элемент такого списка помимо ссылки на левый и правый следующие элементы содержит ссылку на предыдущий элемент.
Многосвязный список.
Каждый элемент содержит n-ссылок на следующие элементы.
Задание.
Спроектировать структуру данных многосвязного списка с произвольным числом ответвлений от каждого узла.
struct node
struct node_t;
struct node
{
int data; struct node_t*v;
};
struct node_t
{
struct node_l;
struct node_t*n;
};
Head
Преимущество последовательного хранения.
При известном размере каждого элемента возможен доступ по индексу элемента.
Недостатки: необходимость резервирования предполагаемого максимального размера, невозможность добавления и исключения элементов, а только модификация.
Недостатки связного хранения: множество дополнительных операций, приводящих к замедлению скорости; доступ к элементам возможен только после просмотра предыдущих элементов.
Преимущества: отсутствие необходимости резервирования максимально предполагаемого размера памяти; отсутствие требований непрерывности используемой памяти; возможность произвольного добавления и исключения элементов.
Дисциплина обслуживания. Очередь.
Принцип: «first-in, first-out» (FIFO)
Стек:«last-in, first-out» (LIFO)
Дек (двунаправленная очередь).
Функции (f).
Совокупность объявлений и операторов, предназначенных для выполнения некоторых отдельных задач. Количество функций в программе не ограничивается. Любая программа на языке С содержит как минимум 1 функцию (главную) с именем main.
Определение функции специфицирует имя функции, атрибуты ее формальных параметров и тело функции, содержащее объявления и операторы. В определении функции также может задаваться класс памяти функции и тип возвращаемого значения.
Объявление функции задает имя и тип возвращаемого значения. В функции, явное определение которой приведено в другом месте программы. В объявлении функции может также специфицироваться класс памяти, число аргументов и их типы. Также допускается задавать в объявлении идентификаторы и класс памяти аргументов. Если тип возвращаемого значения не указывается в определении, то указывается int.
К моменту вызова функции должен быть известен тип возвращаемого значения, что требует предварительного объявления, если это необходимо.
Вызов функции передает управление от возвращаемой функции к вызываемой, значения фактических аргументов при их наличии передаются в вызываемую функцию. При выполнении оператора возврата return в вызываемую функцию управление и возвращаемое значение, если оно есть, передаются в вызывающую функцию. Функция может возвращать значения любого типа, кроме массива или функции. В частности, указатель на любой тип, включая массив и функцию.
Тип возвращаемого значения, задаваемый в определении функции должен соответствовать типу типу возвращаемого значения во всех объявлениях этой функции. Для вызова функции с целым возвращающим значением предварительное объявление не требуется. Для других типов функции должны быть либо объявлены, либо определены до вызова.
Возвращаемое значение функции вырабатывается при выполнении return, содержащего выражение. Выражение вычисляется, преобразуется к типу возвращаемого значения и возвращается в точку вызова функции. Если return отсутствует или не содержит выражения, то возвращаемое значение функции не определено. В этом случае, если значение ожидается, то поведение программы непредсказуемо.
Формальные параметры.
Переменные, которые принимают значения, передаваемые функции при вызове в соответствии с порядком следования их имен в списке параметров. Список параметров содержит в ( ) идентификаторы, разделенные запятыми с указанием типа. Список может быть пустым, в этом случае также ограничивается ( ). После последнего идентификатора в списке параметров может быть записана, … - означает, что число параметров функции переменно, но не меньше, чем следует идентификаторов до многоточия.
Для доступа к значениям параметров, имена которых не заданы в списке формальных параметров, рекомендуется использовать макроопределения:
va_arg; va_end; va_start;
Допускается список параметров только из многоточия. Это означает, что число параметров переменной может быть =0.
Формальные параметры могут иметь базовый тип, либо быть struct, union, указателем или массивом. Указание первой (единственной)размерности для массива не обязательно. Массив воспринимается как указатель на тип элементов массива.
char s[ ]; char S[10]; char*S т.е. для формальных параметров эти 3 определения эквивалентны.
Параметры могут иметь класс памяти auto или registr( по умолчанию auto) . Если параметр представлен, но не объявлен, то предполагается int.
Идентификаторы формальных параметров не могут совпадать с идентификаторами переменных внутри тела функции, но возможно локальное переобъявление формальных параметров внутри вложенных блоков функции.
В объявлении формальных параметров не может перечисляться никакой другой идентификатор, кроме перечисленных в списке параметров. если имеется переменное число параметров, то программист отвечает за определение числа при вызове и получение их из стека функции.
Тип каждого формального параметра должен соответствовать типу фактического аргумента и типу соответствующего аргумента в списке типов аргументов функции в предварительном объявлении со списком типов.
Компилятор преобразует по умолчанию, отдельно над типом каждого формального параметра и фактического аргумента. После преобразования все формальные параметры имеют тип размером не меньшим, чем int и ни один из формальных параметров не имеет тип float.если используется модификаторы near, far, huge компилятор также может неявно провести преобразование аргументов указателей. Метод преобразования зависит от размера указателей в выбранной модели памяти и от наличия или отсутствия списка типов. Тип каждого формального параметра после преобразования определяет как интерпретируются размещенные в стеке аргументы, несоответствие типов фактических аргументов типам формальных параметров может привести к неверной интерпретации. Например, если в качестве аргумента передается 16-битовый указатель, и соответствующий формальный параметр объявлен как 32-битный, то вместо 16 бит из стека будут проинтерпретированы 32 бита, что повлечет за собой изменение значения указателя и других параметров, которые следуют за этим. Ошибки такого рода можно исключить, используя объявление функции со списком типов аргументов. Если функции не имеют аргументов, то рекомендуется использовать ключевое слово point.
Тело функции.
Составной оператор или блок. Он содержит операторы, определяющие действие функции и объявление переменных, используемых в этих операторах. Все переменные, объявленные в теле функции , имеют по умолчанию класс памяти auto, можно явно присвоить другой класс памяти. При вызове функции выделяется память для её локальных переменных и, если указано, проводится их инициализация. Управление передается 1 оператору составного оператора. Выполнение продолжается до тех пор, пока не встретится return или конец тела функции, то есть составного оператора. Управление возвращается в точку вызова функции. Если функция возвращает значение, то должен выполняться return с выражением, иначе возвращаемое значение не определено.
Вызов функции.
Передает управление и фактические аргументы заданной функции.
Синтаксис: выражение (список выражений). Выражение вычисляется и его результат интерпретируется как адрес функции. Выражение должно иметь тип функции. Список выражений, в котором выражения следуют через запятую, представляют собой перечень фактических аргументов, передаваемых функции. Список может быть пустым. При выполнении вызова функции происходит присвоение значений фактических аргументов к формальным параметрам. Перед этим каждый фактический аргумент вычисляется, выполняется необходимые преобразования и он копируется в стек.
I фактический аргумент – I формальному параметру
II - II
…
Все аргументы передаются по значению и только массивы по ссылке. Вызванная функция работает с копией фактических аргументов, поэтому никакое изменение формальных параметров не отразится на значении аргументов, с которых сделана копия. Порядок вычисления выражений, представляющий аргументы функции не определены в С, что может приводить к побочным эффектам. Гарантируется то, что все побочные эффекты будут вычислены до передачи управления вызываемую функцию. Выражение должно ссылаться на функцию. Это означает, что функция может быть вызвана не только по идентификатору, но и через любое выражение, имеющее тип указателя на функцию.
Фактические аргументы.
Фактические аргументы могут быть любым значением базового типа, либо быть struct, union, указателем. Все фактические аргументы передаются по значению. Для массивов и функции передаются указатели на эти объекты. Возможность доступа не к копиям значений, а к самим переменным обеспечивают указатели, содержащие адреса переменных. Фактические аргументы вычисляются и преобразуются следующим образом:
a. если имеется объявление со списком типов аргументов – прототип, то при вызове функции выполняется преобразование по умолчанию над типом каждого фактического аргумента, заданном в списке типов аргументов. Факт приводится к преобразованному типу (float→double, затем фактический аргумент→double ). Независимо от аргументов тип соответствующего формального параметра в списке параметров также подвергается преобразованию по умолчанию. Затем полученный тип фактического аргумента сравнивается с типом соответствующего формального параметра. В случае несоответствия преобразования нет, но компилятор выдает предупредительное выражение как и в случае, как и в операторе присваивания не совпадают типы левого и правого операндов.
b. Если прототип отсутствует, преобразование по умолчанию производится отдельно для каждого аргумента, не имеющего соответствующего имени типа. Если список типов аргументов завершается и задано больше фактических аргументов, то лишние фактические аргументы преобразуются по умолчанию. Если список не завершен…, а передается больше аргументов, то компилятор выдает сообщение об ошибке. Если список содержит void, то наличие фактических аргументов приводит к сообщению об ошибке. Для доступа к аргументам, указанным после объявленных формальных параметров, используют макроопределения.
Рекурсивные функции.
Любая функция в С-программе может быть вызвана рекурсивно (может вызвать сама себя). Компилятор не ограничивает число таких вызовов. При каждом вызове выделяются новые области памяти, для static и extern переменных нет. Число рекурсивных вызовов имеет фактические ограничение, связанное с размером стека.
Файл.
Последовательность является одной из фундаментальных структур данных. В языках высокого уровня для обозначения последовательности компонентов одного и того же типа применяют термин «файл». В любой момент времени один-единственный компонент, другие могут быть получены путем последовательного просмотра файла. Число компонентов, называемых длиной файла, не фиксируется, что позволяет отнести файл к динамическим структурам данных. Файл может ни содержать ни одного элемента. Называется пустым.
Над файлами выполнены 2 типа действий:
1. просмотр (последовательное продвижение по файлу сначала). В процессе просмотра изменять значения компонентов на новые запрещается.
2. создание файла (выполняется дополнение новых элементов в конец первоначально пустого файла). В процессе создания новые значения разрешается записывать только в конец файла. Все остальные действия являются комбинациями его просмотра и создания.
Задача.
Вставить в файл целых чисел после 10-го элемента 25 целых чисел, хранящихся в массиве.
Обновить в файле элементы с 11 по 35. реализовать оба варианта.
Решение.
Создается новый файл – пустой. Обновляемый просматривается. Считывается первые 10 элементов, записываются во вновь созданный файл. Затем туда же дописывается 25 элементов. Затем файл просматривается до признака конца файла. Считанные файлы добавляются.
В случае обновления просмотр продолжается во время создания. Старый файл создается заново (пустой). Его обновленная версия просматривается, считываемые файлы записываются в исходный файл.
Открытие.
Сопоставление файловой переменной с областью действия во внешней памяти, что выполняется средствами ОС. Количество открытых файлов ограничивается значением, хранящийся в переменной среды окружения ОС (имя переменной в MS-DOS) files.
Файл может быть открыт и в режиме просмотра, и в режиме создания. Исторически определялось, что файлы будут храниться на накопителе с последующим доступом (магнитные ленты), в настоящее время с произвольным доступом. Однако лазерные диски сохранили последовательный доступ. В связи с тем, что используются устройства с произвольным доступом в С имеется возможность открытия файлов для добавления элементов.
Добавление элементов в файл обеспечивается особенностью хранения файловой системы на ВЗУ. Каждый файл размещается в 1 или нескольких кластерах.
Кластер – минимальная логическая единица на ВЗУ, доступная для считывания и записи. Кластер состоит из 1 или нескольких секторов.
Сектор – минимальная физическая единица хранения доступная ЗУ.
Информация о принадлежащих файлу кластерах хранится в специализированном массиве данных, называемом FAT(file allocation table – таблица размещения файлов). Структура FAT такова, что позволяет хранить номера кластеров, принадлежащих файлу (тех, в которых размещается файл) таким образом, что последовательный порядок их размещения не обязателен, т.е. используется связное хранение информации. Для каждого файла хранится № начального кластера. Если файл занимает больше 1 кластера, то в таблице с №-ом кластера в ячейке хранится № следующего кластера. В последнем кластере хранится признак конца файла. Каждый файл имеет имя, список имен и № 1-го кластера файла. Храниться в специальном файле, называемом директория (каталог). Корневой каталог начинается с заданного участка. FAT и её копия хранятся в заданном участке диска.
Поддиректории представляют собой особые файлы внутри каталога. В связи с фиксированным размещением корневого каталога присутствует ограничение на количество файлов в корневом каталоге.
Непоследовательное размещение кластеров в 1 файле приводит к замедлению доступа к файлу, так как требует перепозиционирования считывающих элементов в накопителе, поэтому для таких файловых систем требуется дефрагментация, в ходе которой свободное пространство представляется единым блоком, а кластеры файлов размещаются в строго последовательном порядке.
Программа FAT в современной ОС имеются другие файловые системы NTFS, применяемая WINDOWS NT, 2000, ХР, UNIX (собственная файловая система). Они также основаны на связном хранении информации о кластерах, но структура их сравнения обладает дополнениями, повышающими их надежность, безопасность.
Службы индексирования ускоряют поиск файлов на диске. Будущее файловой системы Longhorn. Следующие идеи будут основаны на идеях БД.
В режиме создания указатель на текущий элемент устанавливается в начало файла. Операция записи файла складывается из 2 действий:
Ø записать элемент;
Ø переместить указатель в позицию следующего элемента.
Открытие файла в режиме просмотра делает доступным для чтения первый элемент файла. Операция чтения складывается из:
o считывания из буфера значения элемента;
o запись на его место значения следующего элемента.
// обычно буфер имеет размер для хранения ряда элементов и обновление происходит после прочтения буфера.
В соответствии с данной моделью просмотра и создания файла последовательного доступа и были определены ограничения над операциями.
Операция закрытия файла обновляет содержимое области действия во внешней памяти, разрывает связь с ней и высвобождает память из-под буферных переменных.
Таким образом, операция просмотра начинается с открытия и заканчивается закрытием файла (используют функции ОС). Обязательно требование о закрытии всех открытых файлов, в противном случае возможна потеря работоспособности ОС, так как все операции с файлами с использованием системной памяти.
Просмотр файла должен выполняться в цикле с предусловием, в котором осуществляется проверка на конец файла. При открытии пустого файла в режиме просмотра состояния флага признака конца флага будет истина. При попытке считывания информации признак конца файла будет потерян, и алгоритм и программа выдадут непредсказуемый результат.
Использование файлов в языка программирования С.
В С предусмотрен форматный ввод/вывод в/из файла и бинарный (двоичный). При использовании формата ввод/вывод обмен с файлом осуществляется также как и со стандартным устройством ввода и вывода, которым соответствуют потоки:
ü stdout (монитор)
ü stdin (клавиатура)
Для доступа к этим устройствам используются функции printf, scanf, gets, puts и так далее. Эти же стандартные устройства могут рассматриваться как файлы с соответствующими именами. Это устройства по умолчанию, поэтому открытия/ закрытия не требуется.
Для открытия файла: fopen
Закрытия: fclose
Доступа: fprintf, fscanf, fgets, fputs …
Отличие от printf, scanf, gets, puts состоит в указании в качестве 1-го параметра при вызове этих функций имени файловой переменной.
В качестве файловых переменных используются указатели на файловую структуру:
FILE*A;
С fopen файл может быть открыт для чтения, записи, добавления. Открытие файла в режиме записи приводит к обнулению файла, которое физически происходит при его закрытии. Файл может быть открыт в текстовом и бинарном режимах.
Для работами с файлами как с последовательностью байт используются функции read, write, open (считывает заданное количество байт из файла, открытого с помощью open )
Форматированный ввод и вывод при открытии open невозможен. Открытие с помощью fopen – открытие на высоком уровне, при этом присутствует ограничение на размещение в файловой системе, связанное с особенностями использования ОС. Открытие на низком уровне (open) таких ограничений не имеет, но не позволяет осуществлять форматированный ввод\вывод.
Директивы препроцессора. Указания компилятора.
Препроцессор С представляет собой макропроцессор, используемый для обработки исходного файла на нулевой фазе компиляции. Компилятор С сам вызывает препроцессор, однако препроцессор может быть вызван автономно.
Препроцессор представляет собой инструкции, записанные в исходном тексте программы на языке С и предназначенные для выполнения препроцессора языка С.
Директива препроцессора обычно используется для облегчения модификации исходных текстов программ и сделать их более независимыми от особенностей различных реализаций компилятора С, разных компьютеров и операционных сред.
Директива препроцессора позволяют лексемы в тексте программы некоторым значением, вставить в исходный файл содержимое другого исходного файла, запретить компиляцию некоторой части исходного файла и т.д.
Пробельные символы допускаются между # и первой буквы директивы.
Некоторые директивы могут содержать аргументы. Директивы могут быть записаны в любом месте исходного файла, но их действие распространяется только от точки программы, в которой они записаны, до конца исходного файла.
Указание к компилятору, или программе, представляют собой инструкции, записанные в исходном тексте программы и предназначенные для управления действиями компиляторами С в определенных ситуациях. Набор указаний компилятору и их смысл различаются для разных реализаций компилятора С.
Именованные константы. Макроопределения.
Директива define используется для замены часто используемых выражений в программе констант, ключевых слов, выражений, осмысленными идентификаторами, которые заменяют числовые и символьные последовательности.
Идентификаторы, представляющие собой последовательность действий, заданной операторами и выражениями С, называют макроопределениями. Они могут иметь аргументы. Обращение к макроопределениям называют макровызовам.
Endif отменяет текущее определение макроконстанты. Замены функции макровызовом повышает скорость вызова функции за счет исключения последующих вызовов, увеличивает размер исходного текста программы.
Существует ряд предопределенных идентификаторов, называемых псевдопеременными: № текущей обрабатываемой строки, время начала компиляции и дата компиляции данного файла.
Директивы управления нумерации строк.
После этого препроцессор присваивает строке № . Данная директива возникла при создании С.
Директива обработки ошибок.
Останавливает выполнение компиляции и выводит сообщение об ошибке (используется при условной компиляции). Пустая директива игнорируется препроцессором для оформления.
Указания компилятору. Синтаксис.
Перекомпиляция файла с заготовкой.
В поздних версиях компилятора с языка С произведена попытка избежать перекомпилирования файла с заголовком. В С принято отдельные функции оформлять в виде объектных модулей, которые используются без перекомпилирования.
В результате компилирования программы тратится время на перекомпилирование основного модуля программы, а также блоки объявлений используемых функций. Когда в компилятор С была включена возможность компилирования С++, файл заголовков функций стал занимать чрезвычайно больший объем по сравнению с программой пользователя. Тогда была введена директива pragma, что позволяет отличить подключаемые файлы как предварительно компилируемые. При 1-ой компиляции будет создан псевдообъектный файл, в который будут записаны заголовки функций. При повторной компиляции он будет сразу считан.
Псевдопеременные.
Каждая такая переменная начинается и заканчивается двойными символами подчеркивания и записывается заглавными буквами.
__LINE__содержит номер текущей строки
__FILE__имя компилируемого исходного файла
__DATE__дата начала компиляции
__TIME__время начала компиляции
Условная компиляция необходима при отладочной печати. Также ifndef позволяет избежать повторного включения файла, чтобы не выполнялся include, в include записывается переменная, обозначается, что данный файл уже включен.
Модели памяти.
Модель памяти определяется при компиляции программистом, либо в среде разработке в соответствующем пункте меню, либо в командной строке с помощью опции – Мх (х – модель памяти: t – крошечная модель: s –малая модель: m –средняя модель).
Модели памяти определяет количество доступной памяти, отводимой под сегмент данных, сегмент кода и стек данных. Модель памяти также определяет способ формирования адреса (вид адресаций), используемый по умолчанию.
t –модель:
память, занимаемая программой имеет объем не более 64 кило байт. Выполнение ограничения в 64 кило байта позволяет исполняемый модуль преобразовать в com-формат.
Com-файлы в отличие от exe-файлов целиком размещаются в 64 кило байтном сегменте. Все адресации выполняются внутри сегмента, и время их загрузки на исполнение в связи с этим минимально. Также использование ближней адресации (внутри сегмента) теоретически увеличивает скорость выполнения программы.
s –модель:
Размер кода и размер данных по 64 кило байта. Общий размер не более 128 кило байт.
Использование h-модели памяти приводит увеличению времени доступа к данным, однако позволяет использовать все доступное пространство оперативной памяти.
Использование в современных ОС так называемой виртуальной памяти позволяет ввести так называемую модель памяти (тип функции). При этом адресация осуществляется по 32-битному адресу, который интерпретируется без дополнительных преобразований.
32-битный fare- адрес вне плоской модели памяти преобразуется в 20-битный адрес, что позволяет организовать 1 Мега байтное адресное пространство, разделенное на 64 К - пересекающихся сегментов.
Пересечение сегментов приводит к тому, что массив не может превышать по размеру 64 кило байта. Использование дополнительных действий в h-модели позволяет объявлять массивы, размером больше 64 Кбайт, но его элементы не могут превышать этот предел. Плоская 32-битная адресация лишена всех этих недостатков.
Для ОС, не поддерживающих виртуальное распределение памяти, применяются так называемые экстендеры. Оболочки для программ, реализующие механизмы виртуальной памяти для каждой программы индивидуально. В этом случае говорят, что программа использует виртуальную модель памяти.
Виртуальное распределение памяти – функция ОС, которая позволяет отображать адресное пространство внешней памяти через область (окно) в оперативной памяти. Если программа запрашивает область памяти, размером, доступным в настоящее время в свободном ОЗУ, то данные программы размещаются в ОЗУ.
Если же размещение данных в ОЗУ невозможно, то то ОС размещает данные на ВЗУ, делает это прозрачным для программы.
В результате в распоряжении программы имеется вся доступная память без разделения на ОЗУ и ВЗУ, в пределах допустимого при 32-битной адресации 4 Гбайтного пространства.
Виртуальный (действительный, реально существующий).
В программировании под этим термином понимается то, что пользователю представляется как действительно существующее, но реализуется с помощью каких-либо дополнительных действий.
Виртуальный – физически не существующий, однако всеми своими характеристиками, соответствующий реальному объекту , то есть не отличим от него или логически существующий.
Механизмы, представляющие виртуальный объект как реально существующий, прозрачны для пользователя. Прозрачное то, результаты чего используются, но сами действия при этом оказываются скрытыми. То есть прозрачный объект существует, но недоступен для пользователя, кроме как через его проявление.
Пример: виртуальная память в ОС WINDOWS. Пользователю доступно до 4 Гбайт. Это реализуется с помощью прозрачного механизма swaping (с помощью файла-подкачки). Многомерный массив виртуален, но прозрачные механизмы индексации позволяют рассматривать двумерный массив как матрицу.
Проектирование интерфейса.
Интерфейс пользователя должен обеспечивать эффективное взаимодействие пользователя и системы.
Дружественный интерфейс, если:
1. Интерфейс должен быть естественным.
2. Интерфейс должен быть последовательным
3. Интерфейс должен быть не избыточен
4. Должна быть поддержка пользователя.
5. Интерфейс должен быть гибкий.
ЕСПД – единая система программной документации (несколько десятков госстандартов, регламентирующих содержание и способ отображения программной документации). Описание программы, применения, руководство программиста, описание контрольного примера