#pragma once
和
#ifndef __HEAD_FILE_NAME__
#define __HEAD_FILE_NAME__
#endif
都可以用于 C/C++ 中防止头文件被多次包含。也是预编译的重要指令。
1 条件编译
直接上代码:
#include <cstdio>
#define CONDITION
//example 1:
#ifdef CONDITION
#pragma message("Hello I am a boy.")
#define VALA (1)
#endif
#ifndef CONDITION
#pragma message("Hello I am a boy.")
#define VALB (2)
#else
#pragma message("Hello I am a girl.")
#define VALB (3)
#endif
//example 2:
#if defined(CONDITION1)
#define VALC (4)
#elif defined(CONDITION2)
#define VALC (5)
#elif defined(CONDITION3)
#define VALC (6)
#else
#define VALC (7)
#endif
int main()
{
int a = VALA;
int b = VALB;
int c = VALC;
}
编译器预编译替换后的代码:
#include <cstdio>
int main()
{
int a = (1);
int b = (3);
int c = (7);
return 0;
}
推荐网站可以直接看预编译后的代码:C++ Insights
2 #pragma once
#pragma once 是一种编译器特定的指令,它告诉编译器只包含这个指令的文件一次,不需要再次包含。它是一种比较简洁方便的方式来避免头文件的重复包含问题。
#pragma once 的好处是它可以减少编译时间,因为编译器不需要再去检查这个文件是否已经被包含过。
#pragma once 是编译器扩展,不是标准的 C/C++ 语法,因此可能不是所有编译器都支持。
3 两者PK
#ifndef 结构中所定义的宏一般其实就是头文件的文件名全大写,如果项目较大,或者引入第三方库,可能会出现两个名字相同但是内容不同的头文件,这时就会出现一定的问题。会让一个头文件失效。而pragma就不会出现这样的问题。因为#pragma once 指令通常会使用头文件路径和文件名来作为头文件的唯一标识符。因此,如果两个头文件具有相同的文件名但位于不同的路径下,则它们会被视为不同的头文件,各自会被编译器包含一次。
虽然#pragma once 的工作原理类似于传统的头文件保护宏(例如 #ifndef、#define、#endif 结构),但是它是由编译器直接处理的,而不是由预处理器处理的。这使得它在一定程度上比传统的头文件保护更加高效。
需要注意的是,#pragma once 是编译器扩展,不是标准的 C/C++ 语法,因此可能不是所有编译器都支持。但是,大多数主流的编译器(如 GCC、Clang 和 MSVC)都支持 #pragma once,因此在实际项目中,它通常是一个方便且可靠的选择。
4 #pragma其他用法
#pragma 指令用于设定编译器的状态或者是指示编译器完成一些特定的动作。常用参数如下:
#pragma message
在编译信息窗口输出相应信息,用法为
#pragma message("消息文本")
#pragma code_seg
一般用于设置程序中函数代码存放的代码段,在开发驱动程序时使用较多。
#pragma code_seg(["section-name", ["section-class"]])
#pragma once
头文件只被编译一次。
#pragma hdrstop
表示预编译头文件到此为止,后面的文件不再进行预编译。
#pragma resource
#pragma resource "*.dfm"
表示把*.dfm文件中的资源加入项目。
#pragma warning
用法示例
#pragma warning(disable:4507 34) //不显示4507和34号警告信息
#pragma warning(once:4385) //4385号警告信息仅报告一次
#pragma warning(error:164) //把164号警告信息作为一个错误。
#pragma comment
该指令将一个注释记录放入一个对象文件或可执行文件中。常用lib参数,帮我们连入一个库文件。比如:
#pragma comment(lib, "user32.lib")
该指令用来将user32.lib 库文件加入到本工程中。
linker参数,将一个链接选项放入目标文件中,你可以使用这个指令来代替由命令行传入的或者在开发环境中设置的链接选项,你可以指定/include 选项来强制包含某个对象,例如:
#pragma comment(linker, "/include:__mySymbol")
#pragma pack
内存对齐
#pragma pack(1)
struct
{
......
}
#pragma pack()