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)

 

 

 

 

你可能感兴趣的:(c,c++,c++,win32/x64)