46010 (Препроцессор языка C.), страница 2

2016-07-31СтудИзба

Описание файла

Документ из архива "Препроцессор языка C.", который расположен в категории "". Всё это находится в предмете "информатика" из , которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "рефераты, доклады и презентации", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "46010"

Текст 2 страницы из документа "46010"

Обычно это достигается путем заключения в условие всего содержимого

этого файла, как показано ниже:

#ifndef FILE_FOO_SEEN

#define FILE_FOO_SEEN

Сам файл

#endif /* FILE_FOO_SEEN */

Макрос 'FILE_FOO_SEEN' указывает на то, что файл уже однажды вкючался.

В подключаемых файлах пользователя макрос не должен начинаться с символа

'_'. В системных подключаемых файлах его имя не должно начинаться с символа

'__' во избежание возникновения конфликтов с программами пользователя. Каким

бы ни был файл, имя макроса должно содержать имя файла и некоторый

дополнительный текст во избежание вознкновения конфликтов с другими

подключаемыми файлами.

Препроцессор GNU C построен таким образом, что обработке подключаемого

файла он проверяет наличие определенных конструкций и наиболее рационально

их обрабатывает. Препроцессор специально отмечает полное вложение файла в

условие '#ifndef'. Если в подключаемом файле содержится директива '#include',

указывающая на обрабатываемый файл, или макрос в директиве '#ifndef' уже

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

Существует также специальная директива, указывающая препроцессору, что

файл должен быть включен не более одного раза. Эта директива называется

'#pragma once'. Она использовалась в дополнение к директиве '#ifndef' и

в настоящее время она устарела и не должна прменяться.

В объектно ориентированном языке С существует модификация директивы

'#include', называемая '#import', которая используется для вкючения файла

не более одного раза. При использовании директивы '#import' вместо

'#include' не требуется наличия условных оборотов для предотвращения

многократной обработки файла.

3.5. Подключаемые файлы и наследование

"Наследование" это то, что происходит, когда какой либо объект или

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

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

наследование означает, что один файл включает другой файл, а затем заменяет

или добавляет что-либо.

Если наследуемый подключаемый файл и основной подключаемый файл имеют

различные имена, то такое наследование называется прямым. При этом

используется конструкция '#include "BASE"' в наследуемом файле.

Иногда необходимо чтобы у наследуемого и основного подключаемого файла

были одинаковые имена.

Например, предположим, что прикладная программа использует системный

подключаемый файл 'sys/signal.h', но версия файла '/usr/include/sys/signal.h'

на данной системе выполняет того, что требуется в прикладной программе.

Будет удобнее определить локальную версию, возможно с именем

'/usr/local/include/sys/signal.h' для замены или добавления к версии,

поставляемой с системой.

Это можно выполнить с применением опции '-I.' при компиляции, а также

созданием файла 'sys/signal.h' который выполняет требуемые программе функции.

Но сделать так, чтобы этот файл включал стандартный файл 'sys/signal.h' не

так просто. При включении строки '#include ' в этот файл

произойдет подключение новой версии файла, а не стандартной системной версии.

Это приведет к рекурсии и ошибке при компиляции.

При использовании директивы `#include '

нужный файл будет найден, но этот способ является не эфективным, так как

содержит полный путь к системному файлу. Это может отразиться на содержании

системы, так как это означает, что любые изменения местоположения системных

файлов потребуют дополнительных изменений где-либо еще.

Более эффективным решением этой проблемы является применение директивы

'#include_next', которая используется для подключения следующего файла с

таким же именем. Эта директива функционирует также как и директива '#include'

за исключением поиска требуемого файла. Она начинает поиск списка каталогов

подключаемых файлов после каталога, где был найден текущий файл.

Предположим была указана опция '-I /usr/local/include', а список

каталогов для поиска включает '/usr/include'. Также предположим, что оба

каталога содержат файл с именем 'sys/signal.h'. Директива

'#include ' найдет нужный файл под каталогом

'/usr/local/include'. Если этот файл содержит строку

'#include_next ', то поиск будет возобновлен после предыдущего

каталога и будет найден файл в каталоге '/usr/include'.

4. Макросы

Макрос это тип сокращения, который можно заранее определить и

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

с использованием макросов в С препроцессоре.

4.1. Простые макросы

"Простой макрос" это тип сокращения. Это идентификатор, который

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

Перед использованием макроса его необходимо определить с помощью

директивы '#define', за которой следует название макроса и фрагмент кода,

который будет идентифицировать этот макрос. Например,

#define BUFFER_SIZE 1020

определяет макрос с именем 'BUFFER_SIZE', которому соответствует текст

'1024'. Если где-либо после этой директивы встретится выражение в следующей

форме:

foo = (char *) xmalloc (BUFFER_SIZE);

то С препроцессор определит и заменит макрос 'BUFFER_SIZE' на его значение и

в результате получится

foo = (char *) xmalloc (1020);

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

соглашением и повышает читабельность программ.

Обычно, макроопределением должна быть отдельная строка, как и при

использовании всех директив препроцессора. (Длинное макроопределение можно

разбить на несколько строк с применением последовательности

backslash-newline.) Хотя существует одно исключение: символы перевода

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

или символьной константе, потому как макроопределение не может содержать

каких-либо специальных символов. Макроопределение автоматически дополняется

соответствующим специальным символом, который завершает строчную или

символьную константу. Комментарии в макроопределениях могут содержать символы

перевода строки, так как это ни на что не влияет, потому как все комментарии

полностью заменяются пробелами вне зависимости от того, что они содержат.

В отличие от выше сказанного, не существует никаких ограничений на

значение макроса. Скобки не обязательно должны закрываться. Тело макроса не

обязательно должно содержать правильный С код.

Препроцессор С обрабатывает программу последовательно, поэтому

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

Поэтому, после обработки следующих данных С препроцессором

foo = X;

#define X 4

bar = X;

получится такой результат

foo = X;

bar = 4;

После подстановки препроцессором имени макроса, тело макроопределения

добавляется к началу оставшихся вводимых данных и происходит проверка на

продолжение вызовов макросов. Поэтому тело макроса может содержать ссылки

на другие макросы. Например, после выполнения

#define BUFSIZE 1020

#define TABLESIZE BUFSIZE

значением макроса 'TABLESIZE' станет в результате значение '1020'.

Это не является тем же, что и определение макроса 'TABLESIZE' равным

значению '1020'. Директива '#define' для макроса 'TABLESIZE' использует в

точности те данные, которые были указаны в ее теле и заменяет макрос

'BUFSIZE' на его значение.

4.2. Макросы с аргументами

Значение простого макроса всегда одно и то же при каждом его

использовании. Макросы могут быть более гибкими, если они принимают

аргументы. Аргументами являются фрагменты кода, которые прилагаются при

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

в соответствии с указаниями в макроопределении.

Для определения макроса, использующего аргументы, применяется директива

'#define' со списком имен аргументов в скобках после имени макроса. Именами

аргументов могут быть любые правильные С идентификаторы, разделенные запятыми

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

имени макроса без каких-либо пробелов.

Например, для вычисления минимального значения из двух заданных можно

использовать следующий макрос:

#define min(X, Y) ((X) < (Y) ? (X) : (Y))

Для применения макроса с аргументами нужно указать имя макроса, за

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

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

указываемых. Например, макрос 'min' можно использовать так: 'min (1, 2)' или

'min (x + 28, *p)'.

Значение макроса зависит от используемых аргументов. Каждое имя

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

указанных аргументов. При использовании макроса 'min', рассмотренного ранее,

следующим образом:

min (1, 2)

будет получен следующий результат:

((1) < (2) ? (1) : (2))

где '1' заменяет 'X', а '2' заменяет 'Y'.

При указании аргументов, скобки должны закрываться, а запятая не должна

завершать аргумент. Однако, не существует каких либо ограничений на

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

macro (array[x = y, x + 1])

передает макросу 'macro' два аргумента: 'array[x = y' и 'x + 1]'.

После подстановки указанных аргументов в тело макроса, полученный в

результате текст добавляется к началу оставшихся данных и производится

проверка на наличие других вызовов макросов. Поэтому указываемые аргументы

могут содержать ссылки к другим макросам как с аргументами, так и без, а

также к тому же макросу. Тело макроса также может включать ссылки к другим

макросам. Например, макрос 'min (min (a, b), c)' заменяется следующим

текстом:

((((a) < (b) ? (a) : (b))) < (c)

? (((a) < (b) ? (a) : (b)))

: (c))

(Срока разбита на три для ясности и в действительности она не разбивается.)

Если макрос 'foo' принимает один аргумент и нужно передать ему пустой

аргумент, то в скобках следует указать по крайней мере один пробел:

'foo ( )'. Если пробел не указывать, а макрос 'foo' требует один аргумент,

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

использовать конструкцию 'foo0()' как рассмотрено ниже:

#define foo0() ...

Если используется имя макроса, за которым не следует открывающаяся

скобка (после удаления всех следующих пробелов, символов табуляции и

комментариев), то это не является вызовом макроса и препроцессор не изменяет

текст программы. Поэтому возможно использование макроса, переменной и функции

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

(если за именем следует список аргументов), а когда - переменную или функцию

(если список аргументов отстутствует).

Подобное двойственное использование одного имени может привести к

осложнениям и его следует избегать, за исключением случаев, когда оба

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

функция и макрос и оба выполняют одинаковые действия. Можно рассматривать

это имя как имя функции. Использование имени не для ссылки (например, для

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

к замене имени на значение макроса и в результате будет получен более

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

'min' в том же исходном файле, где определен макрос с тем же именем.

Если написать '&min' без списка аргументов, то это приведет к вызову функции.

Если же написать 'min (x, bb)' со списком аргументов, то вместо этого будет

произведена замена на значение соответствующего макроса. Если использовать

конструкцию '(min) (a, bb)', где за именем 'min' не следует открывающаяся

скобка, то будет произведен вызов функции 'min'.

Нельзя определять простой макрос и макрос с аргументами с одним именем.

В определении макроса с аргументами список аргументов должен следовать

сразу после имени макроса без пробелов. Если после имени макроса стоит

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

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

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

образом позволяет выполнять такие операции как

#define FOO(x) - 1 / (x)

(где определяется макрос 'FOO', принимающий один аргумент и добавляет минус

к числу, обратному аргументу) или

#define BAR (x) - 1 / (x)

(где определяется макрос 'BAR' без аргументов и имеющий постоянное значение

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5231
Авторов
на СтудИзбе
425
Средний доход
с одного платного файла
Обучение Подробнее