最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言 詳細(xì)講解#pragma的使用方法

 更新時間:2022年04月19日 10:59:07   作者:清風(fēng)自在 流水潺潺  
#pragma 指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機(jī)或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機(jī)器或操作系統(tǒng)專有的, 且對于每個編譯器都是不同的

一、#pragma 簡介

#pragma 用于指示編譯器完成一些特定的動作

#pragma 所定義的很多指示字是編譯器特有的

#pragma 在不同的編譯器間是不可移植的

  • 預(yù)處理器將忽略它不認(rèn)識的 #pragma 指令
  • 不同的編譯器可能以不同的方式解釋同一條 #pragma 指令

一般用法:

#pragma parameter

注:不同的 parameter 參數(shù)語法和意義各不相同

二、#pragma message

  • message 參數(shù)在大多數(shù)的編譯器中都有相似的實(shí)現(xiàn)
  • message 參數(shù)在編譯時輸出消息到編譯輸出窗口中
  • message 用于條件編譯中可提示代碼的版本信息

例如:

#if defined(ANDROID20)
    #pragma message("Compile Android SDK 2.0...")
    #define VERSION "Android 2.0 "
#endif

注:#error 和 #warning 不同,#pragma message 僅僅代表一條編譯消息,不代表程序錯誤。

下面看一個 #pragma message 使用示例:

test.c:

#include <stdio.h>
 
#if defined(ANDROID20)
    #pragma message("Compile Android SDK 2.0...")
    #define VERSION "Android 2.0"
#elif defined(ANDROID23)
    #pragma message("Compile Android SDK 2.3...")
    #define VERSION "Android 2.3"
#elif defined(ANDROID40)
    #pragma message("Compile Android SDK 4.0...")
    #define VERSION "Android 4.0"
#else
    #error Compile Version is not provided!
#endif
 
int main()
{
    printf("%s\n", VERSION);
 
    return 0;
}

下面為輸出結(jié)果:

三、#pragma once

  • #pragma once 用于保證頭文件只被編譯一次
  • #pragma once 是編譯器相關(guān)的,不一定被支持

下面兩種方式的區(qū)別是:前者是被 C 語言所支持的,并不是只包含一次頭文件,而是包含多次,然后通過宏控制是否嵌入到源代碼中,也就是說通過宏的方式,可以保證頭文件里面的內(nèi)容只被嵌入一次,但是由于包含了多次,預(yù)處理器還是處理了多次,所以效率上來說比較低;后者是告訴預(yù)處理器當(dāng)前文件只編譯一次,所以說效率較高。

下面看一個 #pragma once 的使用示例:

global.h:

 #pragma once
 
int g_value = 1;

test.c:

#include <stdio.h>
#include "global.h"
#include "global.h"
 
int main()
{
    printf("g_value = %d\n", g_value);
 
    return 0;
}

下面為輸出結(jié)果,可以看到雖然在test.c 定義了兩次global.h,但是程序編譯沒有報錯,且能正常運(yùn)行,這就是 #pragma once 作用的結(jié)果:

工程應(yīng)用中既想要移植性,又想要保證效率,可以采用以下做法:

global.h:

#ifndef _GLOBAL_H_
#define _GLOBAL_H_
 
#pragma once
 
int g_value = 1;
 
#endif

四、#pragma pack

什么是內(nèi)存對齊?

  • 不同類型的數(shù)據(jù)在內(nèi)存中按照一定的規(guī)則排列
  • 而不一定是順序的一個接一個的排列

下面想想 Test1 和 Test2 所占的內(nèi)存空間是否相同?

答案是否定的,Test1 占用 12 個字節(jié),而 Test 占用 8 個字節(jié)

為什么需要內(nèi)存對齊?

  • CPU對內(nèi)存的讀取不是連續(xù)的,而是分成塊讀取的,塊的大小只能是1、2、4、8、16...字節(jié)
  • 當(dāng)讀取操作的數(shù)據(jù)未對齊,則需要兩次總線周期來訪問內(nèi)存,因此性能會大打折扣
  • 某些硬件平臺只能從規(guī)定的相對地址處讀取特定類型的數(shù)據(jù),否則產(chǎn)生硬件異常

#pragma pack 用于指定內(nèi)存對齊方式

#pragma pack 能夠改變編譯器的默認(rèn)對齊方式

例如,下面代碼中,Test1 和 Test2 的內(nèi)存均為 8 個字節(jié)

struct 占用的內(nèi)存大小

第一個成員起始于 0 偏移處

每個成員按其類型大小和 pack 參數(shù)中較小的一個進(jìn)行對齊

  • 偏移地址必須能被對齊參數(shù)整除
  • 結(jié)構(gòu)體成員的大小取其內(nèi)部長度最大的數(shù)據(jù)成員作為其大小

結(jié)構(gòu)體總長度必須為所有對齊參數(shù)的整數(shù)倍

編譯器在默認(rèn)情況下按照 4 字節(jié)對齊。

下面通過代碼,手工計算結(jié)構(gòu)體所占用的內(nèi)存大小

test.c:

#include <stdio.h>
 
#pragma pack(4)
struct Test1
{                   //對齊參數(shù)      偏移地址        大小
    char  c1;       //1            0              1
    short s;        //2            2              2
    char  c2;       //1            4              1
    int   i;        //4            8              4
};
#pragma pack()
 
#pragma pack(4)
struct Test2
{                   //對齊參數(shù)      偏移地址        大小
    char  c1;       //1            0              1
    char  c2;       //1            1              1
    short s;        //2            2              2
    int   i;        //4            4              4
};
#pragma pack()
 
int main()
{
    printf("sizeof(Test1) = %d\n", sizeof(struct Test1));
    printf("sizeof(Test2) = %d\n", sizeof(struct Test2));
 
    return 0;
}

以 Test1 為例,c1 類型大小為 1 字節(jié),而 pack 參數(shù)默認(rèn)為 4,所以對齊參數(shù)取最小為 1;同理 s 的對齊參數(shù)為 2,偏移地址要被 2 整除,所以為 2;同理 c 的對齊參數(shù)為 1,偏移地址為 4;同理,i 的對齊參數(shù)為 4,因?yàn)槠频刂芬鼙?對齊參數(shù) 4 整除,在偏移地址 4 之后能被 4 整除的最小偏移地址為 8,所以 i 的偏移地址為 8,而 i 占用 4 個字節(jié),所以 Test1 結(jié)構(gòu)體占用的總字節(jié)數(shù)為 12 字節(jié),這就和上面的圖對應(yīng)起來了。

下面再通過一個例子感受一下:

在 gcc 編譯器下,test.c:

#include <stdio.h>
 
#pragma pack(8)
 
struct S1
{                   //對齊參數(shù)      偏移地址        大小
    short a;        //2            0              2
    long b;         //4            4              4
};
 
struct S2
{                   //對齊參數(shù)      偏移地址        大小
    char c;         //1            0              1
    struct S1 d;    //4            4              8
    double e;       //4            12             8
};
 
#pragma pack()
 
int main()
{
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
 
    return 0;
}
 

下面為輸出結(jié)果:

這里注意兩點(diǎn):

1.結(jié)構(gòu)體成員的大小取其內(nèi)部長度最大的數(shù)據(jù)成員作為其大小,所以 S1 的內(nèi)存大小為 4,而pack 參數(shù)默認(rèn)為 8,所以對齊參數(shù)為 4

2.一般的 pack 對齊格式分別是 1,2,4,8,16,默認(rèn)的對齊格式,也就是:#pragmapack() 的情況下,會在結(jié)構(gòu)體中挑選占用字節(jié)最多的類型,例如 double 占用 8 個字節(jié)

3.gcc 編譯器暫時不支持 8 字節(jié)對齊,默認(rèn)按照 4 字節(jié)對齊,所以 S2 中的 e 的對齊參數(shù)為 4,故 S2 占用內(nèi)存大小為 20 字節(jié)。(學(xué)習(xí)采用的為 ubuntu 10.10)

如果把代碼放在 VS2012 里運(yùn)行,那結(jié)果就是和分析的一樣,S2 占用 24 字節(jié)。

#include <stdio.h>
 
#pragma pack(8)
 
struct S1
{                   //對齊參數(shù)      偏移地址        大小
    short a;        //2            0              2
    long b;         //4            4              4
};
 
struct S2
{                   //對齊參數(shù)      偏移地址        大小
    char c;         //1            0              1
    struct S1 d;    //4            4              8
    double e;       //8            16             8
};
 
#pragma pack()
 
int main()
{
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
 
    return 0;
}
 

結(jié)果:

五、小結(jié)

#pragma 用于指示編譯器完成一些特定的動作

#pragma 所定義的很多指示字是編譯器特有的

  • #pragma message 用于自定義編譯消息
  • #pragma once 用于保證頭文件只被編譯一次
  • #pragma pack 用于指定內(nèi)存對齊方式

到此這篇關(guān)于C語言 詳細(xì)講解#pragma的使用方法的文章就介紹到這了,更多相關(guān)C語言 #pragma內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c++如何控制輸出浮點(diǎn)數(shù)小數(shù)點(diǎn)后若干位

    c++如何控制輸出浮點(diǎn)數(shù)小數(shù)點(diǎn)后若干位

    這篇文章主要介紹了c++如何控制輸出浮點(diǎn)數(shù)小數(shù)點(diǎn)后若干位問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • C語言函數(shù)調(diào)用的三種實(shí)現(xiàn)方法實(shí)例

    C語言函數(shù)調(diào)用的三種實(shí)現(xiàn)方法實(shí)例

    C語言中函數(shù)的調(diào)用主要有如下三種方法,直接調(diào)用,函數(shù)指針調(diào)用,函數(shù)指針傳遞調(diào)用其中后兩種本質(zhì)一樣,但在有無返回值時還稍有差別,下面這篇文章主要給大家介紹了關(guān)于C語言函數(shù)調(diào)用的三種實(shí)現(xiàn)方法,需要的朋友可以參考下
    2022-01-01
  • C語言 分支語句詳解分析

    C語言 分支語句詳解分析

    分支結(jié)構(gòu)的執(zhí)行是依據(jù)一定的條件選擇執(zhí)行路徑,而不是嚴(yán)格按照語句出現(xiàn)的物理順序。分支結(jié)構(gòu)的程序設(shè)計方法的關(guān)鍵在于構(gòu)造合適的分支條件和分析程序流程,根據(jù)不同的程序流程選擇適當(dāng)?shù)姆种дZ句
    2021-10-10
  • 基于C語言的庫封裝發(fā)布技術(shù)詳解

    基于C語言的庫封裝發(fā)布技術(shù)詳解

    在編程的過程中,使用已經(jīng)封裝好的庫函數(shù)是十分方便的,也是十分高效的,這篇文章主要給大家介紹了關(guān)于C語言庫的封裝和使用的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • C++ 中的單例模式(普通,2B,文藝)

    C++ 中的單例模式(普通,2B,文藝)

    這篇文章主要介紹C++ 中的單例模式寫法,主要包括普通,2B,文藝三種寫法,需要的朋友可以參考下
    2013-03-03
  • Qt物聯(lián)網(wǎng)管理平臺之實(shí)現(xiàn)告警短信轉(zhuǎn)發(fā)

    Qt物聯(lián)網(wǎng)管理平臺之實(shí)現(xiàn)告警短信轉(zhuǎn)發(fā)

    系統(tǒng)在運(yùn)行過程中,會實(shí)時采集設(shè)備的數(shù)據(jù),當(dāng)采集到的數(shù)據(jù)發(fā)生報警后,可以將報警信息以短信的形式發(fā)送給指定的管理員。本文將利用Qt實(shí)現(xiàn)告警短信轉(zhuǎn)發(fā),感興趣的可以嘗試一下
    2022-07-07
  • C語言實(shí)現(xiàn)推箱子代碼

    C語言實(shí)現(xiàn)推箱子代碼

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)推箱子代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++ ostream用法案例詳解

    C++ ostream用法案例詳解

    這篇文章主要介紹了C++ ostream用法案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C++智能指針shared_ptr與weak_ptr的實(shí)現(xiàn)分析

    C++智能指針shared_ptr與weak_ptr的實(shí)現(xiàn)分析

    shared_ptr是一個標(biāo)準(zhǔn)的共享所有權(quán)的智能指針,允許多個指針指向同一個對象,定義在 memory 文件中,命名空間為 std,這篇文章主要介紹了C++ 中 shared_ptr weak_ptr,需要的朋友可以參考下
    2022-09-09
  • 詳解C++中普通舊數(shù)據(jù)(POD)的使用

    詳解C++中普通舊數(shù)據(jù)(POD)的使用

    普通舊數(shù)據(jù)就是內(nèi)存中的連續(xù)字節(jié)序列,是能夠被“僅當(dāng)作數(shù)據(jù)”處理的對象。這篇文章主要帶大家了解一下C++中普通舊數(shù)據(jù)的定義與使用,感興趣的可以了解下
    2023-03-03

最新評論

金塔县| 崇礼县| 西贡区| 昂仁县| 东丰县| 平潭县| 辽阳县| 灌阳县| 广东省| 云浮市| 梅河口市| 华安县| 沽源县| 旬邑县| 铜山县| 万年县| 房产| 伊金霍洛旗| 怀柔区| 定南县| 贵南县| 台安县| 宁夏| 博湖县| 丽水市| 江口县| 西和县| 宁河县| 临城县| 涿州市| 桂平市| 岳阳县| 淄博市| 华池县| 炎陵县| 大安市| 广河县| 奉化市| 定结县| 蚌埠市| 黄石市|