【问题标题】:Why do I need to cast the lpBuffer (LPTSTR) parameter in FormatMessage?为什么我需要在 FormatMessage 中强制转换 lpBuffer (LPTSTR) 参数?
【发布时间】:2014-08-04 12:58:08
【问题描述】:

在Windows的FormatMessage()函数中,参数:

  _Out_     LPTSTR lpBuffer

正在努力。按照 Hart 的 Windows 系统编程书,我声明了一个 LPTSTR 指针用作 lpBuffer(例如 LPTSTR errortext;),然后调用 FormatMessage() 函数.

这个参数的正确传入方式是:(LPTSTR)&errorText

这很好用。但我不明白为什么我需要写(LPTSTR)。我知道这是类型转换,我读过它,但对我来说没有意义,因为我没有更改变量类型或任何东西,我将其声明为 LPTSTR 并将其内存地址传递给函数,该函数需要一个LPTSTR,而我传递给它一个LPTSTR,那么为什么我需要将(LPTSTR) 作为lpBuffer 参数的一部分?

【问题讨论】:

  • 嗯,你是对的,使用演员表是从不正确的。它只会阻止编译器告诉你你做错了。如果您不发布代码,为什么您认为您需要它是无法发现的。
  • 您需要展示一些代码。你究竟是如何声明errortext。它的内存是如何分配的?你在用FORMAT_MESSAGE_ALLOCATE_BUFFER吗?
  • @HansPassant 这不是演员阵容是唯一解决方案的例子吗?这就是为什么我认为这是一个好问题,它不是关于调试,而是关于理解为什么需要演员表,IMO。
  • 不,char[] 和 wchar_t[] 在结构上不兼容,元素的大小不同。无论如何,强制转换要么产生中文或单个字符的 C 字符串,而且缓冲区溢出的可能性很高,YMMV。它需要转换,例如 MultiByteToWideString()。
  • 但是演员表是TCHAR*,因为这个函数只需要TCHAR*。该函数有两种不同的用法,一种是TCHAR*,另一种是TCHAR**,看我的回答。

标签: c++ c winapi formatmessage


【解决方案1】:

FormatMessage()的参数lpBuffer记录如下:

指向缓冲区的指针,该缓冲区接收以 null 结尾的字符串 指定格式化的消息。如果 dwFlags 包括 FORMAT_MESSAGE_ALLOCATE_BUFFER,该函数使用分配缓冲区 LocalAlloc 函数,并将指向缓冲区的指针放在 lpBuffer 中指定的地址。

所以FormatMessage()有两种不同的用法,

1) 提供您自己的缓冲区

const DWORD bufsize = ....;
TCHAR buf[bufsize];
FormatMessage(.... buf, bufsize, ....); // buf is passed as a TCHAR*

2) FormatMessage 为你分配一个缓冲区

const DWORD bufsize = ....;
TCHAR* buf = 0;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | ....,
    .... (LPTSTR)&buf, bufsize, ....); // &buf is a TCHAR** so type-cast needed!
....
LocalFree(buf);

在#1 中,您必须传递缓冲区中第一个TCHAR 的地址,该函数只是将其填充到缓冲区中。

在#2 中,函数需要告诉你它在哪里分配了一个新的缓冲区,所以你必须告诉它在哪里放置那个地址。您必须传递接收地址的指针变量的地址。

简而言之:

  • #1 需要 TCHAR* 到现有缓冲区
  • #2 需要一个接收新缓冲区的TCHAR**

这就是为什么lpBuffer 参数在使用#2 时必须进行类型转换。

【讨论】:

  • 感谢您的解释。我不明白&buf 是如何变成TCHAR** 而不是保持TCHAR*。函数分配一个缓冲区,缓冲区的起始地址分配给&buf,对吧?这意味着buf 将仍然是指向缓冲区的常规指针。我确定我在这里遗漏了一些东西。我是要将TCHAR** 转换为TCHAR*/LPTSTR(如果是这样,我不明白TCHAR** 是如何产生的),还是将缓冲区本身从某种默认类型转换为LPTSTR
  • @user3733070 是的,buf 在这两种情况下都只是指向文本的指针。在 1) 中,直接传递指针以使函数访问文本,但在 2) 中,函数需要访问指针,因此您使用 &buf 传递指针的地址。 bufTCHAR*&bufTCHAR**。该函数被声明为采用TCHAR*,因此TCHAR** 被转换回TCHAR*
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-05
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 2015-01-29
相关资源
最近更新 更多