Visual 中的一些字符指针学习

LPTSTR

已阅读 10 个网页

LPTSTR 是 Windows 编程中非常重要的一个数据类型,尤其在像 VC++ 6.0 这样的经典环境中非常常见。

简单来说,LPTSTR 是一个 指向字符串的长指针,但它的奇妙之处在于,它能根据你的项目设置(是否支持 Unicode)自动变身,让你的代码能更方便地在不同字符集之间移植。

1. LPTSTR 的“变身”原理

LPTSTR 的类型并不是固定不变的,它实际上是一个宏,它的真面目取决于你项目中是否定义了 UNICODE 宏。

  • 在“多字节字符集 (MBCS)” 或 “ANSI” 项目下

    • (也就是 没有定义 UNICODE 宏)

    • LPTSTR 会被定义为 LPSTR

    • LPSTR 本质上就是 char*,即指向单字节字符(ANSI)字符串的指针。

    • 你可以把它当作普通的C语言字符串来理解和使用。

  • 在 “Unicode” 项目下

    • (也就是 定义了 UNICODE 宏)

    • LPTSTR 会被定义为 LPWSTR

    • LPWSTR 本质上就是 wchar_t*,即指向宽字节字符(Unicode)字符串的指针。

这个机制意味着,你在代码中统一使用 LPTSTR,然后通过修改项目设置中的一个开关,就能让整个程序在ANSI和Unicode字符集之间切换,这在当时是非常实用的设计。

2. 名称的含义

这个名字的每一个部分都有它的历史含义:

  • LP:Long Pointer(长指针)。这是从16位Windows系统时代遗留下来的术语,在32位和64位系统中,它就是一个普通的指针,没有实际意义了。

  • T:代表 TCHAR 类型。表明这个指针指向的是 TCHAR 类型的数据,而 TCHAR 正是那个会根据 UNICODE 宏在 charwchar_t 之间切换的“万能”字符类型。

  • STR:String(字符串)。表明这是一个指向字符串的指针。

3. 如何在VC++ 6.0中使用它

在 VC++ 6.0 环境中,你通常会看到它与 TCHAR 系列函数和宏一起使用。

  • 定义变量

    c++

    LPTSTR lpszMyString; // 声明一个指向字符串的指针
    TCHAR szBuffer[128];  // 声明一个字符数组
  • 使用字符串常量
    为了配合 LPTSTR 的自动适应,在定义字符串常量时,最好使用 _T()TEXT() 宏。

    c++

    // 如果项目是ANSI,_T("你好") 会被解释为 "你好"
    // 如果项目是Unicode,_T("你好") 会被解释为 L"你好"
    LPTSTR lpszString = _T("这是一段测试文字");
  • 常用的相关类型
    你还会经常见到它的“亲戚”们:

    • LPCTSTR:增加了一个 C (const),表示这是一个 指向常量字符串的指针。它相当于 const TCHAR*,用于只读字符串,防止被意外修改。

    • LPSTR:不带 T,就是固定的 char* (ANSI字符串)。

    • LPWSTR:带 W (Wide),就是固定的 wchar_t* (Unicode字符串)。

类型含义 (ANSI/非Unicode环境)含义 (Unicode环境)
LPTSTRchar* (指向ANSI字符串)wchar_t* (指向Unicode字符串)
LPCTSTRconst char* (指向常量ANSI字符串)const wchar_t* (指向常量Unicode字符串)
TCHARcharwchar_t

总结

对于正在使用 VC++ 6.0 的你来说,可以把 LPTSTR 理解为一个“智能”的字符串指针。如果你的项目是普通的控制台程序或MBCS程序,它就是一个 char*;如果你的项目是为了处理中文、日文等需要广泛字符集而设置了Unicode支持,它就自动变成了 wchar_t*

为了方便和可移植性,在VC++ 6.0中处理字符串时,推荐使用 TCHARLPTSTR_T() 宏这套组合。

PSTR LPSTR CHAR CHAR* LPTSTR

在VC++ 6.0中,这些类型都是用来表示字符串的,但它们之间有一些细微的区别。我来帮你理清它们的关系:

1. 基础类型关系图

text

CHAR* = char*  (最基础的C语言字符串)
   │
   └── LPSTR = CHAR* = char* (Windows定义的ANSI字符串)
         │
         └── PSTR = LPSTR (完全等同,只是名字不同)

text

TCHAR* (根据宏定义变化)
   │
   ├── 如果定义了 _UNICODE → wchar_t*
   │
   └── 如果没有定义 _UNICODE → char* = LPSTR
         │
         └── LPTSTR = TCHAR* (可变字符串指针)

2. 详细解释每个类型

CHAR

c

// WinDef.h 中的定义
typedef char CHAR;
  • 就是C语言的 char 类型

  • 一个字节,用于存储ASCII字符

CHAR* 或 char*

  • 指向CHAR的指针

  • C语言最原始的字符串表示方法

LPSTR

c

// WinDef.h 中的定义
typedef CHAR *LPSTR;
  • Long Pointer to STRing

  • 指向ANSI字符串的长指针(32位指针)

  • 等价于 char*

  • 多用于Windows API中处理ANSI字符串

PSTR

c

// WinDef.h 中的定义
typedef CHAR *PSTR;
  • Pointer to STRing

  • 完全等同于 LPSTR

  • 只是名字不同,历史遗留原因

  • 在VC++ 6.0中两者可以互换使用

LPTSTR

c

// WinNT.h 中的定义
#ifdef _UNICODE
    typedef WCHAR *LPTSTR;  // WCHAR = wchar_t
#else
    typedef CHAR *LPTSTR;   // CHAR = char
#endif
  • Long Pointer to TCHAR STRing

  • 根据是否定义 _UNICODE 宏自动适应

  • 可移植性字符串类型

  • 在VC++ 6.0默认设置下(ANSI),等同于 LPSTR

3. 实际使用示例

c

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

int main()
{
    // 1. CHAR* / char* 的使用
    char* p1 = "Hello ANSI";           // 标准C字符串
    CHAR* p2 = "Hello CHAR*";          // 和上面完全一样
    
    // 2. LPSTR 的使用  
    LPSTR p3 = "Hello LPSTR";           // 等同于 char*
    LPSTR p4 = p2;                      // 可以和CHAR*互换
    
    // 3. PSTR 的使用
    PSTR p5 = "Hello PSTR";             // 完全等同于LPSTR
    PSTR p6 = p3;                        // LPSTR和PSTR可以互换
    
    // 4. LPTSTR 的使用(VC6默认是ANSI模式)
    LPTSTR p7 = _T("Hello LPTSTR");     // _T宏适应字符集
    
    // 5. 显示结果
    printf("CHAR*: %s\n", p2);
    printf("LPSTR: %s\n", p3);
    printf("PSTR: %s\n", p5);
    printf("LPTSTR: %s\n", p7);
    
    return 0;
}

4. 常见Windows API调用示例

c

#include <windows.h>

int main()
{
    // 情况1:用LPSTR调用API
    LPSTR lpStr = "C:\\test.txt";
    HANDLE hFile1 = CreateFileA(lpStr, GENERIC_READ, 0, NULL, 
                                 OPEN_EXISTING, 0, NULL);
    
    // 情况2:用LPTSTR调用API(VC6默认ANSI)
    LPTSTR lpStr2 = _T("C:\\test.txt"); 
    HANDLE hFile2 = CreateFile(lpStr2, GENERIC_READ, 0, NULL,
                                OPEN_EXISTING, 0, NULL);
    
    // 情况3:直接用char*
    char* pFile = "C:\\test.txt";
    HANDLE hFile3 = CreateFileA(pFile, GENERIC_READ, 0, NULL,
                                 OPEN_EXISTING, 0, NULL);
    return 0;
}

5. 总结对比表

类型本质是否可变字符集典型用途
CHARchar否(是字符)ANSI单个字符
CHAR*char*ANSIC风格字符串
LPSTRchar*ANSIWindows ANSI API
PSTRchar*ANSI与LPSTR完全等同
LPTSTRTCHAR*自适应可移植代码

6. 给VC++ 6.0用户的建议

  1. 新手入门:直接用 char* 最简单,不容易出错

  2. Windows编程:用 LPSTR 更规范,符合API习惯

  3. 想写可移植代码:用 LPTSTR + _T()

  4. 注意:在VC6默认设置下,LPTSTR = LPSTR = char*

一句话总结:在VC++ 6.0的默认配置下,CHAR*、LPSTR、PSTR、LPTSTR 其实都是 char*,可以互换使用。它们只是Windows为了代码清晰和可移植性而定义的不同名字。

把上面的整理成md我要做到CSDN的文章上面

markdown

# VC++ 6.0 中字符串类型详解:CHAR、LPSTR、PSTR、LPTSTR

在 Windows 编程,特别是 VC++ 6.0 环境中,字符串类型繁多,容易混淆。本文将详细解析 CHAR、LPSTR、PSTR、LPTSTR 这些类型的本质区别与联系。

## 1. 类型关系总览

CHAR* = char* (最基础的C语言字符串)

└── LPSTR = CHAR* = char* (Windows定义的ANSI字符串)

└── PSTR = LPSTR (完全等同,只是名字不同)

text


TCHAR* (根据宏定义变化)

├── 如果定义了 _UNICODE → wchar_t*

└── 如果没有定义 _UNICODE → char* = LPSTR

└── LPTSTR = TCHAR* (可变字符串指针)

text

## 2. 各类型详细解析

### CHAR
```c
// WinDef.h 中的定义
typedef char CHAR;
  • 本质:就是C语言的 char 类型

  • 大小:1个字节

  • 用途:存储单个ASCII字符

  • 特点:最基础的字符类型

CHAR* (char*)

  • 本质:指向CHAR的指针

  • 用途:C语言最原始的字符串表示方法

  • 特点:标准C风格字符串

LPSTR

c

// WinDef.h 中的定义
typedef CHAR *LPSTR;
  • 全称:Long Pointer to STRing

  • 本质:指向ANSI字符串的长指针(32位指针)

  • 等价于char*

  • 用途:Windows API中处理ANSI字符串

  • 特点:Windows编程中最常见的ANSI字符串类型

PSTR

c

// WinDef.h 中的定义
typedef CHAR *PSTR;
  • 全称:Pointer to STRing

  • 本质:完全等同于 LPSTR

  • 特点:历史遗留原因造成的命名差异,两者可互换使用

LPTSTR

c

// WinNT.h 中的定义
#ifdef _UNICODE
    typedef WCHAR *LPTSTR;  // WCHAR = wchar_t
#else
    typedef CHAR *LPTSTR;   // CHAR = char
#endif
  • 全称:Long Pointer to TCHAR STRing

  • 本质:根据 _UNICODE 宏自动适应的字符串类型

  • 特点

    • 可移植性字符串类型

    • 在VC++ 6.0默认设置(ANSI)下,等同于 LPSTR

    • 常与 _T() 宏配合使用

3. 实际代码示例

3.1 基本使用示例

c

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

int main()
{
    // 1. CHAR* / char* 的使用
    char* p1 = "Hello ANSI";           // 标准C字符串
    CHAR* p2 = "Hello CHAR*";          // 和上面完全一样
    
    // 2. LPSTR 的使用  
    LPSTR p3 = "Hello LPSTR";           // 等同于 char*
    LPSTR p4 = p2;                      // 可以和CHAR*互换
    
    // 3. PSTR 的使用
    PSTR p5 = "Hello PSTR";             // 完全等同于LPSTR
    PSTR p6 = p3;                       // LPSTR和PSTR可以互换
    
    // 4. LPTSTR 的使用(VC6默认是ANSI模式)
    LPTSTR p7 = _T("Hello LPTSTR");     // _T宏适应字符集
    
    // 5. 显示结果
    printf("CHAR*: %s\n", p2);
    printf("LPSTR: %s\n", p3);
    printf("PSTR: %s\n", p5);
    printf("LPTSTR: %s\n", p7);
    
    return 0;
}

3.2 Windows API 调用示例

c

#include <windows.h>

int main()
{
    // 情况1:用LPSTR调用API
    LPSTR lpStr = "C:\\test.txt";
    HANDLE hFile1 = CreateFileA(lpStr, GENERIC_READ, 0, NULL, 
                                 OPEN_EXISTING, 0, NULL);
    
    // 情况2:用LPTSTR调用API(VC6默认ANSI)
    LPTSTR lpStr2 = _T("C:\\test.txt"); 
    HANDLE hFile2 = CreateFile(lpStr2, GENERIC_READ, 0, NULL,
                                OPEN_EXISTING, 0, NULL);
    
    // 情况3:直接用char*
    char* pFile = "C:\\test.txt";
    HANDLE hFile3 = CreateFileA(pFile, GENERIC_READ, 0, NULL,
                                 OPEN_EXISTING, 0, NULL);
    
    return 0;
}

4. 类型对比表

类型本质是否指针字符集可变性典型用途
CHARcharANSI不可变(字符)单个字符
CHAR*char*ANSI可变C风格字符串
LPSTRchar*ANSI可变Windows ANSI API
PSTRchar*ANSI可变与LPSTR完全等同
LPTSTRTCHAR*自适应可变可移植代码

5. 相关辅助宏

_T() 或 TEXT() 宏

c

// 根据是否定义_UNICODE自动添加或省略L前缀
LPTSTR str = _T("This is a test");
// ANSI模式:等价于 "This is a test"
// Unicode模式:等价于 L"This is a test"

常用相关类型

类型说明等价于
LPCTSTRconst LPTSTRconst TCHAR*
LPCSTRconst LPSTRconst char*
LPCWSTRconst LPWSTRconst wchar_t*

6. VC++ 6.0 中的实际应用建议

6.1 不同场景的选择建议

使用场景推荐类型原因
新手学习char*简单直观,不易出错
Windows API编程LPSTR符合API习惯,规范
可移植代码LPTSTR + _T()支持ANSI/Unicode切换
常量字符串LPCTSTR防止意外修改
MFC编程CStringMFC封装好的字符串类

6.2 注意事项

  1. VC++ 6.0 默认设置:在默认安装的VC++ 6.0中,项目默认不使用Unicode,因此:

    • LPTSTR = LPSTR = char*

    • TCHAR = char

    • _T("") = ""

  2. 内存管理:这些类型都是指针,使用动态内存时需要自行分配和释放:

    c

    // 动态分配
    LPTSTR pBuf = (LPTSTR)malloc(100 * sizeof(TCHAR));
    // 使用...
    free(pBuf);
  3. API函数对应

    c

    // ANSI版本(A结尾)
    MessageBoxA(hWnd, lpStr, lpTitle, MB_OK);
    
    // Unicode版本(W结尾)
    MessageBoxW(hWnd, lpWStr, lpWTitle, MB_OK);
    
    // 通用版本(根据宏定义自动选择)
    MessageBox(hWnd, lpStr, lpTitle, MB_OK);

7. 常见问题解答

Q1: LPSTR 和 PSTR 到底有什么区别?

A: 没有本质区别!它们是同一个类型的两个不同名字,完全等价,可以互换使用。这只是Windows发展过程中的历史遗留问题。

Q2: VC++ 6.0 中 LPTSTR 到底是什么?

A: 在VC++ 6.0的默认设置下(未定义_UNICODE),LPTSTR 就是 LPSTR,也就是 char。只有当你手动在项目设置中启用Unicode支持后,它才会变成 wchar_t

Q3: 我应该用哪种类型?

A:

  • 如果你刚学C/C++:用 char* 最直接

  • 如果你在写Windows程序:用 LPSTR 更规范

  • 如果你想代码能在ANSI/Unicode间切换:用 LPTSTR + _T()

  • 如果你用MFC:直接用 CString 最方便

Q4: 为什么Windows要定义这么多字符串类型?

A: 主要是为了:

  1. 代码可读性:LPSTR明确表示这是一个"指向字符串的长指针"

  2. 可移植性:LPTSTR可以在ANSI和Unicode间切换

  3. 历史兼容:PSTR是更早的定义,LPSTR是为了强调"长指针"(16位时代)

8. 总结

在VC++ 6.0的默认配置下,CHAR*、LPSTR、PSTR、LPTSTR 本质上都是 char*,可以互换使用。它们只是Windows为了代码清晰、规范化和可移植性而定义的不同名字:

  • CHAR*:C语言原始风格

  • LPSTR:Windows ANSI编程标准

  • PSTR:LPSTR的别名

  • LPTSTR:可移植版本(默认=LPSTR)

理解这些类型的关系,对于阅读和编写Windows程序代码会很有帮助。

text


CHAR*:C语言原始风格 LPSTR:Windows ANSI编程标准 PSTR:LPSTR的别名 LPTSTR:可移植版本(默认=LPSTR)在VC6.0中都一样

你说得完全正确!在VC++ 6.0的默认配置下(未定义 _UNICODE 宏),这几者确实完全一样,都是 char*

以下是精简版的总结,适合放在CSDN文章中作为结论部分:


一句话总结(VC++ 6.0 默认配置)

类型本质说明
CHAR*char*C语言原始风格
LPSTRchar*Windows ANSI编程标准
PSTRchar*LPSTR的别名
LPTSTRchar*可移植版本(默认=LPSTR)

在VC++ 6.0默认设置下,这四种类型完全等价,都是 char*,可以互换使用。


验证代码

c

#include <windows.h>
#include <stdio.h>
#include <typeinfo.h>

int main()
{
    CHAR* p1 = NULL;
    LPSTR p2 = NULL;
    PSTR p3 = NULL;
    LPTSTR p4 = NULL;
    
    printf("CHAR*: %s\n", typeid(p1).name());
    printf("LPSTR: %s\n", typeid(p2).name());
    printf("PSTR: %s\n", typeid(p3).name());
    printf("LPTSTR: %s\n", typeid(p4).name());
    
    return 0;
}

在VC6默认配置下,输出都是:

text

CHAR*: char *
LPSTR: char *
PSTR: char *
LPTSTR: char *

注意事项

只有在项目设置中定义了 _UNICODE时,LPTSTR 才会变成 wchar_t*,其他三个仍然保持 char*

c

// 只有定义了 _UNICODE 时
// LPTSTR = wchar_t*
// 其他三个仍然是 char*

这个区别在你做CSDN文章时可以作为一个进阶知识点提及。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值