likes
comments
collection
share

C语言#pragma编译器指令常用语法1.#ifdef GNUC 表明使用的是GUN 编译器。 eg. 2.#pragm

作者站长头像
站长
· 阅读数 44

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
评论
请登录