КИТ и Э КБГУ Понедельник, 06.05.2024, 22:18
Приветствую Вас Гость | RSS
Меню сайта

Наш опрос
Оцените мой сайт
Всего ответов: 118

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Препроцессор

  1. Константы
  2. Препроцессорные директивы: #include, #define, #undef, #if -#else -#endif
  3. Макроопределения с параметрами
  4. Правила оформления деклараций

     Практическая работа. Программирование ввода-вывода с использованием директив #if, #ifdef, #ifndef.

Перечислимые константы

Символические имена, указанные в описании перечисления (нумератора)

enum bool { no, yes };

трактуются как целые константы (этот тип будет рассмотрен позже).

Поименованные константы

С помощью директивы препроцесора  #define можно определить символические имена для констант любого типа эти имена по традиции записываются прописными буквами:

#define MAXBUF81

#define ESC0x1B

#define PI3.14159

#define MSG"Press any key to continue\n"

В процессе обработки текста программы препроцессор заменяет каждое вхождение символического имени соответствующей константой.

Определения такого типа часто используют для введения констант - параметров реализации.

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

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

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

Эти директивы не являются частью языка программирования.

Каждая директива начинается с символа #и заканчивается символом новой строки.

Точка с запятой (;) в конце директивы не применяется.

 

Директива #include

Директива #include-включение файла

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

#include "имя_файла"

или

#include <имя_файла>

Вместо директивы #includeв текст программы включается содержимое указанного файла.

При использовании первой формы оператора поиск файла осуществляется в текущем каталоге, а затем, если он там не обнаружен -в других "стандартных" каталогах.

Пример:

#include "student.h"

При второй форме оператора поиск файла производится сразу в "стандартных" каталогах, а текущий каталог просматриваться не будет.

Пример:

#include <stdio.h>

Включаемые файлы в свою очередь могут содержать директивы #include.

 

Директива #define

Директива #define–макроопределение (макроподстановка)

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

#define идентификатор подстановка

#define идентификатор (формальные_аргументы) подстановка

Директива предписывает всюду в тексте программы, начиная с текущей точки и до конца файла или до директивы #undef, выполнять замену указанного идентификатора на сопоставленную ему цепочку символов (подстановку).

Часто процесс подстановки называется макрорасширением.

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

В определении такой параметрической макроподстановки между идентификатором и открывающей круглой скобкой не должно быть пробелов.

Примеры:

#define MAXLEN 128

#define MAX(x,y) ( (x)>(y) ? (x) : (y) )

 

Длинная цепочка-подстановка может быть продолжена на следующей строке, для этого в конце строки, имеющей продолжение, ставится символ \.

После выполнения текущей макроподстановки получившаяся строка вновь просматривается на предмет возможных макроподстановок.

Макроподстановка, заданная директивой #define, не будет выполняться, если встретившийся идентификатор является частью символической константы или строки символов, заключенной в двойные кавычки или угловые скобки.

В С принято записывать идентификатор, определяемый директивой #define, прописными буквами, это является напоминанием, что будет выполняться макроподстановка.

Язык С содержит предопределенные макроимена, которые не допускается использовать в директиве #define, их обозначения начинаются и заканчиваются двумя символами подчеркивания:

__STDC__-имеет значение 1, если компиляция выполняется в режиме

совместимости с ANSI-стандартом, в противном случае является неопределенным;

__FILE__-литерал -имя текущего обрабатываемого компилятором файла;

__LINE__-номер текущей обрабатываемой компилятором строки файла;

__DATE__-дата начала обработки текущего файла -литерал в форматеmmm dd yyyy;

__TIME__-время начала обработки текущего файла в формате hh:mm:ss.

 

В цепочке-подстановке можно использовать символы ##с необязательным пробелом с каждой стороны, это приводит к "склеиванию" элементов при макроподстановке. Такое свойство применяется для конструирования имен, например, макроопределение

#define VAR(i,j) i##j

вызовет в тексте программы замену выражения VAR(x,6)на x6.

Одинарный символ #перед макроаргументом в цепочке-подстановке вызывает преобразование фактического аргумента в символьную строку, например, макроопределение

#define TRACE(flag) printf(#flag "=%d\n",flag)

приведет в тексте программы

val = 1024; TRACE(val);

к такой последовательности замен:

TRACE(val) превратится вначале в printf("val" "=%d\n",val);

и затем, после конкатенации двух строк, окончательно получится

printf("val=%d\n",val);

 

Пример:

#include <stdio.h>

#define A(b) #b

int main() {

  printf("%s", A("a"*"b"));

  return 0;

}

Ответ: "a"*"b"

 

Директива #undef

Директива #undef-отмена макроопределения

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

#undef идентификатор

Эта директива отменяет определение указанного идентификатора, он будет считаться неопределенным и более не подлежащим замене.

Примеры:

#undef MAXLEN

#undef MAX

 

Пример:

#include <stdio.h>

#define A 1

#define B

#ifdef A

int Print1() {

   printf("A1");

   return 0;

}

#ifndef B

float Print1() {

  printf("B1");

  return 0.0;

}

#else

void Print2()

{   printf("B2"); }

#endif

void Print3()

{  printf("AB"); }

#else

void Print2()

{   printf("A2"); }

void Print3()

 { printf("BA"); }

#endif

int main(void) {

   Print1();

   Print2(); 

   Print3();

   return 0; }                                                                    

  Ответ:  A1B2AB

Директивы условной компиляции

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

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

              #ifdef идентификатор

              #ifndef идентификатор

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

  •              
  •              

     Эти директивы обеспечивают компиляцию тех или иных участков программного кода в зависимости от выполнения некоторых условий.

     Для проверки условия применяется одна из первых трех директив, проверяющих истинно ли (==1) константное_выражение (#if), определен (#ifdef) или не определен (#ifndef) указанный идентификатор.

     Если условие выполнено, то компилируются операторы программы, расположенные вслед за проверяющей директивой вплоть до встречи одной из оставшихся трех директив.

     Если условие не выполнено, то эта часть программы игнорируется.

     Необязательная директива #else вводит альтернативную ветвь программы, которая будет компилироваться, если не выполнено условие в непосредственно предшествующей ей проверяющей директиве.

     Необязательная директива #elif эквивалентна последовательности следующих одна за другой директив #elseи #ifи применяется для организации множественного ветвления.

     Директива #endif отмечает конец участка условной компиляции, начатого одной из первых трех директив проверки.

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

     Язык С позволяет использовать в константном выражении специальную операцию

     defined (идентификатор)

     которая принимает значение 1 (истина), если идентификатор определен, и 0 (ложь) - в противном случае.

     Таким образом, директива

     #if defined(symbol)

  •     

     #ifdef symbol

     Операция defined позволяет организовать сложные проверки, например:

     #if defined(symbol1) || defined(symbol2)

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

 

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

Директивы условной компиляции также применяются для защиты заголовочных файлов (хедер-файлов, .h-файлов) от повторного включения (от повторной загрузки)

     Пример:

     Для защиты файла student.h в него следует включить директивы

#ifndef STUDENT_H

#define STUDENT_H

// содержимое файла

#endif

     Вместо директивы

#ifndef STUDENT_H

можно использовать

#if !defined(STUDENT_H)

 

Прочие директивы

  1. Директива #line

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

#line номер_строки

#line номер_строки имя_файла

Эта директива предписывает заменить значения предопределенных макроимен __LINE__и __FILE__на указанные значения.

  1. Директива #error

Формат директивы: #error сообщение

Директива предписывает прекратить процесс компиляции с выдачей сообщения следующего вида:

Fatal: имя_файла номер_строки Error directive: сообщение

     Используется для целей отладки, например,

#if (VAL != 0 && VAL != 1)

#error VAL must be defined to either 0 or 1

#endif

 

  1. Директива #pragma

Формат директивы: #pragma инструкция

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

 

Вход на сайт

Поиск

Календарь
«  Май 2024  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
2728293031

Архив записей

Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz

  • Copyright Fatima_Zh © 2024Бесплатный хостинг uCoz