2009-07-08 9 views
1

我寫兩種方法具有空隙型參數:讀取和分配空隙類型參數

procedure Method1(const MyVar; size: cardinal); 
var 
    Arr: array of byte; 
begin 
    SetLength(Arr, size); 
    {now copy the data from MyVar to Arr, but how?} 
end; 

procedure Method2(var MyVar; size: cardinal); 
var 
    Arr: array of byte; 
begin 
    SetLength(Arr, size); 
    {return the data from the array, but how?} 
end; 

在我想訪問MyVar的作爲字節陣列的第一個。在第二個中,我想將本地數組Arr中的數據複製到MyVar。因此我使用了CopyMemory()函數,但它有些問題。 (Method2(Pointer(MyString)^,Length(MyString))或Method2(Pointer(MyArray))方法調用Method2是正常的,如果我在第二種方法中使用以下內容, ,Length(MyArray)))。

CopyMemory(Pointer(MyVar), Pointer(Arr), size); 

如果我調用方法二用,例如,整型參數(方法二(MyInteger,一下SizeOf(MyInteger))),它不能正常工作。在這種情況下,CopyMemory的()已被稱爲是這樣的:

CopyMemory(@MyVar, Pointer(Arr), size); 

如何返回從方法2的數據正確,不知道它是否是一個簡單的類型(或記錄)或數組?這種情況將在方法1相似,但在這裏我將不得不使用

CopyMemory(Pointer(Arr), Pointer(MyVar), size); 
在數組中的情況下

CopyMemory(Pointer(Arr), @MyVar, size); 

簡單類型的情況。

當我不知道MyVar參數是什麼時,我該怎麼辦?

回答

6

Delphi中沒有這樣的void類型。你所指的是untyped parameter

一個無類型的參數總是實際的東西本身,而不是你應該使用的東西的指針。因此,要使用CopyMemory這樣的參數的正確方法是將@操作適用於它,像這樣:

CopyMemory(@MyVar, @Arr[0], size); 

通知我也改變了我傳遞的第二個參數的方式。如果不依賴於動態數組真的是指向第一個元素的指針,那更好。如果你需要一個指向第一個元素的指針,那就明確地說,就像我在這裏所做的那樣。

您的困惑來自您在參數使用時所做的測試,就像它是一個指針一樣,並且測試似乎正常工作。不過,我懷疑這種測試的有效性。當你說Pointer(MyString)^時,你所擁有的是字符串的第一個字符。當你在函數內部說Pointer(MyVar)時,你將該字符輸入到一個指針中,這是一種無效的類型轉換。如果你的程序似乎有效,那只是偶然的;你的代碼錯了。

我可以給的最好的建議是不輸入類型的東西,除非你真的必須。而當你這樣做的時候,請確保你正在進行類型轉換的東西確實有這種類型。在你的情況下,在你將它作爲一個無類型參數傳遞之前,你不需要輸入任何東西。您可以撥打Method1這樣的:

Method1(MyString[1], Length(MyString) * Sizeof(Char)); 

(我乘SizeOf(Char),因爲我不知道你是否有德爾福2009年或沒有。)

另外,不要避免非類型參數。編譯器可以幫助確保程序正確性的一件大事是強制執行類型安全性,但是當你拿走這些類型時,編譯器不能再幫你了。

4

你的問題是你傳遞數據或指針到數據到方法1/2。你應該總是傳遞數據本身。 可能你只是忘記了動態數組本身就是一個指針?您不應該在您的方法中傳遞A或指針(A)(這裏的A是動態數組)。通過A [0]或指針(A)^。

procedure Method1(const MyVar; size: cardinal); 
var 
    Arr: array of byte; 
begin 
    SetLength(Arr, size); 
    CopyMemory(Pointer(Arr), @MyVar, Size); 
end; 

procedure Method2(var MyVar; size: cardinal); 
var 
    Arr: array of byte; 
begin 
    SetLength(Arr, size); 
    Arr[0] := 1; 
    Arr[1] := 2; 
    Arr[2] := 3; 
    Arr[3] := 4; 
    CopyMemory(@MyVar, Pointer(Arr), Size); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    I: Integer; 
    A: array of Integer; 
begin 
    I := $01020304; 
    Method1(I, 4); // we pass data itself, not the pointer to it. 
    Method2(I, 4); 
    SetLength(A, 2); 
    A[0] := 0; 
    A[1] := $01020304; 
    Method1(A[0], Length(A) * SizeOf(A[0])); // note, that we pass data, not pointer 
    Method2(A[0], Length(A) * SizeOf(A[0])); // A or Pointer(A) is a pointer to array's data 
end; 

如果A是動態數組:

  1. A [0]是相同的指針(A)^和表示數組的數據。
  2. @A [0]與指針(A)或A相同,代表數組本身,它是指向其數據的指針(以及有關負偏移的一些技術信息)。

如果A是靜態數組:

  1. A [0]相同,A和表示數組本身,這是陣列的數據。
  2. @A [0]與@A相同,表示指向數組的指針。指針(A)或指針(A)^是沒有意義的。

請注意,Method1/2中的Arr也是一個動態數組,因此我們將它轉​​換爲指針(CopyMemory詢問指針,而不是數據)。如果我們想要使用Move例程(它詢問數據),我們應該寫指針(A)^代替。

+0

謝謝你的回答。似乎我以錯誤的方式調用了我的方法,這就是爲什麼我得到了AV異常,並認爲CopyMemory()函數必須以兩種不同的方式調用。感謝您的解釋,我很容易找到我的錯誤。 – 2009-07-09 18:49:39

+0

@亞歷山大。你的總結很好。 – Dylan 2011-08-23 09:40:51

相關問題