C++ Windows字元和字元指標類型

來源:互聯網
上載者:User

下面我羅列一些我們在Windows平台下編程經常使用到的和字元或字串有關的資料類型。

char  和  wchar_t 

這兩個類型大家絕對不會陌生吧,一個是單位元組的字元類型,一個是寬位元組的字元類型(也就是Unicode字元)。

char   c = 'b';

wcha_t  wc = L'b';

上面我就分別定義了2個變數c和wc ,相信第一個定義大家都看的懂,就是定一個字元變數c,其中儲存了'b'這個字元。 那麼第二個呢?  我相信還是很多人都看的懂,要是你看不懂也沒關係,現在就告訴你,也是定義一個字元變數wc, 只不過這個字元變數是Unicode字元變數,用2個位元組來儲存一個字元,而上面的c這個字元變數只有一個位元組來儲存,那麼在'b'前面的L又是什麼意思呢,它就表示這裡的'b'這個字元是一個Unicode字元,所以第二個定義的意思就是將L'b'這個Unicode字元儲存到wc這個Unicode字元變數中。

如果我要定義一個字元數組怎麼定義呢? 用分別用單位元組的char和寬位元組的wchar_t來定義就應該是:

char  c[10];

wchar_t wc[10];

如果是要帶初始化的字元數組的聲明,我們來看看怎麼寫

char c[] = "beyondcode";

wchar_t wc[] = L"beyondcode";

看到了嗎,寬位元組的操作其實和單位元組的字元操作一樣吧,只是在前面加上L表示是寬位元組的字元或者字串。

上面都是屬於C/C++中的知識,並沒有涉及太多Windows中的資料類型,那麼各位朋友們在Windows編程中看到的滿到處都是的 TCHAR,LPSTR, LPCSTR, LPWSTR, LPCWSTR, LPTSTR, LPCTSTR 這些資料類型又是怎麼回事呢? 別急,我們一步一步的來,最後我會聯絡到那上面去的。

上面的你都知道或者是理解了的話,那我們繼續,除了可以聲明一個字元數組,我還可以定義一個字元指標變數來指向一個字元數組,當然這個字元數組可以是Unicode的寬位元組字元數組,也可以是單位元組字元數組,如下:

char  c[] = "hello beyondcode"; //定義一個字元數組

wchar_t  wc[] = L"hello beyondcode"; //定義一個寬位元組字元數組

char   *p = c; //定義一個字元指標,指向剛才的字元數組

wchar_t *wp = wc; //定義一個寬位元組字元指標,指向剛才的寬位元組字元數組

這樣之後,我就可以通過指標來改變剛才我們定義的2個數組,例如:

p[0] = 'H';

wp[0] = L'H';

把上面2個數組的第一個字元通過指標改變成大寫。這裡是可以通過指標來修改的,因為我沒有定義指標為常量指標,也就是沒有加const 修飾符。如果我像下面這樣定義的話,那麼就不能通過這些指標來改變他們所指向的資料了,而是只有讀取他們。

const  char  *p = c;

const  wchar_t  *wp = wc;

上面將的都是C/C++的基礎知識,有點囉嗦,為了照顧新手朋友們嘛,下面我們就來看看Windows是怎麼定義它的資料類型的

首先,定義了CHAR, WCHAR的這2個字元資料類型,就是我們上面討論的兩個字元資料類型改了一下名字而已。現在你還不昏吧··

typedef char CHAR;

typedef wchar_t WCHAR;

然後,用剛才定義的 CHAR, WCHAR這2個字元資料類型去定義了一系列其他字元指標類型。

typedef CHAR *LPSTR;

typedef WCHAR *LPWSTR;

這樣一定義之後,LPSTR的就是 CHAR*, 而CHAR 又是char, 所以LPSTR的本質就是 char*,也就是我們上面熟悉的不能再熟悉的字元指標,  那LPWSTR不用我推導,相信你也推匯出來了吧。不過我還是推導一下,LPWSTR是 WCHAR * , WCHAR是wchar_t,這樣LPWSTR就是 wchar_t* ,也就是我們上面討論的寬位元組字元指標。上面這些定義都是在WinNT.h這個標頭檔中定義的,讀者朋友們有興趣在這個標頭檔裡面去挖掘挖掘吧,上面2個定義我只是提取了重要的部分,其實在裡面他還定義了其他很多別名.

看了LPSTR, LPWSTR是怎麼一回事之後,我們再接再厲,看看LPCSTR,LPCWSTR這2個資料類型又是怎麼一回事呢, 老規矩,先看windows的定義。

typedef CONST CHAR *LPCSTR;

typedef CONST WCHAR *LPCWSTR;

和上面的比較,名字中就多了一個大寫的C,這個C的含義就代表是const修飾符,也就是我們上面所說的常量指標,指向的內容不能通過這個指標被改變,但可以讀取。定義中的大寫的CONST也是一個宏,我在第一篇文章中就講過了,代換出來也就是const, 所以請讀者自己推導一下這兩個資料類型的本質是什麼。

所以,在windows平台下的編程過程中,凡是可以使用char* 的地方,你都可以使用LPSTR來代替,凡是可以使用wchar_t*的地方,你都可以使用LPWSTR來代替,至於怎麼用,還是那句老話,看你個人心情,只不過Windows的API函數中關於字串的都是使用LP這種資料類型。但是你還是可以給他傳遞char* 或者 wchar_t* ,只要他們的本質是一樣的,那怎麼不可以呢~~

下面,我們來看一看一些樣本。

char  c = 'c';  和 CHAR c = 'c';    是一樣的

wchar_t wc = L'w'; 和 WCHAR wc = L'w';    是一樣的

char* p  和 LPSTR p 是一樣的

wchar_t* wp  和 LPWSTR wp    是一樣的

再來看看動態記憶體分配怎麼寫的呢

char* p = new char[10]; //動態分配了十個字元

也可以寫成

CHAR* p = new CHAR[10];

LPSTR p = new CHAR[10];

LPSTR p = new char[10];

寬位元組的再來一次

wchar_t* wp = new wchar_t[10];

也可以寫成下面這些形式

WCHAR*  wp = new WCHAR[10];

LPWSTR  wp = new WCHAR[10];

LPWSTR  wp = new wchar_t[10];

上面定義的這些字元指標 p , wp都沒有用const修飾符,所以可以通過他們來修改他們所指向的內容。這裡留給讀者一個問題,怎麼定義有const修飾符的字元指標呢,都可以用什麼形式來寫呢,寫得越多越好喲。。

通過上面這些,我想你大概已經瞭解了LPSTR, LPCSTR, LPWSTR, LPCWSTR這四個資料類型了,他們無非就是:

LPSTR  -------    char*

LPCSTR -------  const char*

LPWSTR -------  wchar_t*

LPCWSTR --------   const wchar_t* 

下面我提一個問題,如果你在你的程式中使用的字串都是通過LPWSTR,LPCWSTR這種寬位元組(Unicode)字元指標來進行操作的,那麼在Unicode環境下編譯,完全沒有問題,如果這時你需要編譯一套ASCII版本的程式,那你會怎麼辦呢?   你說將用LPWSTR 和LPCWSTR的地方全部換成LPSTR和LPCSTR,再將字串前面的L去掉就可以了,對,這是一種方法,但是!!所有人在這裡都應該知道我要說但是,這也太麻煩了吧。難道沒有通用點的方法嗎?   有!!  所有人在這裡也都知道我會說有,呵呵。  那就是使用微軟的通用資料類型,說通用資料類型有點太專業了,其實也就那樣,請聽我慢慢分析來。我在上一篇文章中說過,凡是涉及字串操作的API函數有2套,一個A系列的,一套W系列的,還有一套宏,能根據不同的工程環境定義成不同的API函數名。那麼在字元類型上微軟也使用幾乎同樣的技術,定義了一套宏能根據不同的工程環境定義成不同的字元資料類型。我上面就提到過的TCHAR,LPTSTR, LPCTSTR就是這樣的類型。

首先說說TCHAR,它是被這樣定義的:

#ifdef UNICODE

typedef  WCHAR TCHAR;

#else

typedef  char TCHAR

看到了嗎? 它也是根據UNICODE這個宏被定義沒有,如果被定義了,那麼TCHAR代表的資料類型就是WCHAR, 也就是wchar_t, 如果沒被定義,那麼TCHAR 就代表的是char

同樣LPTSTR,LPCTSTR也是這樣的,考慮到篇幅,我就只列出LPTSTR來給大家看看了

#ifdef   UNICODE

typedef LPWSTR LPTSTR;

#else

typedef  LPSTR LPTSTR;

這個是我簡化了的定義,真實面目有些複雜,不過意思也是如此,有興趣可以自己看看,在WinNT.h這個標頭檔中。下面再次解釋一下上面這個LPTSTR的定義, 還是老樣子,根據UNICODE這個宏被定義與否來決定怎麼定義LPTSTR ,如果是定義了UNICODE這個宏,表示當前工程環境是Unicode環境,那麼LPTSTR就被定義為了LPWSTR, LPWSTR就是我們前面所講的wchar_t* ,所以此時LPTSTR代表的資料類型就是wchar_t* ,  如果這時的工程沒有定義UNICODE這個宏,那麼就定義LPTSTR為LPSTR,而LPSTR就是我們前面所說的char* ,所以這是的LPTSTR就代表char*。懂了嗎?各位,我都覺得自己有些囉嗦了··不好意思···

然後還有一個宏需要講一下,由於我們使用通用資料類型,那麼我事先就不知道我的原始碼需要在Unicode下編譯還是在ASCII環境下編譯,所以如下這種情況

TCHAR tc = 'a';  或者是 TCHAR tc = L'a';  是否合適呢? 前面我已經說過了字元或字串常量前面加L代表這是寬位元組的字元或字串,將一個寬位元組字元賦值給一個TCHAR資料類型的變數tc,什麼情況下是正確的呢?  各位思考一下呢?  

如果當前工程是Unicode環境,那麼TCHAR資料類型就是wchar_t的寬位元組類型,所以tc就是寬位元組字元變數,那麼上面第二個指派陳述式就是正確的,而第一個就是錯誤的。

如果反過來,當前的工程是ASCII環境,那麼TCHAR代表的是char這種資料類型,那麼第一個指派陳述式就是正確的,而第二個就是錯誤的了。

分析了這麼多,我就是要講一個宏 _T(), 只要將字元或者字串常量放在_T()這個宏裡面,那麼這個宏就能根據當前的環境決定是否在字元或字串前面加L,如下面:

TCHAR tc = _T('A');

如果這麼寫,在不需要改寫原始碼的情況下,就可以編譯出Unicode和ASCII兩套程式,而只需要改變工程的環境而已。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.