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

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

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

Из чего некоторые другие использования #pragma это полезно, но не широко известное?

Править:

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

С каким кодом имеют Вас записанный #pragma Вы нашли полезным?

.

Ответы сразу:

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

  • Jason предложил то использование #pragma once или #ifndef #define #endif позволил бы более быстрой компиляции в крупном масштабе систему. Steve вскочил и поддерживал это.
  • 280Z28 ступил вперед и упомянул это #pragma once предпочтен для MSVC, в то время как компилятор GCC оптимизирован для #ifndef #define #endif. Поэтому нужно использовать также, не оба.
  • Jason, также упомянутый о #pragma pack для совместимости на уровне двоичных кодов и Clifford против этого, из-за возможных проблем мобильности и порядка байтов. Evan обеспечил пример кода, и Dennis сообщил, что большинство компиляторов осуществит дополнение для выравнивания.
  • sblom предложил использовать #pragma warning изолировать настоящие проблемы и отключить предупреждения, которые были уже рассмотрены.
  • Evan предложил использовать #pragma comment(lib, header) для легкого портирования между проектами, не сбрасывая Ваш IDE снова. Конечно, это не слишком портативно.
  • sbi обеспечил остроту #pragma message прием для пользователей VC к выходным сигналам с информацией о номере строки. James взял один шаг вперед и позволяет error или warning соответствовать сообщениям MSVC, и обнаружится соответственно, такие как Ошибочный Список.
  • Chris предоставляют #pragma region смочь свернуть код с пользовательским сообщением в MSVC.

Стоп, ожидайте, что, если я хочу отправить о не использовании #pragmas если необходимый?

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

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

22
задан 19 revs, 4 users 73% 23 May 2017 в 10:26
поделиться

8 ответов

У каждой прагмы есть свои применения, иначе их бы там вообще не было.

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

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

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

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

прагма «error» и «message» очень удобны, особенно внутри блоков условного соответствия (например, «error: сборка 'Release for ePhone' не реализована», message: «в этой сборке включен дополнительный код отладки и профилирования») )

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

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

12
ответ дан 29 November 2019 в 04:17
поделиться

В 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): we need to look at this code
c:\...\test.cpp(10): and at this, too

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

4
ответ дан 29 November 2019 в 04:17
поделиться

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

У других компиляторов будут совершенно другие списки.

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

3
ответ дан 29 November 2019 в 04:17
поделиться

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

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

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

4
ответ дан 29 November 2019 в 04:17
поделиться
#pragma comment(lib, "WS2_32.lib")

для проектов, использующих библиотеку winsock

0
ответ дан 29 November 2019 в 04:17
поделиться

Это очень похоже на ответ 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 ++, поэтому ошибки, предупреждения и сообщения отображаются в списке ошибок вместе со всеми другими предупреждениями и ошибками компилятора.

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

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

8
ответ дан 29 November 2019 в 04:17
поделиться

По возможности избегайте #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 для совместимости с MS, поэтому приведенный выше пример несколько надуманный, но это не относится к более ранним версиям GCC, которые все еще могут использоваться, или к другим компиляторам.

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

Чтобы ответить на ваш исходный вопрос: « Какой код вы написали с помощью #pragma, который вы сочли полезным? »; Возможно, вам лучше рассмотреть полезные способы избежания прагм?

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

9
ответ дан 29 November 2019 в 04:17
поделиться

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

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

#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
9
ответ дан 29 November 2019 в 04:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: