2011-12-01 24 views
7

Tôi nhận được lỗi này:E2010 Các loại không tương thích, tại sao?

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

Sau đây là phần có liên quan của mã từ JwaStrSafe.pas (từ Jedi Api), tôi đang biên soạn với UNICODE biểu tượng định nghĩa:

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} 

Tôi nhận được lỗi trên cuộc gọi của StringCchCopyExW, trên tham số ppszDestEnd.

Nhìn vào định nghĩa loại tôi hiểu rằng PSTRSAFE_LPTSTR là loại con trỏ tới STRSAFE_LPTSTR, đây chỉ là bí danh của STRSAFE_LPWSTR, tại sao PSTRSAFE_LPTSTR và PSTRSAFE_LPWSTR không tương thích?

Giải pháp
Nhờ giải thích của David Tôi thay

PSTRSAFE_LPTSTR = ^STRSAFE_LPTSTR; 

với

PSTRSAFE_LPTSTR = PSTRSAFE_LPWSTR; 

bây giờ mã biên dịch mà không có lỗi.

Cảm ơn

+2

Bạn đang sử dụng phiên bản Delphi nào? –

+0

Tôi đang sử dụng Delphi XE2 –

Trả lời

3

Tôi có thể tạo lại điều này một cách dễ dàng trong XE2 và tôi tưởng tượng nó sẽ hoạt động giống nhau trong tất cả các phiên bản khác. Để làm cho nó đơn giản hơn tôi đã cắt nó xuống này:

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

Điều này cũng sản xuất E2010. Tuy nhiên, nếu bạn bật tùy chọn type-checked pointers thì mã sẽ biên dịch thành công. Trong thực tế, tài liệu về điều đó tùy chọn trình biên dịch rằng:

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.


Nhờ Ken Trắng đã chỉ cho tôi tại sự giúp đỡ hữu ích chủ đề Type Compatibility and Identity. Các chiết xuất thích hợp là rằng các loại T1 và T2 là phân tương thích nếu:

T1 and T2 are compatible pointer types.

Các tài liệu cũng nói rằng loại là loại compatibile nếu:

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

Vì vậy, đây tài liệu hành vi quan sát và dẫn tôi đến ví dụ này:

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

Vì vậy, để tóm tắt:

  • Khi con trỏ được đánh dấu chọn bị tắt, con trỏ được gán tương thích nếu con trỏ cùng loại.
  • Khi con trỏ được đánh dấu chọn được bật, con trỏ sẽ được gán tương thích nếu con trỏ trỏ đến cùng một loại.

Tôi phải thú nhận là không biết gì về lịch sử và lý do đằng sau cài đặt con trỏ được kiểm tra loại, vì vậy tôi không thể đưa ra bất kỳ lời giải thích nào về lý do trình biên dịch là như thế.

+3

Điều này có thể giúp: [Type Identity] (http://docwiki.embarcadero.com/RADStudio/en/Type_Compatibility_and_Identity). –

+0

@Ken Cảm ơn, điều đó đã giúp ích rất nhiều! –

+0

Bạn được chào đón. Bạn đã đặt quá nhiều công việc vào nó mà không có liên kết; Tôi không muốn sử dụng nó và ăn cắp công việc của bạn. :) Công việc tuyệt vời - +1. –

Các vấn đề liên quan