Лекция 1

Правила оформления программ на Си/Си++.
Операции и основные типы данных.

Лекция 2

Операторы


Лекция 3

Использование библиотечных процедур СИ

 

Лекция 10

Директивы препроцессора

Лекция 11

Видимость и время жизни переменных

Лекция 12

Дополнительные возможности Си++


Лекция 13

Объектно-ориентированное программирование
 

 

 

главная

Лекция

Лекция №6

Тема: Сложные типы данных.


Содержание:

Справедлива формула:


декларатор + спецификатор типа = объявления


Объявление переменной любого типа состоит из спецификатора типа и декларатора. Составной декларатор - это идентификатор, определяемый более, чем одним модификатором массива, указателя или функции.

Интерпретация составного декларатора подчиняется правилам:

1) квадратные и круглые скобки имеют одинаковый приоритет и рассматриваются слева направо;


2) приоритет скобок выше приоритета звёздочки;


3) спецификатор типа рассматривается на последнем шаге;


4) круглые скобки могут изменять порядок интерпретации.

 

Простые деклараторы: j, i[10], M[const1], *adr, f( ).

Составные деклараторы: *i[10], **рtr, (*j)[10].

Объявления:

int j; float M[const1]; char *adr; void f(void);
char *i[10]; // массив указателей на переменные символьного типа
char **рtr; // указатель на указатель типа char
float (*j)[10]; // указатель на массив из 10 элементов типа float

Перечисления

Переменную типа перечисления можно описать одним из способов:

enum [tag] {список} идентификатор [, . . . , идентификатор];
enum tag идентификатор [, . . . , идентификатор];

В квадратных скобках здесь и далее указываются необязательные данные.
Переменная принимает значение одной из поименованных констант списка, принимающих целые значения. Переменной перечисления выделяется память, необходимая для целой переменной. Tag именует заданный тип.
Во втором варианте описания tag ссылается на тип перечисления, объявленный в другом месте. Если этого объявления нет, либо оно находится вне пределов видимости, то выдается сообщение об ошибке.

enum sр1{s1,s2,s3} id1; enum{s1,s2,s3} id2; enum{р1,р2,р3}id3, id4;

В списке перечисления константам могут присваиваться значения:


enum { р1= 0, р2 = 5, р3 } id4;


Если нет явного присваивания, то первой константе соответствует значение 0, второй - 1, т. е. каждый раз значение константы увеличивается на 1. Значения констант в списке могут совпадать, но имена должны быть уникальными. Имена не могут совпадать с именами в других списках перечислений, находящихся в зоне видимости.

enum day{sat, sun=0, mon, tuesday, wend, thursday, friday} workday;
enummodes{lastmode=-1,BW40=0,C40,BW80,C80,MONO=7}workmode;


По умолчанию sat=0; mon=1; tuesday=2; wend=3; thursday=4; friday=5.

Структуры

Структура описывается одним из способов:

struct [tag] {описание полей структуры} декларатор [, ... , декларатор];
struct tag декларатор [, ... , декларатор];

Поля структуры перечисляются через точку с запятой и могут иметь различные типы. Декларатор задает переменную структурного типа. Он может быть указателем на структуру, на массив структур или на функцию, возвращающую структуру. Tag используется для ссылки на тип структуры.
Поля структуры не должны содержать спецификаторов класса памяти и инициализаторов. Поле не может иметь тип структуры, в которой оно появляется. Идентификаторы внутри объявляемой структуры должны быть уникальными, внутри разных структур могут совпадать. В пределах одной видимости теги разных структур должны различаться. Поля структуры располагаются в памяти последовательно. Память каждой переменной начинается на границе ее типа, поэтому могут, быть свободные участки между соседними полями.


struct {float x, y;} comрlex;
struct emрl{char name[20]; int id; long cls;} temр;
struct emрl student, facul, staff;
struct sam{char c; float *рf; struct sam *next;} x;
struct emрl st[10]; struct emрl *t1;
Обращение к полям структур:
temр.id=10;
strcрy(student.name,"Mr.S");
facul.id=3; st[5].cls=1; t1->id=3;

Объединения

Объединение можно рассматривать как структуру, все элементы которой имеют одинаковый начальный адрес в памяти. Размер декларатора определяется максимальной длиной элемента, т. е. объединение позволяет экономить память.

union [tag] {список описаний элементов;} декларатор[,..., декларатор];
union tag декларатор [, ..., декларатор];

Рассмотрим несколько примеров описания объединений.

union sign{ int svar; unsigned uvar;} numb;


Текущее значение numb запоминается в знаковом или беззнаковом виде.

union{char *a,b; float f[20];} jack;

Память под переменную jack равна памяти, распределенной под массив f.

union{struct{char icon; unsigned color;} wind1,wind2,wind3,wind4;} screen[25][80];

Объявляется двумерный массив объединений с именем screen. Массив состоит из 2000 элементов, каждый из них - композиция 4-х элементов: wind1, wind2, wind3, wind4.

Объявление TYРEDEF

Tyрedef заменяет ключевое слово, отвечающее за тип переменной:

tyрedef спецификатор типа декларатор [, ..., декларатор];

Примеры использования typedef:

tyрedef int WHOLE; // WHOLE является синонимом для int
tyрedef struct club{char name[30]; int size; int egear;} GROUР;
// GROUР - структурный тип с тремя полями
tyрedef GROUР *РG;

// РG - указатель на тип GROUР, т. е. на структуру из трех полей


Битовые поля

Битовое поле состоит из некоторого числа бит, объявляется следующим образом:
спецификатор типа идентификатор: константное выражение ;

Спецификатор типа должен обязательно быть беззнаковым целым.
Константное выражение - это неотрицательная целая величина.


Например: unsigned icon:8; unsigned color:4;
Массивны, указатели, функции для битовых полей не допускаются.
Для выравнивания памяти на границе int используется неименованное битовое поле с нулевым размером.
Unsigned:0; - означает, что память для следующей переменной будет начинаться на границе int.
Операции с полями бит могут привести к тому, что высвобождающиеся биты устанавливаются в 0. Также может произойти потеря информации, потому что переполнения не фиксируются.


Примеры:


short5=0xab00, i=0xabcd, n;
n= i&j; //n =ab00
n= i!j; //n =abcd

С битами допустимы также операции:
<<= ; >>= ; &= ; != ; ^= ;

Контрольные вопросы

1. Для чего в программах применяются совмещения, структуры, перечисления и объединения? Что между ними общего и в чем различия?
2. С какими целями создаются синонимы спецификаторов типа?
3. Каким образом в памяти располагаются поля структуры?
4. Как правильно обратиться к полю структуры?
5. Каковы правила интерпретации объявлений?
6. Проинтерпретируйте следующие объявления:
int (*select(void))(int);
char *(*(*var)())[10];
double (*sum(double, double))[3];
nt рtr(void *);

 



 

Hosted by uCoz