Какой код вы написали с #pragma, вы нашли полезные? [закрыто

StackOverflow https://stackoverflow.com/questions/2703528

Вопрос

Я никогда не понимал необходимость #pragma once когда #ifndef #define #endif Всегда работает.

Я видел использование #pragma comment Чтобы связаться с другими файлами, но настройка настроек компилятора было проще с IDE.

Каковы другие другие употребления #pragma Это полезно, но не широко известно?

Редактировать:

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

Какой код вы написали с #pragma Вы нашли полезные?

.

Ответы на первый взгляд:

Благодаря всем, кто ответил и / или прокомментировал. Вот краткое изложение некоторых входов, которые я нашел полезным:

  • Джейсон предложил использовать #pragma once или #ifndef #define #endif позволит быстрее компилировать широкомасштабную систему. Стив прыгнул и поддержал это.
  • 280Z28 ступился вперед и упомянул, что #pragma once предпочтительно для MSVC, в то время как компилятор GCC оптимизирован для #ifndef #define #endif. Отказ Поэтому нужно либо использовать, а не оба.
  • Джейсон также упомянул о #pragma pack Для бинарной совместимости и Clifford против этого из-за возможных вопросов переносимости и целесообразности. EVAN предоставил пример кода, и Деннис сообщил, что большинство компиляторов приведут кровя для выравнивания.
  • Sblom предложил использовать #pragma warning Чтобы изолировать реальные проблемы и отключить предупреждения, которые уже были рассмотрены.
  • Эван предложил использовать #pragma comment(lib, header) Для простого портирования между проектами, не повторная настройка вашей IDE снова. Конечно, это не слишком портативный.
  • SBI предоставил нефте #pragma message Хитрость для пользователей VC для вывода сообщений с информацией о номере строки. Джеймс взял еще один шаг вперед и позволяет error или warning Чтобы сопоставить сообщения MSVC и появится соответствующим образом, например, список ошибок.
  • Крис предоставлен #pragma region Чтобы быть в состоянии свернуть код с пользовательским сообщением в MSVC.

Вау, подожди, что если я хочу опубликовать нет используя #pragmas, если не обязательно?

  • Клиффорд опубликовал с другой точки зрения о нет использовать #pragma. Отказ Слава.

Я добавлю больше в этот список, если зарезервирует желание публиковать ответ. Всем спасибо!

Это было полезно?

Решение

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

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

Редактировать: Чтобы ответить на комментарии: представьте, что у вас есть заголовочный файл 200 кБ. С «один раз» компилятор загружает это один раз, а затем знает, что ему не нужно включать заголовок вообще в следующий раз, когда он видит его ссылки. С # Если он должен загрузить и разбирать весь Файл каждый раз, чтобы определить, что весь код отключен IF, потому что IF должен быть оценен каждый раз. На большой кодовой базе это может привести к значительной разнице, хотя в практическом выражении (особенно с предложенными заголовками) это не может.

Прагма «Пакет» бесцензируется, когда вам нужна бинарная совместимость для структуров.

Редактировать: Для двоичных форматов выставляют байты, которые вы поставляете, должны точно соответствовать требуемому формату - если ваш компилятор добавляет некоторую прокладку, он привернут выравнивание данных и повредить данные. Таким образом, для сериализации к двоичному формату файла или структуры в памяти, которую вы хотите пройти к / из вызова ОС или пакета TCP, используя структуру, которая отображается непосредственно в двоичном формате, гораздо более эффективно, чем «пользовательская сериализация» ( Написание полей один за другим) - он использует меньше кода и работает намного быстрее (необходимо в встроенных приложениях, даже сегодня).

Прагма «Ошибка» и «Сообщение» очень удобны, особенно внутри условных блоков заседаний (например, ошибка: «Выпуск для сборки ePhone» не используется «, сообщение:« В этой сборке «)

Прагма «Предупреждение» (особенно с push & Pop) очень полезна для временного отключения раздражающих предупреждений, особенно если в том числе плохо написанные сторонние заголовки (которые полны предупреждений) - особенно если вы строятся с предупреждением 4.

Редактировать: Хорошая практика - добиться нулевых предупреждений в сборке, чтобы приступить к предупреждению, вы замечаете его и сразу исправить. Вы должны конечно исправить все предупреждения в вашем собственном коде. Однако некоторые предупреждения просто не могут быть исправлены, и не говорите вам ничего важного. Кроме того, при использовании сторонних библиотек, где вы не можем Измените свой код, чтобы исправить предупреждения, вы можете удалить «спам» из ваших сборки, отключая предупреждения библиотеки. Использование Push / Pop позволяет выборочно отключить предупреждения только во время библиотеки, так что ваш собственный код все еще проверяется компилятором.

Другие советы

Как вы упоминали, я видел Pragmas в Visual C ++, который скажет ему ссылку на определенную библиотеку во время ссылки. Удобство для библиотеки, которая нуждается в Winsock Libs. Таким образом, вам не нужно изменять настройки проекта, чтобы получить его связанным. бывший: #pragma comment(lib,"wsock32.lib"). Отказ Мне это нравится, потому что он связывает код, который нуждается в .Lib с ним, плюс, как только вы поместите это в файл, вы не можете забывать его, если вы повторно используете этот код в другом проекте.

Кроме того, Pragmas для упаковки структур данных часто полезны, параметрически с системами и сетевым программированием, где смещения членов данных имеют значение. бывший:

#pragma pack(push, 1) // packing is now 1
struct T {
char a;
int b;
};
#pragma pack(pop) // packing is back to what it was

// sizeof(T) == sizeof(char) + sizeof(int), normally there would be padding between a and b

Вам следует избегать #pragma, где это возможно. #PRAGMA Компиляторы директивы всегда Компилятор, специфичный и, следовательно, не портативный. Они должны рассматриваться как последний курорт.

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

#if _MSC_VER
  #pragma PACK(push,1)
#elif   __GNUC__
  // nothing to do here
#else
  #error "Unsupported compiler"
#endif
  struct sPackedExample
  {
      // Packed structure members
#if _MSC_VER
  } ;                              // End of MSVC++ pragma packed structure
  #pragma pack (pop)
#elif   __GNUC__
  }__attribute__((__packed__)) ;   // End of GNU attribute packed structure
#endif

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

Примечание:] GCC 4.x делает на самом деле поддержку #Pragma Pack для совместимости MS, поэтому вышеприведенный пример в некоторой степени урван, но это не относится к более ранним версиям GCC, которые все еще могут быть использованы или другими компиляторами.

«#PRAGMA один раз» особенно проблема, поскольку для компилятора, который не поддерживает его, код будет во всех, кроме самых тривиальных случаев, пробившихся при предварительно обработке. Чем больше добросовестно, но портативное решение должно быть предпочтительным. Применение Visual C ++ и генерация кода «Волшебники» могут использовать его, но часто такой код не является портативным в любом случае. Вы должны знать при использовании такого кода, который вы по существу блокируете свой проект в инструменты Microsoft. Это может быть не проблема, но я бы не рекомендовал использовать директиву в своем собственном коде.

Чтобы решить ваш оригинальный вопрос: "Какой код вы написали с #pragma, вы нашли полезные?«Если вы предпочитаете рассмотреть полезные способы избежать прагма?

Это не должно быть вопрос о "полезность" скорее "необходимость«. Например, несколько встроенных системных компиляторов, которые я использовал, используйте директивы #PRAGMA, которые указывают, что функция представляет собой рутину обслуживания прерывания, и, следовательно, имеет другой код входа / выхода, а во многих случаях работает в другом стеке. Избегать таких Прагма потребует знания языка ассемблера цели и будет менее эффективным, когда C Code Code вызывается для обработки прерывания.

Это очень похоже на Ответ SBI Но имеет некоторые дополнительные функции.

Я использовал следующий набор макросов с #pragma message На Microsoft Visual C ++ в течение некоторого времени:

#define EMIT_COMPILER_WARNING_STRINGIFY0(x) #x
#define EMIT_COMPILER_WARNING_STRINGIFY1(x) EMIT_COMPILER_WARNING_STRINGIFY0(x)
#define EMIT_COMPILER_MESSAGE_PREFACE(type) \
    __FILE__ "(" EMIT_COMPILER_WARNING_STRINGIFY1(__LINE__) "): " type ": "

#define EMIT_COMPILER_MESSAGE EMIT_COMPILER_MESSAGE_PREFACE("message")
#define EMIT_COMPILER_WARNING EMIT_COMPILER_MESSAGE_PREFACE("warning")
#define EMIT_COMPILER_ERROR   EMIT_COMPILER_MESSAGE_PREFACE("error")

Используется в качестве:

#pragma message(EMIT_COMPILER_WARNING "This code sucks; come back and fix it")

который приводит к следующему тексту в выходе сборки:

1>z:\sandbox\test.cpp(163): warning : This code sucks; come back and fix it

Выходные данные соответствует формате сообщений об ошибках Visual C ++, поэтому ошибки, предупреждения и сообщения отображаются в списке ошибок вместе со всеми другими предупреждениями и ошибками компилятора.

Макрос «Предупреждение» гораздо более отвратительно, чем простой // todo fix this В коде, и помогает мне не забыть вернуться и исправить что-то.

Макрос «Ошибка» полезен, потому что он вызывает сбой компиляции, но не сразу останавливает процесс компиляции, как #error Директива делает.

С VC я использовал это в прошлом:

#define STRINGIFY( L )       #L
#define MAKESTRING( M, L )   M(L)
#define SHOWORIGIN           __FILE__ "("MAKESTRING( STRINGIFY, __LINE__) "): "

// then, later...

#pragma message( SHOWORIGIN "we need to look at this code" )
// ...
#pragma message( SHOWORIGIN "and at this, too" )

Выход:

C:  ...  Test.CPP (8): Нам нужно посмотреть на этот код C:  ...  Test.CPP (10): И при этом тоже

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

В Visual Studio C ++ Preprocessor также поддерживает

#pragma region Some Message Goes Here
...
#pragma endregion

Затем вы можете разрушить этот регион в редакторе кода, чтобы он показал только вышеуказанное сообщение. Это аналогично синтаксису региона C #.

#pragma По определению предназначен для директивных директоров / предварительно процессоров, которые могут быть конкретными платформой. Похоже, вы говорите о MSVC ++ #Pragmas здесь. Ты можешь найти их полный список, или Полный список для GCC.

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

Вернуться на MSVC ++, однако, одна из моих любимых прагма #pragma warning. Отказ Я обычно строю код с «лечением предупреждений как ошибки», а затем хирургически отключили определенные предупреждения, которые я проверял, чтобы убедиться, что не вызывает проблем. Это позволяет компилятору помочь мне обнаружить больше проблем во время сборки.

#pragma comment(lib, "WS2_32.lib")

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top