C語(yǔ)言中#pragma的用法及使用解讀
一、比較矛盾的點(diǎn)-#pragma到底算不算關(guān)鍵字
有人認(rèn)為是算,而有人則認(rèn)為不算。
先看反對(duì)派,反對(duì)派認(rèn)為#pragma不算是C關(guān)鍵字的原因也很簡(jiǎn)單,即神并沒(méi)有認(rèn)可,那神是什么喃?即我們熟知的C89,C99,C11等協(xié)議。并沒(méi)有規(guī)定或者定義#pragma。
認(rèn)同派則認(rèn)為反對(duì)派過(guò)于迂腐,#pragma是個(gè)老伙伴了,它為c語(yǔ)言立過(guò)工,它為C語(yǔ)言流過(guò)血,就因?yàn)閰f(xié)議中沒(méi)有規(guī)定,就認(rèn)為他不是關(guān)鍵字,這樣很不好
二、閑話少說(shuō),看#pragma具體用法
pragma具體是指編譯器使用的,即這是編譯器能夠識(shí)別的和其他類型的#指令是一致的。我們最常見(jiàn)的#include和#define和undefine是一樣的。
2.1.#pragma的作用
#pragma 是 C/C++ 預(yù)處理指令之一,用來(lái)向編譯器傳遞一些平臺(tái)相關(guān)的編譯控制信息。
它的特點(diǎn)是:
- 編譯器相關(guān):不同編譯器支持的
#pragma指令不同 - 功能多樣:可以控制編譯器的警告、優(yōu)化、對(duì)齊方式、鏈接等
語(yǔ)法格式:
#pragma 指令名 [參數(shù)]
2.2. 常用的#pragma示例
(1)#pragma once—— 防止頭文件重復(fù)包含
#pragma once
- 作用:保證頭文件只被編譯一次
- 優(yōu)點(diǎn):比傳統(tǒng)的
#ifndef / #define / #endif更高效 - 缺點(diǎn):不是 C 標(biāo)準(zhǔn),但是大多數(shù)現(xiàn)代編譯器(GCC、Clang、MSVC)都支持
(2)#pragma pack—— 控制結(jié)構(gòu)體成員對(duì)齊方式
#pragma pack(push, 1) // 按1字節(jié)對(duì)齊,并保存當(dāng)前對(duì)齊狀態(tài)
struct Data {
char a;
int b;
short c;
};
#pragma pack(pop) // 恢復(fù)之前的對(duì)齊狀態(tài)- 用途:在網(wǎng)絡(luò)協(xié)議、文件格式、硬件驅(qū)動(dòng)等需要精確定義內(nèi)存布局的場(chǎng)景
#pragma pack(n)表示按 n 字節(jié)對(duì)齊(n 取 1、2、4、8 等)主要參數(shù)有push和pop和對(duì)齊的數(shù)字
(3)#pragma message—— 編譯時(shí)輸出提示信息
c運(yùn)行,這個(gè)就很簡(jiǎn)單,如果我們可以在代碼中的任何地方添加,這樣我們就能知道編譯到什么地方了
#pragma message("正在編譯 main.c...")
- 作用:在編譯過(guò)程中輸出自定義提示信息
- 常用于條件編譯檢查
(4)#pragma warning—— 控制編譯器警告
MSVC 編譯器:
#pragma warning(disable: 4996) // 禁用 4996 號(hào)警告 #pragma warning(once: 4820) // 僅顯示一次 4820 號(hào)警告 #pragma warning(error: 164) // 將 164 號(hào)警告視為錯(cuò)誤
GCC/Clang 一般用 -W、-Werror 等命令行參數(shù),不常用 #pragma warning
(5)#pragma comment—— 鏈接時(shí)加入庫(kù)或其他信息(MSVC)
#pragma comment(lib, "ws2_32.lib") // 鏈接 Winsock 庫(kù) #pragma comment(linker, "/subsystem:windows") // 設(shè)置子系統(tǒng)類型
- 僅在 Windows + MSVC 環(huán)境有效
(6)#pragma GCC diagnostic—— GCC 特定的警告控制
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
int x; // 不會(huì)產(chǎn)生未使用變量警告
#pragma GCC diagnostic pop- 作用:臨時(shí)禁用 / 開(kāi)啟某些 GCC 警告
2.3. 注意事項(xiàng)
- 可移植性差
#pragma是編譯器擴(kuò)展,不同編譯器支持的指令不同。例如#pragma once在 GCC/Clang/MSVC 可用,但在某些老編譯器可能不支持。 - 標(biāo)準(zhǔn)中未定義的
#pragma如果編譯器遇到不認(rèn)識(shí)的#pragma,會(huì)忽略該指令,不會(huì)報(bào)錯(cuò)。 - 盡量使用標(biāo)準(zhǔn)方法如果有標(biāo)準(zhǔn)方法(如
#ifndef代替#pragma once),優(yōu)先使用標(biāo)準(zhǔn)方法,提高可移植性。
總結(jié)
| #pragma 示例 | 作用 | 常見(jiàn)編譯器支持 |
|---|---|---|
| #pragma once | 防止頭文件重復(fù)包含 | GCC, Clang, MSVC |
| #pragma pack | 控制結(jié)構(gòu)體對(duì)齊 | 大多數(shù)編譯器 |
| #pragma message | 編譯時(shí)輸出信息 | 大多數(shù)編譯器 |
| #pragma warning | 控制警告 | MSVC |
| #pragma comment | 鏈接設(shè)置 | MSVC |
| #pragma GCC diagnostic | 控制 GCC 警告 | GCC, Clang |
? 結(jié)論:
#pragma是 C 語(yǔ)言中一個(gè)強(qiáng)大但平臺(tái)相關(guān)的預(yù)處理指令,可以用來(lái)控制編譯器行為、優(yōu)化、警告、對(duì)齊等。- 使用時(shí)要注意可移植性,優(yōu)先考慮標(biāo)準(zhǔn)方法,只在必要時(shí)使用特定編譯器的
#pragma擴(kuò)展。
三、一份不同編譯器支持的常用 #pragma 指令對(duì)照表
這樣在跨平臺(tái)開(kāi)發(fā)時(shí)就能清楚哪些可用哪些不可用。
| 功能 | MSVC | GCC / Clang | Keil (ARMCC) | IAR | 說(shuō)明 |
|---|---|---|---|---|---|
| 防止頭文件重復(fù)包含 | #pragma once | #pragma once | #pragma once | #pragma once | 非標(biāo)準(zhǔn),但現(xiàn)代編譯器普遍支持;標(biāo)準(zhǔn)做法是 #ifndef/#define/#endif |
| 結(jié)構(gòu)體 / 聯(lián)合對(duì)齊 | #pragma pack(push, n) #pragma pack(pop) | #pragma pack(push, n) #pragma pack(pop) | #pragma pack(push, n) #pragma pack(pop) | #pragma pack(push, n) #pragma pack(pop) | 設(shè)置結(jié)構(gòu)體成員對(duì)齊為 n 字節(jié);n 可取 1/2/4/8/16 |
| 編譯時(shí)消息輸出 | #pragma message("text") | #pragma message "text" | #pragma message("text") | #pragma message="text" | 在編譯輸出中顯示提示信息 |
| 禁用 / 開(kāi)啟警告 | #pragma warning(disable: 1234) #pragma warning(default: 1234) | #pragma GCC diagnostic ignored "-Wxxx" | #pragma diag_suppress 1234 | #pragma diag_suppress=Pe123 | 臨時(shí)關(guān)閉 / 恢復(fù)特定警告 |
| 警告視為錯(cuò)誤 | #pragma warning(error: 1234) | #pragma GCC diagnostic error "-Wxxx" | #pragma diag_error 1234 | #pragma diag_error=Pe123 | 將指定警告當(dāng)作錯(cuò)誤處理 |
| 鏈接選項(xiàng) | #pragma comment(lib, "libname.lib")#pragma comment(linker, "/option") | 無(wú)(用 -l/-Wl,option) | 無(wú)(用 --library/ scatter file) | 無(wú)(用鏈接器選項(xiàng)) | 向鏈接器傳遞參數(shù)或添加庫(kù) |
| 代碼段 / 節(jié)區(qū)控制 | #pragma section("name")__declspec(allocate("name")) | __attribute__((section("name"))) | __attribute__((section("name"))) | #pragma location="name" | 將變量 / 函數(shù)放入指定段 |
| 優(yōu)化控制 | #pragma optimize("", off)#pragma optimize("", on) | #pragma GCC push_options#pragma GCC optimize("O0")#pragma GCC pop_options | #pragma optimize=none | #pragma optimize=none | 局部關(guān)閉 / 開(kāi)啟優(yōu)化 |
| 循環(huán)優(yōu)化 | #pragma loop(hint_parallel(n)) | #pragma GCC ivdep | 無(wú) | 無(wú) | 提示編譯器并行 / 向量化優(yōu)化 |
| 對(duì)齊控制 | __declspec(align(n)) | __attribute__((aligned(n))) | __attribute__((aligned(n))) | __attribute__((aligned(n))) | 指定變量 / 類型對(duì)齊 |
| 內(nèi)聯(lián)控制 | __forceinline__declspec(noinline) | __attribute__((always_inline))__attribute__((noinline)) | 同上 | 同上 | 強(qiáng)制內(nèi)聯(lián) / 禁止內(nèi)聯(lián) |
| 中斷函數(shù) | __declspec(naked) | 無(wú)(用 __attribute__((naked))) | __attribute__((naked)) | #pragma interrupt | 定義無(wú)棧幀 / 特殊中斷函數(shù) |
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言運(yùn)算符的優(yōu)先級(jí)和結(jié)合性實(shí)例詳解
本文主要介紹C語(yǔ)言運(yùn)算符的知識(shí),這里對(duì)運(yùn)算符的優(yōu)先級(jí)和結(jié)合性做出了詳解,并附實(shí)例代碼,希望能幫助有需要的小伙伴2016-07-07
C語(yǔ)言中auto,register,static,const,volatile的區(qū)別詳細(xì)解析
以下是對(duì)C語(yǔ)言中auto,register,static,const,volatile的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下2013-09-09
C語(yǔ)言中數(shù)組常用的一些排序算法小結(jié)
數(shù)組的排序方法有很多,效率也各不相同,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中數(shù)組常用的一些排序算法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
C語(yǔ)言植物大戰(zhàn)數(shù)據(jù)結(jié)構(gòu)希爾排序算法
這篇文章主要為大家介紹了C語(yǔ)言希爾排序算法實(shí)現(xiàn)植物大戰(zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

