Pragma hdrstop c что это
Перейти к содержимому

Pragma hdrstop c что это

  • автор:

Pragma hdrstop c что это

В этой статье приведены наиболее часто используемые директивы #pragma. Подробнее про директивы #pragma написано в руководстве [1], раздел Compiler -> C/C++ Compiler Language Extensions -> Pragmas.

[Общие сведения]

Компилятор Blackfin C/C++ поддерживает прагмы. Это специальные директивы, которые модифицируют поведение компилятора. Есть 2 способа использования прагм: директивы pragma и операторы pragma.

Директивы pragma имеют следующий синтаксис:

#pragma pragma-directive pragma-directive-operands new-line

Операторы pragma имеют следующий синтаксис:

Когда обрабатывается оператор pragma, компилятор превращает его в директиву pragma directive, используя не строковую версию операнда строкового литерала string-literal. Это означает, что следующая директива pragma:

#pragma linkage_name mylinkname

может быть также быть заменена следующим эквивалентным оператором pragma operator:

_Pragma («linkage_name mylinkagename»)

Примеры в этом руководстве используют форму директивы.

Компилятор языка C поддерживает прагмы для следующих целей:

• Управление выравниванием данных.
• Управление выводом диагностических сообщений компилятора.
• Определение функций, которые могут служить обработчиками прерываний.
• Изменение уровня оптимизации, которое может применяться внутри модуля кода.
• Изменение того, как будет слинкована видимая внешняя функция.
• Предоставление заголовочного файла для конфигураций и свойств.
• Предоставление дополнительной информации для цикла в целях улучшения его оптимизаций.

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

[Управление выравниванием данных]

Может использоваться перед различными декларациями структур и полей. Прикладывается непосредственно к переменной, которая сразу следует за директивой #pragma align. Синтаксис:

#pragma align num

Эта прагма дает эффект, что следующая за ней переменная или поле принудительно будут выровнены по границе адреса блока памяти, как это указано числовым параметром num, следующим образом:

• Если pragma прикладывается к локальной переменной (которая сохраняется в стеке), то выравнивание переменной будет изменено только в том случае, когда число num не больше, чем выравнивание стека, т. е. 4 байта. Если же num больше выравнивания стека, то компилятор выдаст предупреждение, и pragma будет игнорирована.

• Если num больше, чем выравнивание, которое нормально требуется для выравнивания следующей декларируемой переменной или поля, то переменная или поле будут выравнены в памяти по границе с адресом, кратным num.

• Если num меньше, чем нормально требуемое выравнивание, то выравнивание переменной или поля при декларации будет изменено в соответствии с num, и компилятором будет выдано предупреждение, что выравнивание было уменьшено.

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

_WORD задает 32-разрядное выравнивание (соответствует num==4)
_LONG задает 64-разрядное выравнивание (соответствует num==8)
_QUAD задает 128-разрядное выравнивание (соответствует num==16)

Если в настоящий момент активно действие директив #pragma pack или #pragma pad pragma (см. врезки далее), то выравнивание этих директив будет изменено непосредственно следующей декларацией поля.

В следующих примерах показано, как использовать #pragma align.

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

Следующий пример показывает недопустимое использование #pragma align. Поскольку выравнивание не является степенью числа 2, компилятор не позволит его использовать и выдаст ошибку.

Внимание: #pragma align прикладывается только с непосредственно следующей переменной при декларации, даже если она является частью списка. Например:

Директива pack используется для упаковки полей структуры. Синтаксис:

#pragma pack (alignopt)

Прагма pack может применяться к определениям структур (struct). Она прикладывается ко всем определениям структур, которые следуют после неё, пока не будет восстановлено выравнивание по умолчанию, когда в директиве пропущен параметр alignopt (например, когда задана #pragma pack() с пустыми круглыми скобками).

Прагма pack используется для уменьшения выравнивания по умолчанию в структуре до значения alignopt. Если поля в структуре имеют выравнивание по умолчанию больше, то их выравнивание будет уменьшено до alignopt. Если поля в структуре имеют выравнивание меньше alignopt, то их выравнивание останется без изменения.

Если указано значение alignopt, то нельзя использовать #pragma pad, пока не будет восстановлено значение выравнивания по умолчанию. Компилятор генерирует сообщение об ошибке, если прагмы pad и pack используются так, что получается конфликт.

В следующем примере показано, как использовать #pragma pack:

Процессор Blackfin не поддерживает доступы к не выровненным участкам памяти на аппаратном уровне; поэтому компилятор генерирует дополнительные код, чтобы корректно обработать чтения из не выровненных полей структуры (и записи в них). Сгенерированный код не обязательно будет таким же эффективным, как и чтение/запись выровненных полей, но это вынужденный компромисс, на который приходится идти для доступа к упакованным структурам.

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

Поскольку #pragma pack уменьшает требования к выравниванию, и таким образом уменьшает необходимость для добавления нулевых байт к полям структуры, общий размер структуры может быть уменьшен; фактически именно это уменьшение как раз и является причиной использования этой прагмы. Однако имейте в виду, что уменьшенное выравнивание может быть применено к структуре в целом, так что экземпляры структуры могут начинаться на границах alignopt вместо границ по умолчанию, эквивалентных для не упакованных структур.

Для предыдущей версии VisualDSP++ 4.0 это работало не так. Компилятор уменьшал внутреннее выравнивание, но сохранял общее выравнивание. Начиная с VisualDSP++ 4.0 упакованные структуры могут начаться с разных границ от не упакованных структур. Чтобы сохранить общее начальное выравнивание, используйте #pragma align на первом поле структуры.

#pragma pad (alignopt)

Прагма pad pragma может применяться к определениям структур. Она прикладывается к определениям структур, которые следуют выравниванию по умолчанию, восстановленному пропуском alignopt (например, #pragma pad() с пустыми скобками).

Прагма pad является эффективной заменой для размещения #pragma align перед каждым полем внутри определения структуры. Наподобие прагмы pack, она уменьшает выравнивание полей, у которых по умолчанию выравнивание больше, чем alignopt.

Однако, в отличие от прагмы pack, она также увеличивает выравнивание полей, которые по умолчанию меньше, чем alignopt. Также #pragma pack (alignopt) выдает предупреждение, когда выравнивание поля уменьшено, а #pragma pad (alignopt) этого не делает.

Если указан параметр alignopt, то нельзя использовать #pragma pack, пока не будет восстановлено выравнивание по умолчанию.

Следующий пример показывает, как использовать #pragma pad().

[Управление диагностикой]

Компилятор поддерживает директивы #pragma diag, которые позволяют селективный выбор важности диагностических сообщений компилятора. У этой директивы есть 3 формы:

• Модификация важности отдельных диагностик.
• Модификация поведения целого класса диагностик.
• Сохранение или восстановление текущего поведения всех диагностик.

Модификация важности отдельных диагностик. Эта форма директивы имеет следующий синтаксис:

#pragma diag(ACTION: DIAG [, DIAG . ][: STRING])

Здесь ACTION является квалификатором, который может быть одним из ключевых слов, перечисленных в таблице 1-32.

Таблица 1-32. Ключевые слова для квалификатора ACTION.

Ключевое слово Действие
suppress Подавляет все указанные диагностические проверки.
remark Изменяет важность указанной диагностики к комментарию.
warning Изменяет важность указанной диагностики к предупреждению.
error Изменяет важность указанной диагностики к ошибке.
restore Восстанавливает важность диагностики к оригинальному значению, которое было при запуске компиляции (состояние, полученное после обработки всех опций командной строки компилятора).

Если не используется режим MISRA-C, то квалификатор DIAG может быть одним или большим количеством перечисленных через запятую номеров диагностических сообщений компилятора без предшествующих префиксов «cc» или нулей. Выбор номеров ошибок ограничен теми, у которых может быть изменена их важность (это те, которые отображают «» в сообщении об ошибке).

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

В режиме MISRA-C квалификатор DIAG является списком номеров правил MISRA-C в форме misra_rule_6_3 и misra_rule_19_4 для правил 6.3 и 19.4, и так далее. Правила 10.1 и 10.2 являются специальным случаем, в котором оба правила разделяются на 4 отдельные проверки правил. Например, 10.1(c) должно быть обозначено как misra_rule_10_1_c.

Третий, не обязательный аргумент это строковый литерал для вставки комментария, относящегося к использованию #pragma diag.

Модификация поведения целого класса диагностик. Эта форма директивы имеет следующий синтаксис, который не разрешен в режиме MISRA-C:

Эффект получается следующий:

#pragma diag(errors). Эта прагма может быть использована, чтобы запретить все последующие сообщения и ремарки (эквивалентна опции -w командной строки).

#pragma diag(remarks). Эта прагма может быть использована для разрешения последующих ремарок и предупреждений (эквивалентна опции -Wremarks командной строки).

#pragma diag(warnings). Эта прагма может быть использована для восстановления поведения по умолчанию, когда не заданы ни одна из опций -w или -Wremarks, которые отображают предупреждения, но запрещают ремарки.

Сохранение или восстановление текущего поведения всех диагностик. Эта прагма имеет следующий синтаксис:

#pragma diag(push)
#pragma diag(pop)

Эффект получается следующий:

#pragma diag(push). Эта прагма может использоваться для сохранения текущего состояния важности всех диагностических сообщений об ошибках.

#pragma diag(pop). Эта прагма восстанавливает все диагностические сообщения, которые были ранее сохранены ближайшим предыдущим push.

Все директивы #pragma diag(push) должны соответствовать такому же количеству последующих директив #pragma diag(pop) всего юнита трансляции, но не должны быть соответствующими в отдельных исходных файлах, за исключением режима MISRA-C. Обратите внимание, что порог ошибки (установленный на ключевые слова remarks, warnings или errors) также сохранится и восстановится этими директивами.

Длительность таких модификаций важности диагностики продолжается от следующей строки за директивой pragma или до конца юнита трансляции, или до следующей директивы #pragma diag(pop), или до следующей директивы #pragma diag() с тем же номером ошибки. Эти прагмы могут использоваться могут использоваться в любых местах кода, и на них не влияют обычные правила области видимости (normal scoping rules).

Сначала обрабатываются все изменения диагностики, задаваемые из командной строки, и любые последующие директивы #pragma diag() получают приоритет, когда действие восстановления откатывает обработку важности обратно к моменту начала компиляции, когда были обработаны опции командной строки.

Примечание: директивы для модификации отдельных диагностик сингулярны (упоминаются в единственном числе, например «error»), и директивы для модификации классов диагностик плюральны (во множественном числе, «errors»).

[Передача компилятору атрибутов]

Прагма file_attr указывает компилятору выдать специальные атрибуты, когда он обрабатывает файл, содержащий эту прагму. В одной строке допускается использовать несколько директив #pragma file_attr. Синтаксис:

#pragma file_attr(«name[=value]» [, «name[=value]» [. ]])

Если опущено «=value», то будет использоваться значение по умолчанию «1».

Значение атрибута это все символы, которые следуют после символа ‘=’ и перед закрывающего символа «, включая пробелы. Будет выдано предупреждение, если были предшествующие или завершающие пробелы в значении атрибута, поскольку это скорее всего будет ошибкой.

Подробнее про атрибуты см. раздел «File Attributes» руководства [1]. Также см. [3].

Прагмы управления файлами заголовка (hdrstop, no_implicit_inclusion, no_pch, once и system_header) помогают компилятору обрабатывать заголовочные файлы (header files).

Прагма hdrstop используется вместе с опцией -pch (precompiled header). Опция -pch инструктирует компилятор на просмотр предварительно скомпилированного заголовка (precompiled header, файл с расширением .pch file), и, если он не найден, генерировать файл для использования в последующих компиляциях. Файл .pch содержит снимок всего кода, предшествующего точке header stop.

По умолчанию точка header stop это первая точка в модуле кода, где заканчивается препроцессинг. Директива #pragma hdrstop может использоваться для установки точки пораньше.

В следующем примере точка header stop по умолчанию header stop находится в начале декларации переменной i.

Такой вариант может быть не очень хорошим выбором, потому что если в файле frequently_changing_data.h могут быть часто изменяемые данные, то это приведет к частой регенерации файла .pch, и в результате получится потеря выгоды от использования precompiled header. Тогда hdrstop pragma может использоваться для переноса точки header stop в более подходящее место.

В следующем примере так и сделано — файл предварительно скомпилированных заголовков не будет включать содержимое frequently_changing_data.h, потому что он подключается после прагмы hdrstop, так что не нужно будет регенерировать precompiled header всякий раз, когда был модифицирован frequently_changing_data.h.

[Управление оптимизацией]

В коде можно применять директивы all_aligned, different_banks, extra_loop_loads, optimize_off, optimize_for_speed и другие директивы. Подробнее см. [4].

[Управление линкером]

Прагма retain_name показывает, что декларация функции или переменной, которая сразу следует за этой прагмой, не должна быть удалена линкером, если нигде не используется в коде. Обычно если разрешен межпроцедурный анализ (IPA), или если линкеру разрешено удалять неиспользуемые функции или переменные (linker elimination), то инструментарий VisualDSP++ определит неиспользуемые функции и переменные, и удалит их из результирующего выходного исполняемого кода с целью экономии памяти. Прагме retain_name инструктирует инструментарий, что указанный код/переменная должны быть сохранены.

Следующий пример показывает, как использовать эту прагму.

Поскольку программа не использует ни функцию delete_me(), ни keep_me(), то обычно компилятор удалил бы из выходного кода обе эти функции. Но в данном примере компилятор удалит только функцию delete_me(), но функция keep_me() будет сохранена, потому что перед ней стоит эта прагма retain_name. Для функции main() директива retain_name не нужна.

Эта прагма допустима только для глобальных символов. Она недопустима для следующего типа символов:

• Символы со статически классом размещения (static storage class).
• Параметры функции.
• Символы с автоматическим классом размещения (auto storage class, локальные переменные). Они будут размещены в стеке во время выполнения кода.
• Члены/поля структур (structs), объединений (union), классов (class).
• Декларации типа.

Подробнее про межпроцедурный анализ (IPA) см. [5].

[Управление размещением кода и данных]

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

Прагма section(СТРОКАСЕКЦИИ [, QUALIFIER, . ]) используется для переопределения целевой секции для любого глобального или статического символа, который сразу за ней следует. Прагма позволяет лучше управлять квалификатором секции в сравнении с ключевым словом section.

Прагма default_section(ВИДСЕКЦИИ [, СТРОКАСЕКЦИИ [, QUALIFIER, . ]]) используется для переназначения секций по умолчанию, в которые компилятор помещает свои символы.

Секции по умолчанию попадают в категории, перечисленные под ВИДСЕКЦИИ . За исключением категории STI, эта прагма остается в силе для категории секции до её следующего использования с отдельной категорией, или до конца файла. STI является исключением, только в одном STI можно определить default_section, и его область действия весь файл, не только часть после использования STI. Будет выдаваться предупреждение, если в одном и том же файле будет указано несколько секций STI.

Пропуск имени секции приводит к тому, секция по умолчанию будет сброшена к секции, которая была в использовании с начала файла, которая может быть либо значением по умолчанию для компилятора, либо значением, установленным пользователем через опцию командной строки -section (например, -section ВИДСЕКЦИИ=СТРОКАСЕКЦИИ ).

Во всех случаях (включая STI), прагма default_section перезаписывает значение, указанное опцией -section в командной строке.

В этом случае x размещается в NEW_DATA2 потому, что определение x попадает в её действие. Прагма default_section может быть использована только в глобальной области действия, где разрешены глобальные переменные.

ВИДСЕКЦИИ может быть одним из ключевых слов, перечисленных в таблице 1-29.

Таблица 1-29. Виды секций для параметра ВИДСЕКЦИИ.

Ключевое слово Описание
CODE Секция используется для кода процедур и функций программы.
ALLDATA Краткое указание на секции DATA, CONSTDATA, BSZ, STRINGS и AUTOINIT.
DATA Секция, которая содержит «обычные» данные (переменные).
CONSTDATA Секция, которая содержит данные только для чтения (константы).
BSZ Секция, которая содержит не инициализируемые данные.
SWITCH Секция используется для таблиц перехода реализации операторов switch языка C/C++.
VTABLE Секция используется для таблиц виртуальных функций C++.
STI Секция содержит код, необходимый для выполнения инициализаций C++. Подробнее см. раздел справки Constructors and Destructors of Global Class Instances.
STRINGS Секция, которая содержит строковые литералы.
AUTOINIT Секция содержит данные, используемые для инициализации агрегатов C++.

СТРОКАСЕКЦИИ является строкой, заключенной в двойные кавычки, содержащей имя секции, полностью как она появляется в файле ассемблера.

Изменение одного вида секции не влияет на другие виды секции. Например, даже при том, что виды секций STRINGS и CONSTDATA по умолчанию помещаются компилятором в одну и ту же секцию, если изменена секция по умолчанию для CONSTDATA, то это никак не повлияет на данные STRINGS.

Обратите внимание, что ALLDATA не реальная секция, а псевдо-вид, который соответствует DATA, CONSTDATA, STRINGS, AUTOINIT и BSZ. Изменение ALLDATA эквивалентно изменению всех этих видов секций. Таким образом,

будет эквивалентно последовательности:

QUALIFIER может быть одним из ключевых слов, перечисленных в таблице 1-30.

Таблица 1-30. Ключевые слова для QUALIFIER.

Ключевое слово Описание
ZERO_INIT Секция инициализируется нулями при запуске программы.
NO_INIT Секция не инициализируется при запуске программы.
RUNTIME_INIT Секция, инициализируемая пользователем при запуске программы.
DOUBLE32 Секция может содержать 32-разрядные, но не 64-разрядные числа типа double.
DOUBLE64 Секция может содержать 64-разрядные, но не 32-разрядные числа типа double.
DOUBLEANY Секция может содержать либо 32-разрядные, либо 64-разрядные числа типа double.

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

В следующем коде указано, что f() должна быть размещена в секции foo, квалифицированной как DOUBLEANY:

Компилятор всегда пытается соблюдать прагму section как с высшим приоритетом, и прагма default_section всегда имеет приоритет меньше. Например, следующий код в результате приведет к тому, что функция f будет размещена в секции foo:

В следующем коде x будет помещен в секции zeromem:

Примечание: в случаях, когда объект C++ STL требуется разместить в какой-то определенной секции памяти, использование #pragma section/default_section не работает. Вместо этого должна использоваться куча не по умолчанию (non-default heap), как это разъяснено в руководстве «Allocating C++ STL Objects to a Non-Default Heap».

С++ Builder: как ускорить компиляцию с помощью предкомпилированных заголовков

Вместо вступления сразу приведу пример. Полная сборка (build) проекта, содержащего около 170 cpp-модулей, при использовании предкомпилированных заголовков происходит за 811 секунд, при этом число обработанных компилятором строк составляет 1,808,780. При компиляции того же проекта без использования предкомпилированных заголовков, время сборки составляет 2399 секунд, а число строк, обработанных компилятором — 45,261,820. Впечатляет, не так ли? Плата за это ускорение, в принципе не велика — предкомпилированный образ, размер которого около 40 Мб.

При компиляции исходных текстов, компилятор должен обработать все *.cpp файлы проекта и все включенные в них *.h — файлы. При этом обрабатываются как пользовательские заголовочные файлы, так и стандартные, такие как vcl.h или Word2k.h. Количество кода, находящегося в стандартных заголовках может быть очень большим, например размер файла Word2k.h превышает 5 Мб, в нем больше 130 000 строк кода.

Так как содержимое стандартных заголовков не изменяется, то их компиляция при каждой сборке проекта является напрасной тратой времени. Предкомпилированные заголовки помогают решить эту проблему — стандартные файлы компилируются один раз, а затем используется скомпилированный двоичный образ.

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

Для управления предкомпилированными предназначена директива компилятора #pragma hdrstop. Все заголовочные файлы, включенные до этой директивы, помещаются в один образ, например:

Такая последовательность создаст образ, содержащий скомпилированные vcl.h и string. Этот образ будет использован для другого cpp-файла, если в нем до директивы hdrstop будут включены те же файлы, в том же порядке. Обращу внимание, что важен не только состав, но и порядок следования заголовков — даже если следующий cpp-файл включает те же заголовки, но сначала указан string, а потом vcl.h, то для этого cpp-файла будет создан новый образ.

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

  • состав включенный файлов до директивы hdrstop должен быть тем же
  • последовательность включения файлов до директивы hdrstop должна быть той же

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

  • ВСЕ cpp-файлы проекта имели одинаковый блок включений до директивы hdrstop
  • в этот блок должны входить ВСЕ стандартные заголовочные файлы, необходимые для проекта

Выполнить эти условия достаточно просто, для этого в начало каждого cpp-файла необходимо поместить следующие строки:

где pch.h — файл, содержащий включения всех стандартных заголовков:

Полный текст моей версии этого файла приведен в конце статьи. На h-файлы, входящие в предкомпилированный образ, накладывается ограничение — в них не должно быть инициализированных данных, например, в math.hpp есть строки:

Из-за наличия этих констант включить math.hpp в файл pch.h нельзя.

Кстати, С++ Builder при добавлении новых модулей в проект реализует описанную стратегию управления предкомпилированными заголовками. Например, при создании нового приложения, файл Unit1.cpp будет таким:

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

Управлять составом включаемых в vcl.h заголовков можно с помощью специальных символов (INC_VCLDB_HEADERS, INC_VCLEXT_HEADERS и др.). В моей версии pch.h эти символы определяются с помощью #define до включения vcl.h, что приводит к увеличению числа включаемых файлов.

Как в существующем проекте перейти к использованию предкомпилированных заголовков

Даже в большом проекте перейти к использованию предкомпилированных заголовков достаточно просто.

В свойствах проекта нужно включить кэширование предкомпилированных заголовков и рекомендуется указать «персональный» файл, в котором будет храниться образ предкомпилированных заголовков: Project — Options — закладка Compiler, группа «Pre-compiled headers». Тут должно быть выбрано «Cache pre-compiled headers», а в поле «File Name» нужно ввести «pch.csm». При такой настройке образ с предкомпилированными заголовками будет находится в папке с проектом, в файле pch.csm.

После этого в начало каждого cpp-модуля необходимо вставить 2 строки:

Все ранее включенные заголовочные файлы остаются на своих местах, их удалять не надо. Например:

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

Pragma hdrstop c что это

Preprocessing lines of the following form specify implementation-defined actions.

The following #pragmas are recognized by the compilation system. The compiler ignores unrecognized pragmas. Using the –v option will generate a warning for unrecognized pragmas.

2.12.1 align

The align pragma makes all the mentioned variables memory aligned to integer bytes, overriding the default. The following limitations apply:

The integer value must be a power of 2 between 1 and 128. Valid values are: 1, 2, 4, 8, 16, 32, 64, and 128.

variable is a global or static variable.

If the specified alignment is smaller than the default, the default is used.

The pragma line must appear before the declaration of the variables which it mentions. Otherwise, it is ignored.

Any variable that is mentioned but not declared in the text following the pragma line is ignored. For example:

2.12.2 c99

This pragma controls diagnostics for implicit function declarations. If the c99 pragma value is set to “implicit” (note the use of quotation marks), a warning is generated when the compiler finds an implicit function declaration. If the c99 pragma value is set to “no%implicit” (note the use of quotation marks) the compiler silently accepts implicit function declaration until the pragma value is reset.

The value of the -std option affects the default state of this pragma. For -std=c11 or -std=c99, the default state is #pragma c99(“implicit”). For -std=c89, the default state is #pragma c99(“no%implicit”).

2.12.3 does_not_read_global_data

This pragma asserts that the specified list of routines do not read global data directly or indirectly. This behavior results in better optimization of code around calls to such routines. In particular, assignment statements or stores could be moved around such calls.

The specified functions must be declared with a prototype or empty parameter list prior to this pragma. If the assertion about global access is not true, then the behavior of the program is undefined.

2.12.4 does_not_return

This pragma is an assertion to the compiler that the calls to the specified routines will not return. The compiler can then perform optimizations consistent with that assumption. For example, register life-times will terminate at the call sites, which in turn enables more optimizations.

If the specified function does return, then the behavior of the program is undefined. This pragma is permitted only after the specified functions are declared with a prototype or empty parameter list, as shown in the following example:

2.12.5 does_not_write_global_data

This pragma asserts that the specified list of routines do not write global data directly or indirectly. This behavior results in better optimization of code around calls to such routines. In particular, assignment statements or stores could be moved around such calls.

The specified functions must be declared with a prototype or empty parameter list prior to this pragma. If the assertion about global access is not true, then the behavior of the program is undefined.

2.12.6 dumpmacros

Use this pragma when you want to see how macros are behaving in your program. This pragma provides information such as macro defines, undefines, and instances of usage. It prints output to the standard error (stderr) based on the order macros are processed. The dumpmacros pragma is in effect through the end of the file or until it reaches a #pragma end_dumpmacros. See end_dumpmacros. The following table lists the possible values for value :

The dumpmacros pragma has the same effect as the command-line option, however, the pragma overrides the command-line option. See -xdumpmacros[=value[,value. ]].

The dumpmacros pragma does not nest so the following lines of code stop printing macro information when the #pragma end_dumpmacros is processed:

The effect of the dumpmacros pragma is cumulative. The following lines

have the same effect as:

If you use the option #pragma dumpmacros(use,no%loc), the name of each macro that is used is printed only once. If you use the option #pragma dumpmacros(use,loc), the location and macro name is printed every time a macro is used.

2.12.7 end_dumpmacros

This pragma marks the end of a dumpmacros pragma and stops printing information about macros. If you do not use an end_dumpmacros pragma after a dumpmacros pragma, the dumpmacros pragma continues to generate output through the end of the file.

2.12.8 error_messages

The error_messages pragma provides control within the source program over the messages issued by the C compiler and lint. For the C compiler, the pragma has an effect on warning messages only.

The on option ends the scope of any preceding #pragma error_messages option, such as the off option, and overrides the effect of the –erroff option.

#pragma error_messages (off, tag… tag )

The off option prevents the C compiler or the lint program from issuing the given messages beginning with the token specified in the pragma. The scope of the pragma for any specified error message remains in effect until overridden by another error_messages pragma, or the end of compilation.

#pragma error_messages (default, tag… tag )

The default option ends the scope of any preceding #pragma error_messages directive for the specified tags.

#pragma error_messages will not suppress messages issued by lint pass 2.

For more information about lint passes, see Using lint.

2.12.9 fini

Causes the implementation to call functions f1 to fn (finalization functions) after it calls main() routine. Such functions are expected to be of type void and accept no arguments. They are called either when a program terminates under program control or when the containing shared object is removed from memory. As with initialization functions, finalization functions are executed in the order processed by the link editors.

You should be careful when a finalization function affects the global-program state. For example, unless an interface explicitly states what happens when you use a system-library finalization function, you should capture and restore any global state information, such as the value of errno, that the system-library finalization function may change.

Such functions are called once for every time they appear in a #pragma fini directive.

2.12.10 hdrstop

The hdrstop pragma must be placed after the last header file to identify the end of the viable prefix in each source file that is to share the same precompiled-header file. For example, consider the following files:

The viable source prefix ends at c.h so you would insert a #pragma hdrstop after c.h in each file.

#pragma hdrstop must only appear at the end of the viable prefix of a source file that is specified with the cc command. Do not specify #pragma hdrstop in any include file.

2.12.11 ident

Places string in the .comment section of the executable.

2.12.12 init

Causes the implementation to call functions f1 to fn (initialization functions) before it calls the main() function. Such functions are expected to be of type void and accept no arguments. They are called while constructing the memory image of the program at the start of execution. Initializers in a shared object are executed during the operation that brings the shared object into memory, either at program startup or some dynamic loading operation, such as dlopen(). The only ordering of calls to initialization functions is the order in which they were processed by the link editors, both static and dynamic.

Take extra precautions when an initialization function affects the global-program state. For example, unless an interface explicitly states what happens when you use a system-library initialization-function, you should capture and restore any global state information, such as the value of errno, that the system-library initialization-function may change.

Such functions are called once for every time they appear in a #pragma init directive.

2.12.13 inline

This pragma controls the inlining of routine names listed in the argument of the pragma. The scope of this pragma is over the entire file. Only global inlining control is allowed — call-site specific control is not permitted by this pragma.

#pragma inline provides a suggestion to the compiler to inline the calls in the current file that match the list of routines listed in the pragma. This suggestion may be ignored in certain situations. For example, the suggestion is ignored when the body of the function is in a different module and the crossfile option is not used.

#pragma no_inline provides a suggestion to the compiler not to inline the calls in the current file that match the list of routines listed in the pragma.

Both #pragma inline and #pragma no_inline are permitted only after the function is declared with a prototype or empty parameter list, as shown in the following example.

For more information, see the descriptions of compiler options -xldscope, -xinline, -xO, and -xipo.

2.12.14 int_to_unsigned

For a function that returns a type of unsigned, in –Xt or –Xs mode, changes the function return to be of type int.

2.12.15 must_have_frame

This pragma requests that the specified list of functions always be compiled to have a complete stack frame (as defined in the System V ABI). You must declare the prototype for a function before listing that function with this pragma.

This pragma is permitted only after the prototype for the specified functions is declared. The pragma must precede the end of the function.

2.12.16 nomemorydepend

(SPARC) This pragma specifies that within any iteration of a loop, there are no memory dependences caused by references to the same memory address. This pragma enables the compiler to schedule instructions more effectively within a single iteration of a loop. If any memory dependences exist within any iteration of a loop, the results of executing the program are undefined. The compiler takes advantage of this information at optimization level of 3 or above.

The scope of this pragma begins with the pragma and ends with whichever of the following situations occurs first: the beginning of the next block, the next for loop within the current block, the end of the current block. The pragma applies to the next for loop prior to the end of the pragma’s scope.

2.12.17 no_side_effect

funcname specifies the name of a function within the current translation unit. The function must be declared with a prototype or empty parameter list prior to the pragma. The pragma must be specified prior to the function’s definition. For the named function, funcname , the pragma declares that the function has no side effects of any kind and returns a result value that depends only on the passed arguments. In addition, funcname and any called descendants behave as follows:

Do not access for reading or writing any part of the program state visible in the caller at the point of the call.

Do not perform I/O.

Do not change any part of the program state not visible at the point of the call.

The compiler can use this information when doing optimizations using the function. If the function does have side effects, the results of executing a program that calls this function are undefined. The compiler takes advantage of this information at optimization level of 3 or above.

2.12.18 opt

funcname specifies the name of a function defined within the current translation unit. The value of level specifies the optimization level for the named function. You can assign optimization levels 0, 1, 2, 3, 4, or 5. You can disable optimization by setting level to 0. The functions must be declared with a prototype or empty parameter list prior to the pragma. The pragma must precede the definitions of the functions to be optimized.

The level of optimization for any function listed in the pragma is reduced to the value of -xmaxopt. The pragma is ignored when –xmaxopt=off.

2.12.19 pack

Use #pragma pack( n ) to affect member packing of a structure or a union. By default, members of a structure or union are aligned on their natural boundaries; one byte for a char, two bytes for a short, four bytes for an integer, and so on. If n is present, it must be a power of 2 specifying the strictest natural alignment for any structure or union member. Zero is not accepted.

The #pragma pack( n ) directive applies to all structure or union definitions that follow it until the next pack directive. If the same structure or union is defined in different translation units with different packing, your program may fail in unpredictable ways. In particular, you should not use #pragma pack( n ) prior to including a header that defines the interface of a precompiled library. The recommended usage of #pragma pack( n ) is to place it in your program code immediately before any structure or union to be packed. Follow the packed structure immediately with #pragma pack( ).

You can use #pragma pack( n ) to specify an alignment boundary for a structure or union member. For example, #pragma pack(2) aligns int, long, long long, float, double, long double, and pointers on two byte boundaries instead of their natural alignment boundaries.

If n is the same or greater than the strictest alignment on your platform, (four on x86 with -m32, eight on SPARC with —m32, and 16 with -m64), the directive has the effect of natural alignment. Also, if n is omitted, member alignment reverts to the natural alignment boundaries.

Note that when you use #pragma pack, the alignment of the packed structure or union itself is the same as its more strictly aligned member. Therefore any declaration of that struct or union will be at the pack alignment. For example, a struct with only chars has no alignment restrictions, whereas a struct containing a double would be aligned on an 8-byte boundary.

Use #pragma pack(push[, n ]) to push the current alignment setting onto an internal stack and optionally set the new alignment with the given value of n .

Use #pragma pack(pop) to set the alignment to the last value saved onto the internal stack via a previous push and remove, or pop, that stack entry.

2.12.20 pipeloop

This pragma accepts a positive constant integer value, or 0, for the argument n . This pragma specifies that a loop can be pipelined and the minimum dependence distance of the loop-carried dependence is n . If the distance is 0, then the loop is effectively a Fortran-style doall loop and should be pipelined on the target processors. If the distance is greater than 0, then the compiler (pipeliner) will only try to pipeline n successive iterations. The compiler takes advantage of this information at optimization level of 3 or above.

The scope of this pragma begins with the pragma and ends with whichever of the following situations occurs first: the beginning of the next block, the next for loop within the current block, the end of the current block. The pragma applies to the next for loop prior to the end of the pragma’s scope.

2.12.21 rarely_called

This pragma provides a hint to the compiler that the specified functions are not called frequently. The compiler can then perform profile-feedback style optimizations on the call-sites of such routines without the overhead of a profile-collections phase. Because this pragma is a suggestion, the compiler can choose not perform any optimizations based on this pragma.

The specified functions must be declared with a prototype or empty parameter list prior to this pragma. The following example shows #pragma rarely_called:

2.12.22 redefine_extname

This pragma causes every externally defined occurrence of the name old_extname in the object code to be replaced by new_extname . As a result, the linker sees the name new_extname only at link time. If #pragma redefine_extname is encountered after the first use of old_extname , as a function definition, an initializer, or an expression, the effect is undefined. (This pragma is not supported in –Xs mode).

When #pragma redefine_extname is available, the compiler provides a definition of the predefined macro __PRAGMA_REDEFINE_EXTNAME, which you can use to write portable code that works both with and without #pragma redefine_extname.

#pragma redefine_extname provides an efficient means of redefining a function interface when the name of the function cannot be changed. For example, if the original function definition must be maintained in a library for compatibility with existing programs along with a new definition of the same function for use by new programs, you can add the new function definition to the library by a new name. Subsequently, the header file that declares the function uses #pragma redefine_extname so that all of the uses of the function are linked with the new definition of that function.

2.12.23 returns_new_memory

This pragma asserts that the return value of the specified functions does not alias with any memory at the call site. In effect, this call returns a new memory location. This information enables the optimizer to better track pointer values and clarify memory location, resulting in improved scheduling, pipelining, and parallelization of loops. However, if the assertion is false, the behavior of the program is undefined.

This pragma is permitted only after the specified functions are declared with a prototype or empty parameter list as shown in the following example.

2.12.24 unknown_control_flow

To describe procedures that alter the flow graphs of their callers, use the #pragma unknown_control_flow directive. Typically, this directive accompanies declarations of functions like setjmp(). On Oracle Solaris systems, the include file <setjmp.h> contains the following code:

Other functions with properties like those of setjmp() must be declared similarly.

In principle, an optimizer that recognizes this attribute could insert the appropriate edges in the control flow graph, thus handling function calls safely in functions that call setjmp() while maintaining the ability to optimize code in unaffected parts of the flow graph.

The specified functions must be declared with a prototype or empty parameter list prior to this pragma.

2.12.25 unroll

This pragma accepts a positive constant integer value for the argument unroll_factor . Setting unroll_factor other than 1 serves as a suggestion to the compiler that the specified loop should be unrolled by the given factor when possible. If unroll_factor is 1, this directive commands the compiler that the not to unroll the loop. The compiler takes advantage of this information at optimization levels 3 or above.

The scope of this pragma begins with the pragma and ends with whichever of the following situations occurs first: the beginning of the next block, the next for loop within the current block, the end of the current block. The pragma applies to the next for loop prior to the end of the pragma’s scope.

2.12.26 warn_missing_parameter_info

When you specify #pragma warn_missing_parameter_info, the compiler issues a warning for a function call whose function declaration contains no parameter type information. Consider the following example:

#pragma no_warn_missing_parameter_info turns off the effect of any previous #pragma warn_missing_parameter_info.

By default, #pragma no_warn_missing_parameter_info is in effect.

2.12.27 weak

This pragma defines a weak global symbol. It is used mainly when building libraries. The linker does not produce an error message if it is unable to resolve a weak symbol.

defines symbol to be a weak symbol. The linker does not produce an error message if it does not find a definition for symbol .

defines symbol1 to be a weak symbol, which is an alias for the symbol symbol2 . This form of the pragma can only be used in the same translation unit where symbol2 is defined, either in the source files or one of its included header files. Otherwise, a compilation error will result.

If your program calls but does not define symbol1 and symbol1 is a weak symbol in a library being linked, the linker uses the definition from that library. However, if your program defines its own version of symbol1 , then the program’s definition is used and the weak global definition of symbol1 in the library is not used. If the program directly calls symbol2 , the definition from the library is used. A duplicate definition of symbol2 causes an error.

Что делает #pragma hdrstop

If a C or C++ file contains a hdrstop pragma when compiled with either /YX or /Yc, the compiler saves the state of the compilation up to the location of the pragma. The compiled state of any code that follows the pragma is not saved.

Всё равно неясно для чего это нужно и нужно ли вообще.

Собственно тоже сталкнулся с этим, Быдлер постоянно сует ее в чистых проектах, что делает сия директива? Я ее просто удаляю, но может она зачем-то нужна?

Типа PCH, тока не понятно, для чего так, если есть нормальные средства для этого.

MAMONT-92 [REBORN]
А ты загугли.

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

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

Wraith
> А ты загугли.
а я через гуголь и попал сюда.

MAMONT-92 [REBORN]
> кароче можно просто удалять и не волнует, так?
если стоит вначале, и выше только #include ". /precompiled.h" — Да

#pragma hdrstop — своеобразный аналог PCH — все заинклуденные хидеры до #pragma hdrstop будут прекомпилированы и закешены, если где еще в C/CPP файлах компилятор встретит ту же последовательность хидеров до #pragma hdrstop — то заюзается уже скомпиленый кеш.

А в небыдлер-м$ $тудии с этой же целью заставляют инклудить stdafx.h, причём принудительно. Так-то!

Sbtrn. Devil
это был один из агрументов, почему ушел со студии, там без этой хрени ничего не компилилось.

MAMONT-92 [REBORN]
> это был один из агрументов, почему ушел со студии, там без этой хрени ничего не
> компилилось.
Бедняжка. Хоть не на линукс перешел?

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

entryway
> Бедняжка. Хоть не на линукс перешел?
Линукс — это поделка собранная на коленке в туалете полная всевозможных костылей.

MAMONT-92 [REBORN]
> Sbtrn. Devil
> > А в небыдлер-м$ $тудии с этой же целью заставляют инклудить stdafx.h, причём принудительно. Так-то!
> это был один из агрументов, почему ушел со студии, там без этой хрени ничего не компилилось.
пф-пф-пф.

Sbtrn. Devil
> А в небыдлер-м$ $тудии с этой же целью заставляют инклудить stdafx.h, причём принудительно. Так-то!

Ну что за бред. Никто никого не заставляет, в чистом проекте вообще нет никаких stdafx.h. Я в каждом новом проекте сам создаю stdafx.h такой, какой мне нужен.
А если уж так хочется создать проект визардом и при этом убрать stdafx.h и при этом не хочется убирать галочку ответственную за это (нафига тока не ясно), то при желании парой кликов PCH отключается.

MAMONT-92 [REBORN]
> это был один из агрументов, почему ушел со студии, там без этой хрени ничего не компилилось.

Лол. Можно это просто не использовать.
Но так как эта вещь очень полезна, то не вижу смысла её не использовать.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *