程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> tchar char 字符 和 字符數組 字符串操作

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

編輯:C++入門知識

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

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要注意的小細節

     復制字符串總是在後2到3個字節後開始,前幾個字節不變,剛開始以為是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',應該要大小為9的buffer,這裡才會出錯,

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

非常重要的一個問題:

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

 

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

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

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

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

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

 

     對於win32 API函數來說,目前的windows操作系統內部都使用UNICODE來實現和字符串有關的函數。但是通常,都提供ASCLL和Unicode兩個版本的,如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函數MultiByteToWideChar和WideCharToMultiByte函數來實現ACSLL字符和UNICODE字符的相互轉換。

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

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved