您使用#pragma 编写了哪些您认为有用的代码?

发布于 2024-08-30 02:36:28 字数 1488 浏览 6 评论 0 原文

#pragma Once 的需要>#ifndef #define #endif 始终有效。

我见过使用 #pragma comment 来链接其他文件,但使用 IDE 来设置编译器设置会更容易。

#pragma 还有哪些有用但不广为人知的用法?

编辑:

只是在#pragma指令列表之后。也许我应该稍微重新表述一下这个问题:

您使用 #pragma 编写了哪些代码,您认为有用?

答案一览:

感谢所有回答和/或评论的人。以下是我发现有用的一些输入的摘要:

  • Jason 建议使用 #pragma Once#ifndef #define #endif 将允许在大型系统上更快地进行编译。史蒂夫加入并支持这一点。
  • 280Z28 率先提到,#pragma Once 是 MSVC 的首选,而 GCC 编译器则针对 #ifndef #define #endif 进行了优化。因此,应该使用其中之一,而不是同时使用两者。
  • Jason 还提到了用于二进制兼容性的#pragma pack,而 Clifford 反对这一点,因为可能存在可移植性和字节顺序问题。 Evan 提供了示例代码,Dennis 告知大多数编译器将强制执行填充以进行对齐。
  • sblom 建议使用#pragma warning 来隔离真正的问题,并禁用已经审查过的警告。
  • Evan 建议使用 #pragma comment(lib, header) 以便在项目之间轻松移植,而无需再次重新设置 IDE。当然,这不太便携。
  • sbi 为 VC 用户提供了一个漂亮的#pragma message 技巧来输出带有行号信息的消息。 James 更进一步,允许 errorwarning 来匹配 MSVC 的消息,并且会适当地显示,例如错误列表。
  • Chris 提供了#pragmaregion 以便能够在 MSVC 中使用自定义消息折叠代码。

哇哦,等等,如果我想发布关于使用#pragmas,除非有必要怎么办?

  • Clifford 从另一个角度发布了关于使用#pragmas #pragma。荣誉。

如果 SOers 迫切需要发布答案,我会在此列表中添加更多内容。谢谢大家!

I've never understood the need of #pragma once when #ifndef #define #endif always works.

I've seen the usage of #pragma comment to link with other files, but setting up the compiler settings was easier with an IDE.

What are some other usages of #pragma that is useful, but not widely known?

Edit:

I'm not just after a list of #pragma directives. Perhaps I should rephrase this question a bit more:

What code have you written with #pragma you found useful?

.

Answers at a glance:

Thanks to all who answered and/or commented. Here's a summary of some inputs I found useful:

  • Jason suggested that using #pragma once or #ifndef #define #endif would allow faster compiling on a large-scale system. Steve jumped in and supported this.
  • 280Z28 stepped ahead and mentioned that #pragma once is preferred for MSVC, while GCC compiler is optimised for #ifndef #define #endif. Therefore one should use either, not both.
  • Jason also mentioned about #pragma pack for binary compatibility, and Clifford is against this, due to possible issues of portability and endianness. Evan provided an example code, and Dennis informed that most compilers will enforce padding for alignment.
  • sblom suggested using #pragma warning to isolate the real problems, and disable the warnings that have already been reviewed.
  • Evan suggested using #pragma comment(lib, header) for easy porting between projects without re-setting up your IDE again. Of course, this is not too portable.
  • sbi provided a nifty #pragma message trick for VC users to output messages with line number information. James took one step further and allows error or warning to match MSVC's messages, and will show up appropriately such as the Error List.
  • Chris provided #pragma region to be able to collapse code with custom message in MSVC.

Whoa, wait, what if I want to post about not using #pragmas unless necessary?

  • Clifford posted from another point of view about not to use #pragma. Kudos.

I will add more to this list if the SOers feel the urge to post an answer. Thanks everyone!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

拧巴小姐 2024-09-06 02:36:28

每个编译指示都有其用途,否则它们一开始就不会存在。

如果您知道不会将代码移植到不同的编译器,则编译指示“once”只是更少的打字和更整洁。它也应该更高效,因为编译器根本不需要解析标头来确定是否包含其内容。

编辑:回答评论:想象你有一个 200kB 的头文件。使用“once”,编译器加载一次,然后知道下次看到它被引用时根本不需要包含标头。使用 #if 时,每次都必须加载并解析整个文件,以确定所有代码都被 if 禁用,因为每次都必须评估 if。在大型代码库上,这可能会产生显着的差异,但实际上(尤其是预编译头)可能不会。

当您需要结构的二进制兼容性时,pragma“pack”非常有用。

编辑:对于二进制格式,您提供的字节必须与所需的格式完全匹配 - 如果您的编译器添加一些填充,它会搞乱数据对齐并损坏数据。因此,对于序列化为二进制文件格式或内存中结构(您希望将其传递给操作系统调用或 TCP 数据包或从操作系统调用或 TCP 数据包传递),使用直接映射到二进制格式的结构比“按成员序列化”更有效(一个接一个地编写字段) - 它使用更少的代码并且运行速度更快(即使在今天,这在嵌入式应用程序中也是必不可少的)。

pragma“error”和“message”非常方便,特别是在条件编译块内(例如“错误:'Release for ePhone'构建未实现”,消息:“在此构建中启用了额外的调试和分析代码”)

pragma“警告”(特别是对于推送和弹出)对于暂时禁用烦人的警告非常有用,尤其是当包含写得不好的第三方标头(充满警告)时 - 特别是如果您使用警告级别 4 进行构建。

编辑:好的做法是在构建中实现零警告,以便在发生警告时您会注意到它并立即修复它。您当然应该修复自己代码中的所有警告。但是,有些警告根本无法修复,并且不会告诉您任何重要信息。此外,当使用第三方库时,您无法更改其代码来修复警告,您可以通过禁用库的警告来从构建中删除“垃圾邮件”。使用push/pop允许您仅在库包含期间有选择地禁用警告,以便编译器仍然检查您自己的代码。

Every pragma has its uses, or they wouldn't be there in the first place.

pragma "once" is simply less typing and tidier, if you know you won't be porting the code to a different compiler. It should be more efficient as well, as the compiler will not need to parse the header at all to determine whether or not to include its contents.

edit: To answer the comments: imagine you have a 200kB header file. With "once", the compiler loads this once and then knows that it does not need to include the header at all the next time it sees it referenced. With #if it has to load and parse the entire file every time to determine that all of the code is disabled by the if, because the if must be evaluated each time. On a large codebase this could make a significant difference, although in practical terms (especially with precompiled headers) it may not.

pragma "pack" is invaluable when you need binary compatibility for structs.

Edit: For binary formats, the bytes you supply must exactly match the required format - if your compiler adds some padding, it will screw up the data alignment and corrupt the data. So for serialisation to a binary file format or an in-memory structure that you wish to pass to/from an OS call or a TCP packet, using a struct that maps directly to the binary format is much more efficient than 'memberwise serialisation' (writing the fields one by one) - it uses less code and runs much faster (essential in embedded applications, even today).

pragma "error" and "message" are very handy, especially inside conditional compliation blocks (e.g. "error: The 'Release for ePhone' build is unimplemented", message: "extra debugging and profiling code is enabled in this build")

pragma "warning" (especially with push & pop) is very useful for temporarily disabling annoying warnings, especially when including poorly written third-party headers (that are full of warnings) - especially if you build with warning level 4.

edit: Good practice is to achieve zero warnings in the build so that when a warning occurs you notice it and fix it immediately. You should of course fix all warnings in your own code. However, some warnings simply cannot be fixed, and do not tell you anything important. Additionally, when using third party libraries, where you cannot change their code to fix the warnings, you can remove the 'spam' from your builds by disabling the library's warnings. Using push/pop allows you to selectively disable the warnings only during the library includes, so that your own code is still checked by the compiler.

蓝梦月影 2024-09-06 02:36:28

正如您所提到的,我在 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

As you've mentioned I've seen pragmas in visual c++ which tell it to link to a certain library during link time. Handy for a library which needs winsock libs. This way you don't need to modify the project settings to get it linked it. ex: #pragma comment(lib,"wsock32.lib"). I like this because it associates the code that needs the .lib with it, plus once you put that in the file, you can't forget it if you reuse that code in another project.

Also, pragmas for packing of data structures are often useful, pareticually with systems and network programming where the offsets of data members matter. ex:

#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
悲喜皆因你 2024-09-06 02:36:28

您应该尽可能避免#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 来说,

情况并非如此,或者其他编译器尤其有问题,因为对于不支持它的编译器来说,在大多数情况下,代码在预处理时都会中断。更冗长但可移植的解决方案应该是首选,Visual C++ 的应用程序和代码生成“向导”可能会使用它,但通常此类代码在任何情况下都是不可移植的。请注意,使用此类代码时,您实际上将项目锁定在 Microsoft 的工具中。这可能不是问题,但我不建议在您自己的代码中使用该指令。

解决您最初的问题:“您认为有用的 #pragma 编写了哪些代码?”;也许您应该考虑避免使用实用程序的有用方法?

也许这不应该是“有用性”的问题,而应该是“必要性”的问题。例如,我使用过的许多嵌入式系统编译器,使用#pragma指令来指定函数是中断服务例程,因此具有不同的进入/退出代码,并且在许多情况下在不同的堆栈上运行。避免此类编译指示需要了解目标的汇编语言,并且在调用 C 代码来处理中断时效率会较低。

You should avoid #pragma wherever possible. #pragma compiler directives are always compiler specific and therefore non-portable. They should be regarded as a last resort.

Moreover, the ISO required behaviour for a compiler that encounters an unrecognised pragma is to simply ignore it. This it may do silently without warning, so if the directive is essential to the correct operation of your code, it may compile but fail to run as expected when compiled with a different compiler. GCC for examples uses very few pragmas, and primarily only for target specific compiler behaviour or compatability with some other compilers. Consequently if you want to ensure portability you end up with constructs like:

#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

It is a mess, you rapidly cannot see the wood for the trees and the problem becomes worse as you add support for more compilers (which in turn requires knowledge of the pre-defined macros identifying the compiler.

[note:]GCC 4.x does in fact support #pragma pack for MS compatibility, so the above example is somewhat contrived, but this is not true of earlier versions of GCC that may still be in use, or other compilers.

'#pragma once' is particularly problematic, since for a compiler that does not support it, the code will in all but the most trivial cases break when preprocessed. The more verbose but portable solution should be preferred. Visual C++'s application and code generation 'wizards' may use it, but often such code is non-portable in any case. You should be aware when using such code that you are essentially locking your project into Microsoft's tools. This may not be a problem, but I would not recommend using the directive in your own code.

To address your original question: "What code have you written with #pragma you found useful?"; you should rather be considering useful ways of avoiding pragmas perhaps?

It should not perhaps be a question of "usefulness" but rather "necessity". For example a number of embedded systems compilers I have used, use #pragma directives to specify that a function is an interrupt service routine, and therefore has different entry/exit code, and in many cases operates on a different stack. Avoiding such a pragma would require knowledge of the target's assembler language, and would be less efficient when C code is called to handle the interrupt.

微暖i 2024-09-06 02:36:28

这与 sbi 的答案非常相似< /a> 但还有一些附加功能。

我在 Microsoft Visual C++ 上使用以下一组带有 #pragma message 的宏已经有一段时间了:

#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”宏很有用,因为它会导致编译失败,但不会像 #error 指令那样立即停止编译过程。

This is very similar to sbi's answer but has some additional features.

I've used the following set of macros with #pragma message on Microsoft Visual C++ for some time:

#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")

Used as:

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

which results in the following text in the build output:

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

The output matches the Visual C++ error message format, so errors, warnings, and messages show up in the Error List along with all the other compiler warnings and errors.

The "warning" macro is far more obnoxious than a simple // todo fix this in the code, and helps me to remember to come back and fix something.

The "error" macro is useful because it causes compilation to fail but does not immediately stop the compilation process like the #error directive does.

⒈起吃苦の倖褔 2024-09-06 02:36:28

对于 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 会将您带到正确的文件和行。

With VC, I have used this in the past:

#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" )

Output:

c:\...\test.cpp(8): we need to look at this code
c:\...\test.cpp(10): and at this, too

You can double-click on it in the output pane and the IDE takes you to the right file and line.

離人涙 2024-09-06 02:36:28

在 Visual Studio 中,C++ 预处理器也支持

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

然后您可以在代码编辑器中折叠该区域,使其仅显示上述消息。这类似于 C# 区域语法。

In Visual Studio, C++ preprocessor also supports

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

Then you can collapse this region in the code editor so that it only shows the above message. This is analogous to the C# region syntax.

蓝海 2024-09-06 02:36:28

#pragma 根据定义,适用于可能特定于平台的编译器/预处理器指令。看来您在这里谈论的是 MSVC++ #pragmas。您可以找到他们的完整列表,或< a href="http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html" rel="nofollow noreferrer">gcc 的完整列表。

其他编译器将有完全不同的列表。

不过,回到 MSVC++,我最喜欢的编译指示之一是#pragma warning。我通常会在启用“将警告视为错误”的情况下构建代码,然后通过手术禁用我已经检查过的某些警告,以确保不会引起问题。这使得编译器可以帮助我在构建过程中检测更多问题。

#pragma by definition is for compiler/pre-processor directives that may be platform specific. It looks like you're talking about MSVC++ #pragmas here. You can find their full list, or the full list for gcc.

Other compilers will have completely different lists.

Back on MSVC++, though, one of my favorite pragmas is #pragma warning. I usually build code with "treat warnings as errors" enabled, and then surgically disable certain warnings that I've reviewed to make sure aren't causing problems. This allows the compiler to help me detect more problems during build.

装迷糊 2024-09-06 02:36:28
#pragma comment(lib, "WS2_32.lib")

对于使用winsock库的项目

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

for projects using winsock library

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文