Директивы условной компиляции # if , # else , # elif , # endif , # ifdef , # ifndef . 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Директивы условной компиляции # if , # else , # elif , # endif , # ifdef , # ifndef .



#if, #ifdef, #ifndef применяются для исключения компиляции отдельных частей программы. Это бывает полезно при отладке или при поддержки нескольких версий программы для различных платформ.

 

Формат директивы #if:

 

       #if константное_выражение

       …

       [#elif константное_выражение…]

       [#elif константное_выражение…]

       [#else …]

       #endif

 

Директива #if вместе с директивами #elif, #else и #endiif управляет компиляцией частей исходного файла. Каждой директиве #if в исходном файле должна соответствовать закрывающая директива #endif.Между директивами #if и #endif допускается нуль или более директив #elif и не более одной директивы #else. Директива #else, если она есть, должна быть расположена непосредственно перед директивой #endif.

 

Синтаксис директив #ifdef и #ifndef:

 

       #ifdef [определитель]

       #ifndef [определитель]

 

Директивы #ifdef и #ifndef выполняют те же самые задачи, что и директива #if, использующая defined ([определитель]). Эти директивы могут быть использованы там же, где используется директива #if, и используются исключительно для компактности записи.

 

Когда препроцессор обрабатывает директиву ifdef, то делается проверка идентификатора [определитель] на истинность (не нуль).

 

Директива #ifdef является отрицанием директивы #ifdef. Другими словами, если [определитель] не определен (или его определение отменено директивой #undef), то его значение истинно (не нуль). В противном случае значение ложно (нуль).


 

Понятие структуры. Доступ к членам структуры.

Cтруктуры – это составной объект, в который входят элементы любых типов, за исключением функций. В отличие от массива, который является однородным объектом, структура может быть неоднородной.

Тип структуры определяется записью вида:

               struct { список определений };

В структуре обязательно должен быть указан хотя бы один компонент. Определение структур имеет

следующий вид:

               тип-данных описатель;

где тип-данных указывает тип структуры для объектов, определяемых в описателях. В простейшей форме описатели представляют собой идентификаторы или массивы.

Пример:

               struct { double x,y; } s1, s2;

               struct { int year; char moth, day; } date1, date2;

Переменные s1, s2 определяются как структуры, каждая из которых состоит из двух компонент х и у. Каждая из двух переменных date1, date2 состоит из трех компонентов year, moth, day. Существует и другой способ ассоциирования имени с типом структуры, он основан на использовании тега структуры. Тег структуры аналогичен тегу перечислимого типа. Тег структуры определяется следующим образом:

               struct тег { список описаний; };

где тег является идентификатором.

В приведенном ниже примере идентификатор student описывается как тег структуры:

struct student { char name[25];

                                                                             int id, year_of_birth;

                                                                             char grp; };

Объявление структурного типа обязательно заканчивается;.                                                                 

Тег структуры используется для последующего объявления структур данного вида в форме:

               struct тег список-идентификаторов;

Пример:

               struct studeut st1,st2;

                   

Использование тегов структуры необходимо для описания рекурсивных структур. Ниже рассматривается использование рекурсивных тегов структуры.

               struct node { int data;

                                                                            struct node * next; } st1_node;

                                                         

Тег структуры node действительно является рекурсивным, так как он используется в своем собственном описании, т.е. в формализации указателя next. Структуры не могут быть прямо рекурсивными, т.е. структура node не может содержать компоненту, являющуюся структурой node, но любая структура может иметь компоненту, являющуюся указателем на свой тип, как и сделано в приведенном примере.

Значения элементов структур могут определяться вводом, присваиванием или инициализацией.

Пример инициализации структуры:

student stud1={"Васильков",1,1992,"ПО711"};

Доступ к членам структуры

Доступ к отдельному элементу структуры осуществляется посредством конструкции вида:

               имя-структуры.элемент

Оператор доступа к элементу структуры. соединяет имя структуры и имя элемента.

Пусть объявлена структура, содержащая информацию о координатах точки:

struct {int x;

                                                        int y} pt;

Чтобы напечатать, например, координаты точки pt, используется следующее обращение к printf:

               printf("%d, %d", pt.x, pt.y);           

Пример обращения к элементам сруктуры student, описанной в предыдущем пункте:

               st1.name="Иванов";

               st2.id=st1.id;

               st1_node.data=st1.year_of_birth;


 

Присваивание структур.

Если тип двух программных объектов одинаков    , то один объект можно присвоить другому.

По умолчанию, когда один объект присваивается другому, делается поразрядная копия всех

данных-членов копируемого объекта. Например, когда структура var1 присваивается структуре

var2. То содержимое всех полей структуры var1 копируется в соответствующие поля структуры

var2. Это иллюстрируется следующим программным кодом:

#include

#include

struct ex_struct//объявили структурный тип

{int a;

int b;};

void main(){

//объявляем переменную структурного типа и присваиваем ее полям занчение 5

ex_struct var1={5,5};

// объявляем переменную структурного типа

ex_struct var2;

//выводим на экран значение переменной var1

printf("\nvar1.a=%d var1.b=%d",var1.a,var1.b);// на экран выведется var1.a=5 var1.b=5

//присваиваем переменной var2 var1

var2=var1;

//выводим на экран значение переменной var2

printf("\nvar2.a=%d var2.b=%d",var2.a,var2.b); // на экран выведется var2.a=5 var2.b=5

//присваиваем полю a переменной var2 значение 6

var2.a=6;

//выводим на экран значения переменных var1 и var2.

printf("\nvar1.a=%d var1.b=%d",var1.a,var1.b); // на экран выведется var1.a=5 var1.b=5

printf("\nvar2.a=%d var2.b=%d",var2.a,var2.b); // на экран выведется var2.a=6 var2.b=5

}

Таким образом после выполнения операции присваивания два объекта остаются независимыми.

На пример изменение поля a переменной var1 не влияет на переменную var2.

Однако при присваивании объектов друг другу необходимо быть очень внимательным.

Рассмотрим несколько измененный структурный тип ex_str

struct ex_str //объявили структурный тип

{int *a;// теперь поле a – указатель на переменную целого типа типа

int b;};

void main(){

 ex_str var1,var2; //объявили две переменные структурного типа

//инициализируем значения переменной var1

var1.a=(int*)calloc(1,sizeof(int));// выделили память под переменную целого типа

*(var1.a)=5;//присвоили по адресу var1.a значение 5

var1.b=5; // присвоили полю b значение 5.

// выводим на экран значение переменной var1

printf("\n*(var1.a)=%d var1.b=%d",*(var1.a),var1.b);// на экран выведется var1.a=5 var1.b=5

//присваиваем переменной var2 var1

var2=var1;

//выводим на экран значение переменной var2

printf("\n*(var2.a)=%d var2.b=%d",*(var2.a),var2.b);// на экран выведется var2.a=5 var2.b=5

//присваиваем по адресу var2.a значение 6

*(var2.a)=6;

//выводим на экран значения переменных var1 и var2.

printf("\n*(var1.a)=%d var1.b=%d",*(var1.a),var1.b);// на экран выведется var1.a=6 var1.b=5

printf("\n*(var2.a)=%d var2.b=%d",*(var2.a),var2.b);// на экран выведется var2.a=6 var2.b=5

}

Ошибка в этой программе весьма коварна. Когда создаются структурные переменные var1 и var2, то для хранения значения по адресу должна выделяться память. Указатель на выделенную каждому полю память хранится в поле a. Однако когда переменная var1 присваивается переменной var2, то указатель a переменной var1 и указатель a переменной var2 указывает на одну и туже область памяти. Внутреннее представление в памяти переменных var1 и var2 после выполнения операции присваивания проиллюстрировано на рисунке.

Рисунок 9.3.1 Внутреннее представление в памяти переменных var1 и var2 после выполнения операции присваивания.


 

39. Массивы структур.

Рассмотрим программу, определяющую число вхождений каждого ключевого слова в текст С-программы. Нам нужно уметь хранить ключевые слова в виде массива строк и счетчики ключевых слов в виде массива целых. Один из возможных вариантов –это иметь два параллельных массива:

               char *keyword[NKEYS];

               int keycount[NKEYS];

Однако именно тот факт, что они параллельны, подсказывает нам другую организацию хранения – через массив структур. Каждое ключевое слово можно описать парой характеристик

               char *word;

               int count;

Такие пары составляют массив. Объявление 

struct key {

                                                                            char *word;

                                                                            int count;

                                                                            } keytab[NKEYS];

                                                                                

объявляет структуру типа key и определяет массив keytab, каждый элемент которого является структурой этого типа и которому где-то будет выделена память. Это же можно записать и по-другому:

               struct key {

                                                                            char *word;

                                                                            int count;

                                                        };

               struct key keytab[NKEYS];

                   

Так как keytab содержит постоянный набор имен, его легче всего сделать внешним массивом и инициализировать один раз в момент определения. Инициализация структур аналогична ранее демонстрировавшимся инициализациям – за определением следует список инициализаторов, заключенный в фигурные скобки:

               struct key {

                                                        char *word;

                                                        int count;

                                    } keytab[] = {

                                                                                                 "auto", 0,

                                                                                                 "break", 0,

                                                                                                 "case", 0,

                                                                                                 "char", 0,

                                                                                                 "const", 0,

                                                                                                 "continue", 0,

                                                                                                 "default", 0,

                                                                                                 /*...*/

                                                                                                 "unsigned", 0,

                                                                                                 "void", 0,

                                                                                                 "volatile", 0,

                                                                                                 "while", 0

                                                                                                 };

                                                                                                                                          

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

               { "auto", 0 },

               { "break", 0 },

               { "case", 0 },

                                   ...

                                        

Однако когда инициализаторы - простые константы или строки символов и все они имеются в наличии, во внутренних скобках нет необходимости. Число элементов массива keytab будет вычислено по количеству инициализаторов, поскольку они представлены полностью, а внутри квадратных скобок "[]" ничего не задано.


 



Поделиться:


Последнее изменение этой страницы: 2021-08-16; просмотров: 48; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.218.55.14 (0.035 с.)