delphi - E2010 不兼容类型,为什么?

标签 delphi unicode types

我收到此错误:

[DCC Error] JwaStrSafe.pas(2277): E2010 Incompatible types: 'PSTRSAFE_LPWSTR' and 'PSTRSAFE_LPTSTR'

以下是来自 JwaStrSafe.pas(来自 Jedi Api)的代码的相关部分,我使用定义的符号 UNICODE 进行编译:

type

STRSAFE_LPWSTR = PWIDECHAR;
PSTRSAFE_LPWSTR = ^STRSAFE_LPWSTR;

{$IFDEF UNICODE}
  STRSAFE_LPTSTR = STRSAFE_LPWSTR;
  PSTRSAFE_LPTSTR = ^STRSAFE_LPTSTR;
{$ELSE}
  ...
{$ENDIF}

...
//function declaration
function StringCchCopyExW(
  {__out_ecount(cchDest)}pszDest : STRSAFE_LPWSTR;
  {__in}cchDest : size_t;
  {__in}const pszSrc : STRSAFE_LPCWSTR;
  {__deref_opt_out_ecount(pcchRemaining^)}ppszDestEnd : PSTRSAFE_LPWSTR;
  {__out_opt}pcchRemaining : PSize_t;
  {__in}dwFlags : Cardinal) : HRESULT; stdcall; forward; external;

...
//var passed to function
ppszDestEnd : PSTRSAFE_LPTSTR;

...

{$IFDEF UNICODE}
  result := StringCchCopyExW(pszDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
{$ELSE}
  result := StringCchCopyExA(pszDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
{$ENDIF}

我在参数 ppszDestEnd 上调用 StringCchCopyExW 时收到错误。

查看类型定义,我了解到 PSTRSAFE_LPTSTR 是指向 STRSAFE_LPTSTR 的指针类型,而 STRSAFE_LPTSTR 只是 STRSAFE_LPWSTR 的别名,为什么 PSTRSAFE_LPTSTR 和 PSTRSAFE_LPWSTR 不兼容?

解决方案
感谢大卫的解释我更换了

PSTRSAFE_LPTSTR = ^STRSAFE_LPTSTR;

PSTRSAFE_LPTSTR = PSTRSAFE_LPWSTR;

现在代码编译没有错误。

谢谢

最佳答案

我可以在 XE2 中轻松地重现这一点,并且我想它在所有其他版本中都会表现相同。为了使其更简单,我将其简化为:

program PointerTypeCompatibility;
{$APPTYPE CONSOLE}
type
  A = Integer;
  B = Integer;
var
  ptA: ^A;
  ptB: ^B;
begin
  ptA := ptB;
end.

这也会产生 E2010。但是,如果您启用type-checked pointers选项,然后代码编译成功。事实上,该编译器选项的文档指出:

In the {$T-} state, distinct pointer types other than Pointer are incompatible (even if they are pointers to the same type). In the {$T+} state, pointers to the same type are compatible.

<小时/>

感谢 Ken White 向我指出有用的帮助主题 Type Compatibility and Identity 。相关摘录是类型 T1 和 T2 是赋值兼容的,如果:

T1 and T2 are compatible pointer types.

文档还指出,如果满足以下条件,类型类型兼容:

Both types are (typed) pointers to the same type and the {$T+} compiler directive is in effect.

因此,这记录了观察到的行为并引导我看到这个示例:

program PointerTypeCompatibilityTake2;
{$APPTYPE CONSOLE}
{$TYPEDADDRESS OFF}
var
  P1,P2: ^Integer;
  P3: ^Integer;
begin
  P1 := P2;//compiles
  P1 := P3;//E2008 Incompatible types
end.

所以,总结一下:

  • 当类型检查指针被禁用时,如果指针属于相同类型,则指针是赋值兼容的。
  • 启用类型检查指针后,如果指针指向相同类型,则指针是赋值兼容的。

我必须承认我对类型检查指针设置背后的历史和推理一无所知,所以我无法提供任何解释为什么编译器是这样的。

关于delphi - E2010 不兼容类型,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8349464/

相关文章:

delphi - 我不知道是否需要或如何实现接口(interface)的这 3 个基本方法

delphi - fmShareDenyWrite 模式似乎不起作用

java - 如何用不同的 Unicode 字符构建最长的字符串

python - 将字符串 '\u05d9\u05d7\u05e4\u05d9\u05dd' 转换为其在 python 中的 unicode 字符

types - Elixir、透析器、类型和子类型警告

JavaScript 括号对加法期间类型转换的影响

c - 如何将 linmath.h 矩阵传递给 glsl 着色器?

delphi - 调用 ShowModal 并设置 PopupParent 是一个好主意吗?在较新的 Delphi 版本中是否有必要?

visual-studio-2010 - 通过注入(inject)的 Delphi dll 启用 __fastcall 来 Hook 在 MSVC++ 上制作的应用程序

java - Java String 中的字符数