int j,k,K,*I,*I; //k=const
{
int j,k,i[k],I[K],sum=0,pr=1;
for (j=0;j<k;j++)
{
scanf (“%d”,&i[j]);
scanf (“%d”,&I[j]);
}
for (k=1;k<=K;k++)
{
for (j=k+1;j<=K;j++)
{
pr*=I[j];
}
sum+=pr;
}
printf(“%d”,sum);
getch();
}
Структура.
Тип данных, позволяющий объединить в одном объекте совокупность значений разного типа.
Операции:
v Передача в функцию в качестве параметра
v Возврат значения функции
v Получения адреса
v Присваивание в случае совпадения типов левого и правого операндов
struct [тег]
{
Список полей
Тип имя переменной
………….
}
Пример.
struct С
{
float Re;
float Im;
struct C*p;
}x;
При использовании объявления структуры с использованием тега допустимо в дальнейшем объявлять переменные следующим образом
struct С y;
Для доступа к полям используется знак “.”:
x.Re=0.1;
x.Im=0.2;
y=x;
Структуры обычно используются для хранения списков. Списки хранят помимо области данных указатель на саму структуру.
struct (*z);
Тогда доступ к полям z возможен 2 способами
(*z).Re=0.4;
z→Im=-5;
Тег – идентификатор, именующий структуру, которая объявляется списком объявления элементов. Описание специфицирует либо переменную типа struct, либо массив, либо указатель на структуру данного типа, либо объект, являющийся комбинацией вышеперечисленного.
struct С y,*f //объявление функции, возвращающей указатель на структуру с именем С.
Список объявлений – последовательность из одного и более объявлений, либо битовых полей.
Переменная, объявленная в списке объявлений, называется элементом структуры. Объявление переменной в этом списке не может содержать классов памяти инициализатора.
Элемент может иметь 1 из базовых типов или являться структурой, или объединением, или указателем.
Элементом структуры не может быть структура определяемого типа, но может быть указателем на структуру определяемого типа.
Битовые поля.
Используется как тип элементов структуры для осуществления прямого доступа к отдельным битам, а также для экономии памяти.
Синтаксис.
Спецификация типа идентификатор, символ :, константные выражения.
Битовое поле состоит из разрядов, количество которых задается константным выражением, которое должно иметь неотрицательное целое значение. Значение не должно превышать количества разрядов, необходимых для хранения значения специфицируемого типа.
Битовые поля нельзя использовать в массивах, функциях, указателях. Не приминима операция взятия адреса.
Пример.
Определить массив, хранящий информацию о содержимом экрана в текстовом видеорежиме с использованием 25 строк по 80 символов, каждый символ описывается 2 байтами. 1-ый хранит код символа, 2-ой его атрибут.
8 бит атрибутов включают в себя: 4 бита – цвет символа, 3 бита – цвет фона, 1 бит – признак мерцания.
struct screen
{
int sym 8;
int col 4;
int fcol 3;
int blink 1;
}P[25][80];
P[1][1].sym=’-’;
P[1][1].col=15;
P[1][1].fcol=4;
P[1][1].blink=1;
Объединение.
Предназначено для хранения данных разнородной информации в одной и той же области памяти. Например требуется организовать доступ к отдельным байтам числа типа float. С помощью объединения размещаем в 1 области памяти переменную float и массив из 4 символов.
Способ интерпретации содержимого памяти будем определять именем поля.
union
{
int s;
unsigned u;
}a;
a.s=-1 a.s=0
a.u=, n=16 a.u=||a.s||, n – количество разрядов для
a.u=65535 хранения целого числа
Объем памяти для хранения union определяется наибольшим по размеру из элементов. Например, union с полями int, float, double будет занимать sizeof(double)=8 байт. Int занимает младшие 2 байта.
Указатели.
Для выполнения операций с адресами. Указатель –объект для хранения адреса объекта определенного типа. Указатель на функцию содержит указатель на точку входа в функцию (адрес 1 исполняемого оператора тела функции)
Тип *описатель
Объявление указателя специфицирует тип объекта и имя переменной. Базовый, перечислимый, пустой типы, struct, union. Если спецификатор типа опущен, то подразумевается int. Если описатель представлен идентификатором, то он является указателем данного типа. Если описатель представлен более сложной конструкцией, то тип объекта на который ссылается описатель является
char **a адрес переменной типа символ в памяти
Может ссылаться на те же типы struct, union, массив, указатель.
Указатель на пустой тип предназначен для хранения на произв. тип void *p
Для выполнения операций над указателем на void, необходимо привести тип указателя к типу отличному от void.
Занимаемая память.
По умолчанию тип адресации ближний, адрес 2 байта, адресация внутри 64-ого сегмента far. Представлен адресом сегмента и смещением внутри сегмента. В переменной типа указатель хранится адрес, формат которого зависит от используемой вычислительной системы, а также от модели памяти установленной в опциях компилятора.
В компиляторе Borland C возможны 3 вида модификатора адреса позволяющие переопределить формат адреса, устанавливаемый для определенной модели памяти по умолчанию.
Модификатор near (ближний) – занимает 2 байта, позволяет адресовать данные в пределах 64 кило байтного сегмента данных.
Модификатор far(дальний) – занимает 4 байта, адресация внутри сегмента, размер 64 кило байта в пределах Мега байтного адресного пространства, при этом 2-х байтный адрес сегмента и 2-х байтное смещение сегмента преобразуются в 20-ти битный адрес в пределах 1 Мега байта следующим образом: адрес сегмента сдвигается влево на 4 разряда (х16) и к нему добавляется смещение.
Huge (огромный) – способ адресации, при котором возможно адресовать объекты размером больше , чем сегмент(far адресация из-за взаимного пересечения этого делать не позволяет).
32- разрядная адресная шина позволяет адресовать 4Г байта памяти. OC WINDOWS, а также так называемые экстендеры памяти в MS-DOS позволяют использовать так называемую плоскую модель памяти, где 32-битный адрес позволяет обращаться к 4Г-байтному пространству.
Указатель на struct, union или перечислимый тип может быть объявлен до того, как этот тип определен, но не может использоваться до определения.
Константа NULL предназначена для нулевой инициализации указателя. Гарантируется, что никакой элемент никогда не будет иметь адрес NULL(отсутствие адреса).
Huge (огромный) адрес хранится в нормализованном виде, поэтому доступ к huge адресу объекта замедляется за счет дополнительных операций нормализации и денормализации.
Описатели. Интерпретация составных описателей.
Описатель в С позволяет объявить следующие объекты: простые переменные, массивы, указатели, функции.
Описатель представляет собой идентификатор, если объявляется простая переменная базового типа, либо struct, либо union.
Объекту присваивается тип заданный спецификацией типа. Для объявления массива специфицирующего типа функция возвращает значение специфицирующего типа либо указателя на значение специфицирующего типа. Идентификатор добавляется [ ]справа, ( ) справа, или * слева.
Составной описатель – идентификатор, дополненный более чем 1 признаком типа массив, указатель или функция. С 1 идентификатором можно образовать множество различных комбинаций признаков, отдельные комбинации запрещены. Не может содержать функцию, функция не может возвращать массив или функцию.
При интерпретации составных частей описателя сначала рассматривается [ ] ( ), стоящие справа от идентификатора. [ ] и ( )имеют равный приоритет и интерпретируются слева направо. После них справа налево рассматривается *, расположенные слева от идентификатора.
Спецификация типа рассматривается на последнем шаге, после того как описатель полностью интерпретирован. Для изменения действующего по умолчанию порядка интерпретации можно использовать внутри описателя ( ).
Правила интерпретаций составных описателей: «изнутри-наружу».
Начинают с идентификатора, затем проверяют наличие открывающихся [ или (, если они есть, интерпретируется правая часть описателя, затем проверяется наличие * слева, если есть, левая часть.
Если на каком-либо этапе справа встречается ), используемая для изменения порядка интерпретации, то вначале проводится интерпретация описателя внутри данной пары скобок, а затем продолжает рассматриваться справа и слева от скобок.
7 6 4 2 1 3 5
char *(*(*X)( ))[10];
1. Объявить массив из 5 указателей на int
int *Х[5]
2. Объявить указатель на массив из 5 значений int
int (*Х)[5];
3. Функция, возвращающая указатель на значение длинное целое
long int*X()
4. Указатель на функцию
long int (*X)()
5. Массив из 5 указателей на функции, возвращающие struct.
struct (*X[5])();
6. Объявить функцию, возвращающую указатель на массив из 3 значений double. double (*f ()) [3];
Описатели с модификаторами.
В качестве модификаторов следующие ключевые слова:
ü Const
ü Volatile (модифицируемый) interrupt
ü Cdecl
ü Pascal
ü Near
ü Far
ü Huge
Действия определяются обработчиком прерывания.
Интерпретация описателей с модификатором.
Cdecl, pascal , interrupt воздействуют на идентификатор и записываются непосредственно перед ним.
Const, volatile, near, far, huge воздействуют либо на идентификатор, либо на указатель непосредственно слева от идентификатора.
Если справа идентификатор, то модифицируется тип объекта, именуемого идентификатором. Если справа указатель, то есть указатель не модифицируемый тип.
Например.
int const*p; p – указатель на постоянное целое
int *const p1; p1 – неизменный указатель на целое
Скобки могут предопределять порядок модификаторов
char far*(far * get int )( int far*);
get int – указатель на far- функцию, требующую 1 аргумент, который является указателем на far – значение типа int и возвращающую указатель на far – значение типа char.
Для доступа к нему требуется 4-байтовый адрес.
Const – не допускает явного присваивания значения переменной либо других косвенных действий по изменению ее значения (инкремент, декремент). Значение указателя с модификатором const изменено быть не может, но может изменяться объект на который указывает. Применение const позволяет выявить нежелательные присваивания значений переменных.
Volatile - показывает, что значение переменной может быть изменено, но не только программой, а также и внешним воздействием (программа обработчиком прерыванием), либо, если переменная соответствует порту ввода/вывода: обменом с ВУ.
Объявление объекта с volatile предупреждает компилятор языка С, что не следует делать предположений относительно стабильности значения объекта в момент вычисления содержащего его выражения, т.к. значение может изменяться в любой момент. Такие volatile-объекты не подвергаются оптимизации, их значения не запускаются в машинные регистры.
Возможно одновременное использование const, volatile. Это означает, что внутри программы объект изменяться не может, но может подвергаться внешним воздействиям.
volatile int ticks;
void interrupt timer() //таймер-функция ничего не возвращающая; обработчик прерывания
{
ticks++;
}
void wait (int interval)
{
ticks =0
while (ticks< interval)
}
Будет ждать в течение времени заданного параметром интервал, в т.0 если функция таймер будет корректно связана с аппаратным прерыванием от таймера.
Если ticks объявить без volatile , то компилятор с высоким уровнем оптимизирующих преобразований, сравнений ticks и interval вынес бы за пределы цикла, т.к. в теле цикла их значения не изменяются, что привело бы к зацикливанию программы.
Запрос на прерывания: от аппаратуры, программный.
Прерывание генерируется, если на линии запроса устанавливается соответствующий сигнал (операция ввода/вывода, запрос на следующую порция данных для принтера)
Для вызова обработчика прерывания программист может установить программный запрос на прерывание. Все функции MS-DOS через механизмы прерывания.