<address id="ousso"></address>
<form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
  1. C語言

    c++ 中--declspec 的用法詳解

    時間:2025-01-03 23:18:41 C語言 我要投稿
    • 相關推薦

    c++ 中--declspec 的用法詳解

      c++ 中__declspec 的用法是怎樣的呢?如下是為大家整理的c++ 中__declspec 的用法詳解,想要了解的繼續往下看吧。

      語法說明:

      __declspec ( extended-decl-modifier-seq )

      擴展修飾符:

      1:align(#)

      用__declspec(align(#))精確控制用戶自定數據的對齊方式 ,#是對齊值。

      e.g

      __declspec(align(32))

      struct Str1{

      int a, b, c, d, e;

      };

      它與#pragma pack()是一對兄弟,前者規定了對齊的最小值,后者規定了對齊的最大值。同時出現時,前者優先級高。

      __declspec(align())的一個特點是,它僅僅規定了數據對齊的位置,而沒有規定數據實際占用的內存長度,當指定的數據被放置在確定的位置之后,其后的數據填充仍然是按照#pragma pack規定的方式填充的,這時候類/結構的實際大小和內存格局的規則是這樣的:在__declspec(align())之前,數據按照#pragma pack規定的方式填充,如前所述。

      當遇到__declspec(align())的時候,首先尋找距離當前偏移向后最近的對齊點(滿足對齊長度為max(數據自身長度,指定值)),然后把被指定的數據類型從這個點開始填充,其后的數據類型從它的后面開始,仍然按照#pragma pack填充,直到遇到下一個__declspec(align())。當所有數據填充完畢,把結構的整體對齊數值和__declspec(align())規定的值做比較,取其中較大的作為整個結構的對齊長度。特別的,當__declspec(align())指定的數值比對應類型長度小的時候,這個指定不起作用。

      2: allocate("segname")

      用__declspec(allocate("segname")) 聲明一個已經分配了數據段的一個數據項。它和#pragma 的code_seg, const_seg, data_seg,section,init_seg配合使用,segname必須有這些東東聲明。

      e.g

      #pragma data_seg("share_data")

      int a = 0;

      int b;

      #pragma data_seg() __declspec(allocate("share_data")) int c = 1;

      __declspec(allocate("share_data")) int d;

      3. deprecated

      用__declspec(deprecated ) 說明一個函數,類型,或別的標識符在新的版本或未來版本中不再支持,你不應該用這個函數或類型。它和#pragma deprecated作用一樣。

      e.g

      #define MY_TEXT "function is deprecated"

      void func1(void) {}

      __declspec(deprecated) void func1(int) { printf("func1n");}

      __declspec(deprecated("** this is a deprecated function **")) void func2(int) { printf("func2n");}

      __declspec(deprecated(MY_TEXT)) void func3(int) { printf("func3");}

      int main()

      {

      fun1();

      fun2();

      fun3();

      }

      4.dllimport 和dllexport

      用__declspec(dllexport),__declspec(dllimport)顯式的定義dll接口給調用它的exe或dll文件,用 dllexport定義的函數不再需要(.def)文件聲明這些函數接口了。注意:若在dll中定義了模板類那它已經隱式的進行了這兩種聲明,我們只需在 調用的時候實例化即可,呵呵。

      e.g 常規方式dll中

      class ___declspec(dllexport)

      testdll{

      testdll(){};

      ~testdll(){};

      };

      調用客戶端中聲明

      #import comment(lib, "**.lib)

      class ___declspec(dllimportt)

      testdll{

      testdll(){};

      ~testdll(){};

      };

      e.g 模板類:dll中

      template<class t>

      class test{

      test(){};

      ~test(){};

      }

      調用客戶端中聲明

      int main()

      {

      test< int > b;

      return 0;

      }

      5. jitintrinsic

      用__declspec(jitintrinsic)標記一個函數或元素為64位公共語言運行時。具體用法未見到。

      6. __declspec( naked )

      對于沒有用naked聲明的函數一般編譯器都會產生保存現場(進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器 ——prolog)和清除現場(退出函數時則產生代碼恢復這些寄存器的內容——epilog) 代碼,而對于用naked聲明的函數一般不會產生這些代碼,這個屬性對于寫設備驅動程序非常有用,我們自己可以寫這樣一個過程,它僅支持x86 。naked只對函數有效,而對類型定義無效。對于一個標志了naked的函數不能產生一個內聯函數即時使用了__forceinline 關鍵字。

      e.g

      __declspec ( naked ) func()

      {

      int i;

      int j;

      __asm /* prolog */

      {

      push ebp

      mov ebp, esp

      sub esp, __LOCAL_SIZE

      }

      /* Function body */

      __asm /* epilog */

      {

      mov esp, ebp

      pop ebp

      ret

      }

      }

      7. restrict 和 noalias

      __declspec(restrict) 和 __declspec(noalias)用于提高程序性能,優化程序。這兩個關鍵字都僅用于函數,restrict針對于函數返回指針,restrict 說明函數返回值沒有被別名化,返回的指針是唯一的,沒有被別的函數指針別名花,也就是說返回指針還沒有被用過是唯一的。編譯器一般會去檢查指針是否可用和 是否被別名化,是否已經在使用,使用了這個關鍵字,編譯器就不在去檢查這些信息了。noalias 意味著函數調用不能修改或引用可見的全局狀態并且僅僅修改指針參數直接指向的內存。如果一個函數指定了noalias關鍵字,優化器認為除參數自生之外, 僅僅參數指針第一級間接是被引用或修改在函數內部。可見全局狀態是指沒有定義或引用在編碼范圍外的全部數據集,它們的直至不可以取得。編碼范圍是指所有源 文件或單個源文件。其實這兩個關鍵字就是給編譯器了一種保證,編譯器信任他就不在進行一些檢查操作了。

      e.g

      #include <stdio.h>

      #include <stdlib.h>

      #define M 800#define N 600#define P 700float * mempool, * memptr;

      __declspec(restrict) float * ma(int size)

      {

      float * retval;

      retval = memptr;

      memptr += size;

      return retval;

      }

      __declspec(restrict) float * init(int m, int n)

      {

      float * a;

      int i, j;

      int k=1;

      a = ma(m * n);

      if (!a) exit(1);

      for (i=0; i<m; i++)

      for (j=0; j<n; j++)

      a[i*n+j] = 0.1/k++;

      return a;

      }

      __declspec(noalias) void multiply(float * a, float * b, float * c)

      {

      int i, j, k;

      for (j=0; j<P; j++)

      for (i=0; i<M; i++)

      for (k=0; k<N; k++)

      c[i * P + j] = a[i * N + k] * b[k * P + j];

      }

      int main()

      {

      float * a, * b, * c;

      mempool = (float *) malloc(sizeof(float) * (M*N + N*P + M*P));

      if (!mempool)

      puts("ERROR: Malloc returned null"); exit(1);

      memptr = mempool;

      a = init(M, N);

      b = init(N, P);

      c = init(M, P);

      multiply(a, b, c);

      }

      8. noinline__declspec(noinline)

      告訴編譯器不去內聯一個具體函數。

      9. noreturn__declspec(noreturn)

      告訴編譯器沒有返回值.注意添加__declspec(noreturn)到一個不希望返回的函數會導致已沒有定義錯誤.

      10.nothrow__declspec(nothrow)

      用于函數聲明,它告訴編譯器函數不會拋出異常。

      e.g

      #define WINAPI __declspec(nothrow) __stdcall

      void WINAPI f1();

      void __declspec(nothrow) __stdcall f2();

      void __stdcall f3() throw();

      11.novtable __declspec(novtable)

      用在任意類的聲明,但是只用在純虛接口類,因此這樣的不能夠被自己實例話.它阻止編譯器初始化虛表指針在構造和析構類的時候,這將移除對關聯到類的虛表的 引用.如果你嘗試這實例化一個有novtable關鍵字的類,它將發生AV(access violation)錯誤.C++里virtual的缺陷就是vtable會增大代碼的尺寸,在不需要實例化的類或者純虛接口的時候,用這個關鍵字可以減 小代碼的大小.

      e.g

      #if _MSC_VER >= 1100 && !defined(_DEBUG)

      #define AFX_NOVTABLE __declspec(novtable)

      #else

      #define AFX_NOVTABLE

      #endif

      ....

      class AFX_NOVTABLE CObject

      {

      ...

      };

      這是vc里面的一段代碼,我們可以看出編譯Release版本時,在CObject前是__declspec(novtable),在debug版本沒有這個限制。

      e.g

      #include <stdio.h>

      struct __declspec(novtable) X

      {

      virtual void mf();

      };

      struct Y : public X

      {

      void mf()

      {

      printf_s("In Yn");

      }

      };

      12.selectany的作用

      __declspec(selectany)可以讓我們在.h文件中初始化一個全局變量而不是只能放在.cpp中。比如有一個類,其中有一個靜態變量,那 么我們可以在.h中通過類似" __declspec(selectany) type class::variable = value; "這樣的代碼來初始化這個全局變量。既是該.h被多次include,鏈接器也會為我們剔除多重定義的錯誤。這個有什么好處呢,我覺得對于 teamplate的編程會有很多便利。

      e.g

      class test

      {

      public:

      static int t;

      };

      __declspec(selectany) int test::t = 0;

      13.thread

      thread 用于聲明一個線程本地變量. __declspec(thread)的前綴是Microsoft添加給Visual C++編譯器的一個修改符。它告訴編譯器,對應的變量應該放入可執行文件或DLL文件中它的自己的節中。__declspec(thread)后面的變量 必須聲明為函數中(或函數外)的一個全局變量或靜態變量。不能聲明一個類型為__declspec(thread)的局部變量。

      e.g

      __declspec(thread)

      class X{

      public:

      int I;

      } x; // x is a thread objectX y; // y is not a thread object

      14.uuid__declspec(uuid)

      用于編譯器關聯一個GUID到一個有uuid屬性的類或結構的聲明或者定義.

      e.gstruct __declspec(uuid("00000000-0000-0000-c000-000000000046")) IUnknown;struct __declspec(uuid("{00020400-0000-0000-c000-000000000046}")) IDispatch;我們可以在MFC中查看源碼.:)


    【c++ 中--declspec 的用法詳解】相關文章:

    C++類中的繼承實例詳解07-05

    英語中know的幾種用法詳解03-19

    c++中的string常用函數用法總結06-25

    C++ this指針詳解07-04

    c++快速排序詳解04-24

    詳解C/C++中堆和棧及靜態數據區03-18

    C++ cin輸入流詳解04-03

    java list的用法詳解01-23

    C++ 排序插入排序詳解08-03

    <address id="ousso"></address>
    <form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
    1. 日日做夜狠狠爱欧美黑人