C语言#pragma编译器指令常用语法1.#ifdef GNUC 表明使用的是GUN 编译器。 eg. 2.#pragm
C和C++中有一些预定义标识和预定义宏,无论阅读开源代码还是自己编写代码都很有用,一起来看一下:
1.#ifdef GNUC 表明使用的是GUN 编译器。
eg.
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic push
#endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
2.#pragma GCC diagnostic push 和 #pragma GCC diagnostic pop
用途
#pragma GCC diagnostic push
:用于记录当前的诊断状态
#pragma GCC diagnostic pop
:用于恢复诊断状态
用法
#pragma GCC diagnostic push
#pragma GCC diagnostic [kind] "option"
/* code */
#pragma GCC diagnostic push
示例
#pragma GCC diagnostic ignored "option"
:忽略option诊断信息;
#pragma GCC diagnostic error "option"
:将Option诊断视为错误;
#pragma GCC error "message"
:Generates an error message. This pragma is considered to indicate an error in the compilation, and it will be treated as such.
3.#pragma GCC visibility pop
#pragma GCC visibility
是一种特定的编译器指令(pragma)
,用于GNU GCC(GNU Compiler Collection)
和其他兼容GCC的编译器中,以控制符号(symbols)的可见性。在编译大型库或应用程序时,这个特性特别有用,因为它可以帮助减少生成的二进制文件的大小,同时提高性能,因为减少了需要被动态链接器(dynamic linker)处理的符号数量。
在GCC中,visibility属性可以被设置为几个不同的值,包括default、internal、hidden和protected。这些值控制了符号在共享库中的可见性,即它们是否可以被库外部的代码看到和链接。
default
:符号是可见的,除非另有指定。hidden
:符号在库内部可见,但在库外部不可见。internal
:与hidden类似,但有一些细微的差别,主要用于优化内部链接。protected
:在GCC中,这个值主要用于特定场景,与default和hidden不同,但它在标准的GCC使用中不常见。
#pragma GCC visibility push, pop
指令允许开发者保存和恢复当前的可见性设置。这在复杂的项目中特别有用,当你需要在代码的某个部分改变符号的可见性,但又不想影响到其他部分时。
#pragma GCC visibility push(hidden)
:将当前的可见性设置(通常是default)保存,并将可见性设置为hidden。这会影响随后定义的所有符号,直到遇到pop指令。
#pragma GCC visibility pop
:恢复之前通过push指令保存的可见性设置。
例如,如果你正在编写一个库,并希望隐藏大多数内部符号,但想要临时暴露一些特定的函数或变量,你可以使用push和pop来管理这些更改,而不会影响库的其他部分。
#pragma GCC visibility push(hidden)
// 隐藏大部分符号
void internal_function() {
// ...
}
#pragma GCC visibility pop
// 这里的符号将恢复到push之前的可见性设置,通常是default
void public_function() {
// ...
}
这样,
internal_function
将是隐藏的,而
public_function
将是可见的,即使它们都位于同一个源文件或库中。
4.#pragma warning(disable : 4996)
禁用警告
#pragma warning(disable : 4996)
这会禁用编号为 4996 的警告。
恢复警告
#pragma warning(default : 4996)
这会将编号为 4996 的警告恢复到默认状态。
5.内存对齐#pragma pack(push, 1)和#pragma pack(pop)
#pragma pack(push, 1)
struct MyStruct {
char a;
int b;
};
#pragma pack(pop)
这将设置结构体的内存对齐为 1 字节,然后通过 #pragma pack(pop)
恢复到之前的设置。
6.#### #pragma once
#pragma once
是一个非标准但广泛支持的预处理器指令,用来保证头文件的内容只被包含(include)一次,以防止头文件的内容在同一编译单元中多次定义。这有助于防止编译错误和链接问题,如重复定义等。
如何使用
#pragma once
:
你只需要在头文件的最开始添加这个指令,如下所示:
#pragma once
// 头文件的内容...
当预处理器看到这个指令时,它会记住这个头文件已经被包含过,并防止它在同一编译单元中被再次包含。
作用:
- 避免重复包含:无需使用传统的宏定义来防止头文件被多次包含。
- 简洁:只需要一行代码,比传统的
#ifndef
、#define
、#endif
宏防卫更加简洁。 - 可移植性:尽管
#pragma once
不是C/C++标准的一部分,但它被大多数现代编译器所支持。
#pragma once
和 Include Guards 的比较:
传统的方法是使用宏定义(也称为 include guards)来防止头文件被多次包含:
#ifndef MY_HEADER_H
#define MY_HEADER_H
// 头文件的内容...
#endif // MY_HEADER_H
这种方法是标准的,也被所有的 C/C++ 编译器支持。但是,它需要多行代码,并且需要为每个头文件提供一个唯一的宏名称。
#pragma once
提供了一个更为简单的替代方案,但必须保证编译器是否支持它。大多数现代编译器(如 GCC、Clang、MSVC)都支持这个指令。
转载自:https://juejin.cn/post/7425467139603759156