_bstr_t與BSTR

問題:數組

BSTR   a   =   _bstr_t("a");ide

BSTR   b   =   _bstr_t("b");  函數

  CString   c   ;  測試

  c   =   a;  指針

  MessageBox(c);  code

  c   =   b;  對象

  MessageBox(c);  內存

  爲何消息框中顯示的都是   b?  字符串

  若是這樣:  編譯器

    _bstr_t   bstr1("a");  

  BSTR   a   =   bstr1;  

  _bstr_t   bstr2("b");  

  BSTR   b   =   bstr2;  

  CString   c   ;  

  c   =   a;  

  MessageBox(c);  

  c   =   b;  

  MessageBox(c);  

  消息框中顯示就對了!

Answer:

首先要明確,_bstr_t是對BSTR的封裝。  

   

  Code   1:  

   

  BSTR   a   =   _bstr_t("a");  

  //這裏,_bstr_t("a")只是臨時對象,當它初始化(包含一個內部的BSTR)並賦值給BSTR   a以後,它就被撤銷了。而它賦的值是BSTR的地址。  

  BSTR   b   =   _bstr_t("b");  

  //第二次,仍然產生一個臨時對象,它也初始化...過程跟上面同樣。並且,因爲前面的_bstr_t對象已被撤銷,因此它產生BSTR的地址也同上。  

  //因此,實際上a,b指向同一個地址。而該地址的內容被寫了兩次。  

   

  Code   2:  

   

  _bstr_t   bstr1("a");  

  BSTR   a   =   bstr1;  

  _bstr_t   bstr2("b");  

  BSTR   b   =   bstr2;  

  //這裏的兩個_bstr_t   bstr1,bstr2都是局部對象,同時存在。因此,他們內部包含的BSTR的地址不同。這樣分別賦值就沒問題。

 

 

#if   defined(WIN32)   &&   !defined(OLE2ANSI)  

  typedef   WCHAR   OLECHAR;  

  #else  

  typedef   char   OLECHAR;  

  #endif  

  typedef   OLECHAR*   BSTR;  

   

  實際上BSTR就是直接指向字符串的首地址(雙字節或者ANSI字符串)。  

  而BSTR以前的四個字節是該字符串的長度,由編譯器生成的代碼自動去讀這個長度,而不是用"\0"來標識字符串的結束。

 

BSTR字符串有如下幾個要點要強調一下:  

  1.一個BSTR字符串變量其實是一個指針變量。它佔用32bit即4個字節,就像其它的指針同樣。並且,它指向一個Unicode格式的字符數組。可是,咱們不能把字符串與BSTR字符串等同起來。咱們必須用它本身確切的名字――「BSTR「。  

  2.一個BSTR字符串變量指向的字符串數組必須由4個字節的保留字開始(保存字符串數組的字節數而不是字符數),由2個空字符結束。  

  3.因爲空字符在Unicode格式的字符串中的任何位置都有可能出現,因此,以空字符聲明一個Unicode格式的字符串的結束並不合適。所以,在4個保留字中保存字符串的長度是相當重要的。  

  4.咱們再強調一下,BSTR字符串指針實際指向的是Unicode格式的字符數組的首地址,而不是開頭的4個字節。接下來咱們就會看到,在這兒這樣不厭其煩地強調BSTR字符串變量的特徵是爲了與立刻就要解釋的VC++中的string類型做個比較。  

  5.前4個字節的length記錄的是字符數組的字節數(注意,不是字符數),包括結尾的空字節。由於數組是Unicode格式的,因此實際字符是length的一半。  

  在這兒強調一下,一個Unicode格式的空字符實際上是佔用2個字節的空間,而不是1個字節。在Unicode格式的數組中測試空字符時要小心這一點。  

  咱們通常在慣例上說BSTR字符串「help」是「一個BSTR類型的字符串」。通常公認爲,一個BSTR字符串變量指向的一個字符數組中包括至少兩個空字符。  

  就Visual   Basic來講,BSTR字符串未尾的兩個空字節可能沒什麼用處,可是對Win32來講,它們倒是相當重要的。緣由在於,Win32版本的Unicode   String(它稱爲LPWSTR)定義爲指向一個空字符結尾的Unicode格式的字符串的指針。  

  從這個緣由上解釋BSTR字符串爲何要以空字符結尾就合情合理了。下面讓咱們討論一下C++類型的string變量。  

  兩句代碼:  

  Dim   str   as   String  

  str=」help」  

  str表示的是一個BSTR字符串變量的名字,而不是一個Unicode格式的字符數組。換句話說,str是一個保存地址xxxx的變量的名字。  

  如下是個小小的實驗,它代表Visual   Basic中string變量是指向字符數組的指針而不是字符數組。下面定義了一個結構,它的成員變量的類型是string。  

  Private   Tyep   utTest  

  astring   As   String  

  bstring   As   String  

  End   Type  

  Dim   uTest   As   utTest  

  Dim   s   as   String  

  s=」testing」  

  uTest.astring=」testing」  

  uTest.astring=」testing」  

  Debug.Print   Len(s)  

  Debug.Print   Len(uTest)  

  這幾句代碼的執行結果是:  

  7  

  8  

  對string變量來講,Len函數返回的是字符串數組的字符個數。因此7個字符的字符串「testing」返回7。對結構變量uTest來講,Len函數返回的是該結構佔用的內存空間。因此返回值8清楚地代表了每個BSTR變量在內存中佔用4個字節。由於BSTR是一個Win32的指針!  

  C類型的LPSTR和LPWSTR   字符串  

  Visual   C++使用LPSTR和LPWSTR字符串。  

  LPSTR類型字符串的定義是:指向一個空字節結尾的ANSI格式的字符串數組的指針。可是,由於咱們是以空字節的位置來判斷LPSTR字符串的終止的,因此,在LPSTR中是不容許字符串中還有第二個空字節存在。一樣,LPWSTR是一個指向空字節終止的Unicode格式的字符串的指針,它的中間也不容許有空字節存在。LPWSTR中的W指Wide,它是微軟對Unicode的另外一種說法。  

   

  可能咱們也會碰到LPCSTR和LPCWSTR類型的字符串。其中的C表示Constant(常量)。這種字符串是不能被API函數修改的。除此之外,LPCSTR都與LPSTR相同。同理,LPCWSTR除不能修改外,其它的都與LPWSTR相同。  

  再說LPTSTR,LPTSTR通常都用在條件編譯中,就象TCHAR同樣。如下是一個例子代碼:  

  #ifdef     UNICODE  

  typedef   LPWSTR   LPTSTR;             //   在Unicode下LPTSTR與LPWSTR是相同的  

  typedef   LPCWSTR   LPCTSTR;         //   在Unicode下LPCTSTR與LPCWSTR是相同的  

  #else        

  typedef   LPSTR   LPTSTR;               //在ANSI下LPTSTR與LPSTR是相同的  

  typedef   LPCSTR   LPCTSTR;           //在ANSI下LPTCSTR與LPCSTR是相同的  

  #endif  

相關文章
相關標籤/搜索