• char,wchar_t,WCHAR,TCHAR,ACHAR的区别----LPCTSTR


    转自http://blog.chinaunix.net/uid-7608308-id-2048125.html

    简介:这是DWORD及LPCTSTR类型的了解的详细页面,介绍了和类,有关的知识,加入收藏请按键盘ctrl+D,谢谢大家的观看!要查看更多有关信息,请点击此处

     首先声明,这都是在网上找的资料,我再整理修改的:

    一:关于DWORD

    DWORD就是32bit的unsigned  long无符号长整型,DWORD是双字类型 ,4个字节,API函数中有很多参数和返回值是DWORD的。

    二:如何理解LPCTSTR类型?

     (一)LPCTSTR类型的概念

       L表示long指针 这是为了兼容Windows 3.1等16位操作系统遗留下来的,在win32中以及其他的32为操作系统中, long指针和near指针及far修饰符都是为了兼容的作用。没有实际意义。

      P表示这是一个指针

      C表示是一个常量

      T表示在Win32环境中, 有一个_T宏

      这个宏用来表示你的字符是否使用UNICODE, 如果你的程序定义了UNICODE或者其他相关的宏,那么这个字符或者字符串将被作为UNICODE字符串,否则就是标准的ANSI字符串。

    和 "DWORD及LPCTSTR类型的了解" 有关的 c#、asp.net、c++ 编程小帖士:

    strong>Sqrt(number)
    取得一数值得平方根。 
      STR表示这个变量是一个字符串

      所以LPCTSTR就表示一个指向常固定地址的可以根据一些宏定义改变语义的字符串。

      同样, LPCSTR就只能是一个ANSI字符串,在程序中我们大部分时间要使用带T的类型定义。

      LPCTSTR == const TCHAR *

      UNICODE方式下,CString 和 LPCTSTR 可以说通用。

        常量字符串ansi和unicode的区分是由宏_T来决定的。但是用_T("abcd")时, 字符串"abcd"就会根据编译时的是否定义_UNICODE来决定是char* 还是 wchar_t*。     

        (二)这里插入一些关于char,wchar_t,WCHAR,TCHAR,ACHAR的区别的说明:

           现在C++的字符分成两种类型wchar_t和char。

        

         char:
         ANSI字符串,可用字符串处理函数strcat( ),strcpy( ), strlen( )等以str打头的函数。

         wchar_t :
         wchar_t是Unicode字符的数据类型,它的实际定义为:

         typedef unsigned short wchar_t; 
         wchar_t 可用字符串处理函数:wcscat(),wcscpy(),wcslen()等以wcs打头的函数。

         WCHAR:
         在头文件中有这样的定义:typedef wchar_t WCHAR; 所以WCHAR实际就是wchar_t。
    在C语言里面提供了_UNICODE宏(有下划线),在Windows里面提供了UNICODE宏(无下划线),只要定了_UNICODE宏和UNICODE宏,系统就会自动切换到UNICODE版本,否则,系统按照ANSI的方式进行编译和运行。只定义了宏并不能实现自动的转换,他还需要一系列的字符定义支持。

        TCHAR:
        如果定义了UNICODE宏则TCHAR被定义为wchar_t。typedef wchar_t TCHAR; 否则TCHAR被定义为char typedef char TCHAR;

        ACHAR:
        此类型是AUTODESK公司在adachar.h 头文件中定义的。
    当定义了AD_UNICODE(AUTODESK公司使用UNICODE宏)时为wchar_t。

         WCHAR,CHAR,TCHAR的关系实际上是这样的  

         typedef unsigned short wchar_t;
         #ifdef   UNICODE     
                typedef   wchar_t   TCHAR;     
         #else     
                typedef   unsigned   char   TCHAR;     
         #endif     

            

           typedef   unsigned   char   CHAR;     
         typedef   unsigned   wchar_t   WCHAR; 

    在VS2005/2008中,c++对字符串的处理已经默认采用了unicode版本了。 Unicode可以使你的程序能够更全面的支持多国语言文字,即使在英文,日文等系统下也不会出现乱码。而且NT内核基于Unicode,可以减少了系统 的编码转换开销,提高程序运行速度,并且可以支持更多的微软新推出的仅支持Unicode的API。但是有可能会造成在95/98下程序运转不正常。

    (三)CString类对象

    CString是基于TCHAR数据类型的对象。如果在你的程序中定义了符号_UNICODE,则TCHAR被定义为类型wchar_t,即16位字符类型;否则,TCHAR被定义为char,即8位字符类型。 

        在UNICODE方式下,CString对象由16位字符组成。非UNICODE方式下,CString对象由8位字符组成。 

        当不使用_UNICODE时,CString是多字节字符集(MBCS,也被认为是双字节字符集,DBCS)。注意,对于MBCS字符串,CString仍然基于8位字符来计算,返回,以及处理字符串,并且你的应用程序必须自己解释MBCS的开始和结束字节。

    UNICODE方式下CString与wchar_t是通用的 
    就是说在vs2005中, 
    WCHAR str=L"字符串"; 
    CString str1=str; 
    是可以通过编译的,但到vc6中就不可以了

    通用 MFC 数据类型

    映射到 ASCII

    映射到 UNICODE

    注释

    _TCHAR

    char

    wchar_t

    _TCHAR 是一个映射宏,当定义 UNICODE 时,该数据类型映射到 wchar_t,如果没有定义 UNICODE,那么它映射到 char。

    _T 或 _TEXT

    char 常量字符串

    wchar_t 常量字符串

    功能与宏相同,在 ASCII 模式下,它们被忽略,也就是说被预处理器删除掉,但是如果定义了UNICODE, 则它们会将常量字符串转换成等价的 UNICODE 。

    LPTSTR

    char*, LPSTR(Win32)

    wchar_t*

    可移植的32位字符串指针。它将字符类型映射到工程设置的类型。

    LPCTSTR

    const char*, LPCSTR(Win32)

    const wchar_t*

    可移植的32位常量字符串指针。它将字符类型常量映射到工程设置的类型。

    (五)UNICODE WCHAR*到 char * 
     CString str(wchar*);
    LPCSTR       32-bit   指针,指向一个常量字串   
    LPSTR        32-bit   指针,指向一个字串   
    LPCTSTR      32-bit   指针,指向一个常量字串。此字串可移植到Unicode和DBCS   
    LPTSTR       32-bit   指针,指向一个字串。此字串可移植到Unicode和DBCS 
    LPWSTR       32-bit   指针,指向一个unicode字符串的指针   
    LPCWSTR      32-bit   指针, 指向一个unicode字符串常量的指针   
    前面的L代表LONG,P就是指针的意思,C就是constant的意思, W是wide的意思,STR就是string的意思

    (六)ANSI的情况

    ANSI情况下,LPCTSTR 就是 const char*, 是常量字符串(不能修改的)。

      而LPTSTR 就是 char*, 即普通字符串(非常量,可修改的)。

      这两种都是基本类型, 而CString 是 C++类, 兼容这两种基本类型是最起码的任务了。

      由于const char* 最简单(常量,不涉及内存变更,操作迅速), CString 直接定义了一个类型转换函数

      operator LPCTSTR() {......}, 直接返回他所维护的字符串。

      当你需要一个const char* 而传入了CString时, C++编译器自动调用 CString重载的操作符 LPCTSTR()来进行隐式的类型转换。

      当需要CString , 而传入了 const char* 时(其实 char* 也可以),C++编译器则自动调用CString的构造函数来构造临时的 CString对象。

      因此CString 和 LPCTSTR 基本可以通用。

      但是 LPTSTR又不同了,他是 char*, 意味着你随时可能修改里面的数据,这就需要内存管理了(如字符串变长,原来的存贮空间就不够了,则需要重新调整分配内存)。

      所以 不能随便的将 const char* 强制转换成 char* 使用。

      如例子:

      LPSTR lpstr = (LPSTR)(LPCTSTR)string;

      就是这种不安全的使用方法。

      这个地方使用的是强制类型转换,你都强制转换了,C++编译器当然不会拒绝你,但同时他也认为你确实知道自己要做的是什么。因此是不会给出警告的。

      强制的任意类型转换是C(++)的一项强大之处,但也是一大弊端。这一问题在 vc6 以后的版本(仅针对vc而言)中得到逐步的改进(你需要更明确的类型转换声明)。

      其实在很多地方都可以看到类似

      LPSTR lpstr = (LPSTR)(LPCTSTR)string;

      地用法,这种情况一般是函数的约束定义不够完善的原因, 比如一个函数接受一个字符串参数的输入,里面对该字符串又没有任何的修改,那么该参数就应该定义成 const char*, 但是很多初学者弄不清const地用法,或者是懒, 总之就是随意写成了 char* 。 这样子传入CString时就需要强制的转换一下。

      这种做法是不安全的,也是不被建议的用法,你必须完全明白、确认该字符串没有被修改。

      CString 转换到 LPTSTR (char*), 预定的做法是调用CString的GetBuffer函数,使用完毕之后一般都要再调用ReleaseBuffer函数来确认修改 (某些情况下也有不调用ReleaseBuffer的,同样你需要非常明确为什么这么做时才能这样子处理,一般应用环境可以不考虑这种情况)。

      同时需要注意的是, 在GetBuffer 和 ReleaseBuffer之间,CString分配了内存交由你来处理,因此不能再调用其他的CString函数。

      CString 转LPCTSTR:

      CString cStr;

      const char *lpctStr=(LPCTSTR)cStr;

      LPCTSTR转CString:

      LPCTSTR lpctStr;

      CString cStr=lpctStr;

    -------------------------------
     

    #define UNICODE
    #define _UNICODE//TCHAR默认为char 定义UNICODE后为wchar_t


    #include <stdio.h>
    #include <tchar.h>
    #include <locale.h>
    #include <stdlib.h>
    int main()
    {
        //int i;

        wchar_t a;
        TCHAR b;
        wchar_t c[10];
        wcscpy(c,L"我是谁");
        long *p;
        printf("wchar_t len is %d tchar len is %d wchar_t array len is %d ",
            sizeof(wchar_t),sizeof(TCHAR),sizeof(c));
        setlocale(LC_ALL, "chs"); //没有该行则wprintf输出为空
        wprintf(L"c is %s ",c);
        c[2]='';
        wprintf(L"c update is %s ",c);
        system("pause");
        p=(long *)malloc(8*1024*1024);
        system("pause");
        free(p);
        //while(getchar()!='c');

        system("pause");
        return 0;
    }

  • 相关阅读:
    本周总结
    本周总结:用户故事和用户场景
    排球比赛规则说明书
    我与计算机
    官网地址备份
    连续自然数序列,求取中位数方案
    Spark 实现自定义对象sequenceFile方式存储,读写示例(scala编写)
    hbase 异常
    python_初步
    redis_入门网址
  • 原文地址:https://www.cnblogs.com/wangchengfeng/p/3715779.html
Copyright © 2020-2023  润新知