pragma argsused что это
Иллюстрированный самоучитель по C++ Builder
Создание консольного приложения
Начинается консольное приложение директивой #pragma hdrstop, которая запрещает выполнение предварительной компиляции подключаемых файлов. После этой директивы надо вставить директивы #inciude, обеспечивающие подключение необходимых библиотек (например, #include ). Директива #pragma argsused отключает предупреждение компилятора о том, что аргументы, указанные в заголовке функции, не используются.
Следует обратить внимание на то, что консольное приложение разрабатывается в Windows, а выполняется как программа DOS. В DOS и Windows буквы русского алфавита имеют разные коды (в DOS используется кодировка ASCII, а в Windows – ANSI). Это приводит к тому, что консольное приложение вместо сообщений на русском языке выводит «абракадабру».
Проблему вывода сообщений на русском языке консольными приложениями можно решить, разработав функцию перекодировки ANSI-строки в строку ASCII. Если эту функцию назвать rus, то инструкция вывода сообщения может выглядеть, например, так:
В качестве примера консольного приложения в листинге 7.1 приведена программа «Угадай число», которая для вывода сообщений использует функцию RUS. Значение функции rus – строка символов в кодировке ASCII, соответствующая строке, полученной в качестве параметра.
Листинг 7.1. Пример консольного приложения.
#pragma
Директива #pragma определяется стандартом ANSI С для реализации директив, предоставляющих компилятору различные инструкции. Стандартный вид #pragma следующий:
где имя — это имя директивы #pragma. Borland определяет 14 директив #pragma:
argused
anon_struct
codeseg
comment
exit
hdrfile
hdrstop
inline
intrinsic
message
option
saveregs
startup
warn
Директива argused должна стоять перед функцией. Она используется для устранения предупреждений, если аргумент функции, перед которой стоит #pragma, не используется в теле функции.
Чтобы разрешить использовать анонимные структуры, укажите директиву anon_struct. С помощью директивы codeseg можно указать сегмент, класс или группу, используемую функцией.
Используя директиву comment, в выходной файл, например, в файл с расширением obj или ехе можно поместить комментарии.
Директива exit определяет одну или несколько функций, вызываемых при завершении программы. Директива startup определяет одну или несколько функций, вызываемых при запуске программы. Они имеют следующий вид:
#pragma exit имя_функции приоритет
#pragma startup имя_функции приоритет
Приоритет — это значение от 64 до 255 (значения от 0 до 63 зарезервированы). Приоритет определяет порядок вызова функций. Если приоритет не указан, то по умолчанию предполагается значение 100. Все функции, выполняющиеся в начале или конце программы, должны объявляться следующим образом:
void f(void);
Следующий пример определяет функцию start(), выполняющуюся в начале программы.
#include
void start(void);
#pragma startup start 65
int main(void)
<
printf(«In main\n»);
return 0;
>
void start (void)
<
printf(«In start\n»);
>
В результате работы программы на экране появится:
Как показывает данный пример, необходимо предоставить прототип функции до использования директивы #pragma.
С помощью директивы hdrfile можно определить имя файла, используемого для хранения пред- компилированных заголовочных файлов. Он имеет вид
#pragma hdrfile «имя_файла. csm»
где имя_файла — это имя файла (с расширением csm).
Директива hdrstop сообщает Borland С++ о необходимости остановить предкомпиляцию заголовочных файлов.
Также имеется директива inline, имеющая следующий вид:
Она сообщает компилятору, что программа содержит внутренний ассемблерный код. При создании самого быстрого кода компилятор должен знать, что в программе содержится ассемблерный код.
Используя директиву intrinsic, можно указать компилятору на необходимость подстановки кода функции вместо ее вызова. Директива имеет вид:
#pragma intrinsic имя_функции
где имя_функции — это имя функции, которую необходимо сделать внутренней.
alloca memcpy stpcpy strcpy strncpy
fabs memset strcat strlen strnset
memchr rotl strchr strncat strrchr
memcmp rotr strcmp strncmp
Воспользовавшись директивой intrinsic, можно отменить функции, которые станут внутренними: #pragma intrinsic имя_функции
Директива message позволяет определить сообщение, выводимое в качестве предупреждения при компиляции программы. Например:
#include
#pragma message This will be displayed as a warning.
int main(void)
<
int i=10;
printf («This is i: %d\n», i);
#pragma message This is also displayed as a warning.
return 0;
>
При компиляции появятся два сообщения #pragma, выводящиеся в качестве предупреждений. При использовании ИСР они появятся в стандартном окне сообщений.
Директива option позволяет определить опции командной строки вместо того, чтобы данные опции явно указывать в командной строке. Она имеет следующий вид:
#pragma option список_опций
Например, следующая директива приводит к тому, что содержащая ее программа будет компилироваться в модели large:
Следующие опции не могут использоваться с директивой option:
Для использования некоторых опций директива option должна стоять перед любыми объявлениями, включая прототипы функций. Поэтому имеет смысл помещать данную директиву самой первой.
Директива saveregs запрещает функции, объявленной как huge, изменять какие-либо регистры. Данная директива должна стоять перед функцией, и она влияет только на функцию, перед которой стоит.
Директива warn позволяет запретить или разрешить различные предупреждения. Она имеет вид:
#pragma warn установки
где установки — это опции для определения предупреждений.
pragma, а __pragma также _Pragma Ключевые слова и
Директивы директивы pragma определяют функции компилятора, зависящие от конкретного компьютера или операционной системы. __pragma Ключевое слово, относящееся только к компилятору Майкрософт, позволяет создавать pragma директивы кода внутри определений макросов. Стандартный _Pragma Оператор препроцессора появился в C99 и принят в c++ 11.
Синтаксис
#pragma #pragma
__pragma( __pragma( ) токена два подчеркивания в начале — конкретное расширение Майкрософт
_Pragma( _Pragma( ) C99
Комментарии
Каждая реализация C и C++ поддерживает некоторые возможности, уникальные для хост-компьютера или операционной системы. Некоторые программы, например, должны выполнять точный контроль над расположением данных в памяти или управлять способом получения параметров определенными функциями. #pragma Директивы предлагают каждому компилятору возможность предоставлять функции для конкретного компьютера и операционной системы, сохраняя общую совместимость с языками C и C++.
Директивы директивы pragma зависят от конкретного компьютера или операционной системы и обычно отличаются для каждого компилятора. pragmaМожно использовать в условной директиве для предоставления новых функций препроцессора. Или используйте один из них, чтобы предоставить компилятору сведения, определяемые реализацией.
Компиляторы Microsoft C и C++ распознают следующие pragma директивы:
1 поддерживается только компилятором C++.
__pragma ключевое слово
В следующем примере кода показано, как __pragma ключевое слово может использоваться в макросе. Этот код взят из заголовка мфкдуал. h в образце ACDUAL в «примеры поддержки компилятора COM»:
_Pragma оператор предварительной обработки
Кавычки и обратные косые черты должны быть экранированы, как показано выше. pragmaСтрока, которая не распознана, игнорируется.
В следующем примере кода показано, как _Pragma ключевое слово можно использовать в макросе, похожем на утверждение. Он создает pragma директиву, которая подавляет предупреждение в случае, если условие выражения является константой.
2.11 – Защита заголовков
Проблема повторяющегося определения
В уроке «2.6 – Предварительные объявления и определения» мы отметили, что идентификатор переменной или функции может иметь только одно определение (правило одного определения). Таким образом, программа, которая определяет идентификатор переменной более одного раза, вызовет ошибку компиляции:
Точно так же программы, которые определяют функцию более одного раза, также вызовут ошибку компиляции:
Хотя эти программы легко исправить (удалить повторяющееся определение), с помощью заголовочных файлов довольно легко попасть в ситуацию, когда определение в заголовочный файл включается более одного раза. Это может произойти, если заголовочный файл включает с #include другой заголовочный файл (что является обычным явлением).
Рассмотрим следующий академический пример:
Таким образом, после разрешения всех директив #include файл main.cpp будет выглядеть так:
Защита заголовка
Хорошей новостью является то, что мы можем избежать указанной выше проблемы с помощью механизма, называемого защитой заголовка (или защитой включения). Защита заголовка – это директивы условной компиляции, которые имеют следующую форму:
Все ваши заголовочные файлы должны иметь защиту заголовков. Имя SOME_UNIQUE_NAME_HERE может быть любым, но по соглашению устанавливается равным полному имени заголовочного файла, набранному заглавными буквами, с использованием подчеркивания вместо пробелов и знаков препинания. Например, у square.h будет защита заголовка будет следующей:
Даже заголовочные файлы стандартной библиотеки используют защиту заголовков. Если бы вы взглянули на заголовочный файл iostream из Visual Studio, вы бы увидели:
Для продвинутых читателей
Обновление нашего предыдущего примера с помощью защиты заголовков
После того, как препроцессор разрешит все включения, эта программа будет выглядеть так:
Как видно из примера, второе включение содержимого square.h (из geometry.h ) игнорируется потому, что SQUARE_H уже был определен при первом включении. Следовательно, функция getSquareSides включается только один раз.
Защита заголовков не препятствует одиночным включениям заголовка в разные файлы исходного кода.
Обратите внимание, что цель защиты заголовков – предотвратить получение файлом исходного кода более одной копии защищенного заголовка. По замыслу, защита заголовков не препятствует включению данного заголовочного файла (однократно) в отдельные исходные файлы. Это также может вызвать непредвиденные проблемы. Рассмотрим следующую возможность:
Разве мы не можем просто избежать определений в файлах заголовков?
Обычно мы советуем вам не включать определения функций в заголовки. Итак, вам может быть интересно, зачем вам включать защиту заголовков, если она защищают вас от чего-то, чего вы не должны делать.
В будущем мы покажем вам довольно много случаев, когда в файл заголовка необходимо поместить определения, не являющиеся функциями. Например, C++ позволяет вам создавать свои собственные типы. Эти пользовательские типы обычно определяются в файлах заголовков, чтобы эти определения можно было распространить на исходные файлы, которые должны их использовать. Без защиты заголовков ваши исходные файлы могут иметь несколько идентичных копий этих определений, что приведет к ошибке компиляции повторяющихся определений.
Таким образом, хотя на данном этапе этой серии обучающих статей не обязательно иметь защиту заголовков, но мы вырабатываем хорошие привычки, чтобы вам не приходилось отказываться от вредных привычек позже.
#pragma once
Многие компиляторы поддерживают более простую альтернативную форму защиты заголовков с помощью директивы #pragma :
#pragma когда-то служила той же цели, что и защита заголовков, а ее дополнительное преимущество заключается в том, что она короче и менее подвержена ошибкам.
Однако #pragma once не является официальной частью языка C++, и не все компиляторы поддерживают ее (хотя большинство современных компиляторов поддерживает).
В целях совместимости мы рекомендуем придерживаться традиционной защиты заголовков. Она не требуют много работы и гарантированно поддерживаются всеми компиляторами.
Резюме
Защита заголовков предназначена для того, чтобы содержимое заданного заголовочного файла не копировалось более одного раза в любой отдельный файл, чтобы предотвратить дублирование определений.
Обратите внимание, что дублирование объявлений – это нормально, поскольку объявление может быть объявлено несколько раз без инцидентов, но даже если ваш заголовочный файл состоит только из объявлений (без определений), всё равно рекомендуется включать защиту заголовков.
Обратите внимание, что защита заголовков не предотвращает копирование содержимого заголовочного файла (один раз) в отдельные файлы проекта. Это хорошо потому, что нам часто нужно ссылаться на содержимое заданного заголовка из разных файлов проекта.
Небольшой тест
Вопрос 1
Добавьте защиту заголовка в этот заголовочный файл:
hdrstop pragma
Предоставляет более полный контроль над именами файлов с предварительной компиляцией и расположением, в котором сохраняется состояние компиляции.
Синтаксис
#pragma hdrstop [(» #pragma hdrstop «)]
Комментарии
Имя файла является именем предкомпилированного файла заголовка для использования или создания (в зависимости от того, указан ли /Yc параметр или). Если имя файла не содержит спецификацию пути, предполагается, что предкомпилированный заголовочный файл находится в том же каталоге, что и исходный файл.
Имя предкомпилированного файла заголовка определяется в соответствии со следующим правилам в порядке приоритета.
Аргумент для /Fp параметра компилятора
Аргумент filename для
Базовое имя исходного файла с расширением PCH
Если ни один из /Yc параметров и не /Yu hdrstop pragma указывает имя файла, базовое имя исходного файла используется в качестве базового имени файла предкомпилированного заголовка.
Команды предварительной обработки также можно использовать для выполнения замены макроса.
Следующие правила управляют тем, где hdrstop pragma можно разместить.
Она должна находится за пределами любых объявлений или определений данных или функций.
Она должна задаваться в файле исходного кода, а не заголовка.