tchar char 字符 和 字符數組 字符串操作

如下操作實在類中定義的: 

TCHAR m_illegal_chars[13];

TCHAR temp[13] = {_T('|'),
  _T('*'),
  _T('\\'),
  _T(':'),
  _T(';'),
  _T('>'),
  _T('<'),
  _T('?'),
  _T('"'),
  _T(','),
  _T('='),
  _T('`') };
 int i = sizeof(temp)/sizeof(temp[0]);  此時i= 13
 _tcscpy_s(m_illegal_chars, i,temp);

上面沒有問題。

但下面的代碼

 _tcscpy_s(m_illegal_chars,12,temp);  用12替換i

程序出現異常,down掉了,而且查看了m_illegal_chars爲 0*\:;><?",=`  而不是|*\:;><?",=`  第一個字符沒有拷貝成功;

解釋:

類裏面用_tcscpy_s要注意的小細節

     複製字符串總是在後23個字節後開始,前幾個字節不變,剛開始以爲是UTF8頭(EF BB BF)的問題,但那幾個字節不是,文件也不是UTF8的,單步步進一看,errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR*_SRC)

這個函數的 _DEST還真的往前移了幾個字節,ALT+8看彙編,才發現這個地址是this+偏移過來的,但偏移是4字節對齊,這個偏移前面有個bool型變量,導致偏移差了3個字節,vs2010自己還是4字節對齊,導致多加了3個。

字節對齊在結構體或類中。

影響字節對齊有幾個因素。

1)  編譯器對齊字節值。        一般默認爲4,可以通過#pragra  更改

2)  類成員對齊字節值。        成員所佔的字節

3)  類自己的對齊字節值。    類裏面的最大成員的對齊值。  它將決定類在補齊字節時的值。

4)  類成員有效對齊值。        類成員對齊字節值和編譯器對齊字節值中小的哪個。    它決定類成員佔多大字節。

你應該看到了Assert窗口了

   "Buffer is too small"

那原因是什麼呢? 字符串str中有8個字符,加上字符串結束符'\0',應該要大小爲9buffer,這裏纔會出錯,

 至於要求使用strcpy_s,就是考慮到strcpy_s這一系列的函數,可以保證不做越界操作。

非常重要的一個問題:

win32平臺上字符串的常見處理方式

 

     1:強烈推薦使用UNICODE來編寫程序。

1,使用unicode,可以使用一個exe,或者DLL來支持多國語言,方便實現本地化。

2,使用Unicode,可以節省WIN32API調用的時間和空間開銷,下面會詳細介紹。

3,可以更好地和COM組件交互,因爲COM組件只支持UNICODE

4,可以更好地和NETFRAMEWORK交互。

 

     對於win32 API函數來說,目前的windows操作系統內部都使用UNICODE來實現和字符串有關的函數。但是通常,都提供ASCLLUnicode兩個版本的,如CreateWindowA,CreateWindowW,其實內部只有後者的真正實現,前者則是分配內存,轉換傳入的ASCLL字串爲寬字符,然後傳入後者,等待後者返回後,釋放內存,並返回。在頭文件中呢,微軟定義了宏

#ifdef UNICODE

#define CreateWindow CreateWindowW

#else

#define CreateWindow CreateWindowA

#endif

,正是通過是否定義了UNICODE來決定調用哪一個。

     那麼,C標準庫呢?C標準庫中的字符串處理函數,則不像win32 API一樣,只有寬字符版本的實現,C標準庫有兩個實現,一個實現是ANSI的,一個是UNICODE的,程序員可以在編譯的時候來指定。這一點可以參看深入淺出MFC第一章。比如strlen是針對ASCLL的,wcslen是針對UNICODE的,標準庫如何判斷到底使用哪一個呢?標準庫定義了宏:

#ifdef _UNICODE

#define _tcslen wcslen

#else

#define _tcslen strlen

#endif

可以看出來,標準庫會將UNICODE的標識定義爲包含下劃線的形式,而微軟的開發團隊沒有那樣做,微軟的是不帶下劃線的。不過,我們的程序一般來說,既要用到API,又要用到標準庫函數,所以就有了一條規則,要麼UNICODE_UNICODE都指定,否則都不指定。

     下面來總結一下一些原則吧:)

1,建議使用UNICODE

2,建議不要使用char, wchar_t,而使用CHAR,WCHAR,最好包含tchar.h,使用TCHAR

3,計算字符數組長度時,使用sizeof(ArrayName)/sizeof(ArrayName[0])來計算。

4,同時定義UNICODE_UNICODE,或者兩個都不要定義。

5,使用windows API函數MultiByteToWideCharWideCharToMultiByte函數來實現ACSLL字符和UNICODE字符的相互轉換。

6,也可以使用C標準庫中的wcstombs來執行轉換。

 

經驗教訓:

一定注意在字符串操作時的越界問題,strcpy拷貝導致的越界沒有提示, 會導致程序出現不可預測的bug(比如說以前執行正確函數 突然出現內存讀取違法錯誤 崩潰了 頭大,why, 可能和某地方的字符數組越界有關。),使用支持安全的strcpy_s(http://blog.csdn.net/shutear/article/details/8256096

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章