Autor Beitrag
reimo
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 75



BeitragVerfasst: Fr 27.02.04 13:00 
also, folgendes Problem:

ich empfange über IP ein telegram mit dynamischer Länge, also reserviere ich den dafür nötigen Speicher auch dynamisch:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
Cnt : Integer;
pBuffer : ^Byte;
bRec: Byte;

Cnt := Socket.ReceiveLength;
GetMem( pBuffer, Cnt );

Socket.ReceiveBuf( pBuffer^, Cnt );

// so, jetzt möchte ich den buffer byteweise auslesen, aber wie???
// 1. Versuch

for i := 0 to Cnt-1 do begin
   bRec := pBuffer[i];      // schön wärs, geht leider nicht
end;

// 2. Versuch
bRec: ^Byte;

bRec := pBuffer;      // geht auch nicht, obwohl beide gleichen Typs, schreit der Compiler, dagegen bRec := @pBuffer funktioniert -> will ich aber nicht
for i := 0 to Cnt-1 do begin
   ...
   Inc(bRec);
end;

wie kann ich auf die einzelnen Bytes des reservierten Speichers zugreifen??
wieso kann ich einen Pointer nicht inkrementieren?

mfg
reimo

Moderiert von user profile iconTino: Titel geändert.
ErnestoChe
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: Fr 27.02.04 13:27 
Hallo,

ich nehme mal an, dass du versuchst es wie in C zu machen. Was Pointer und Arrays angeht unterscheidet sich Delphi von C. In deinem Fall würde ich einfach einen Pointer auf ein Byte-Arry machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
type
  TByteArr = array of Byte;
  PByteArr = ^TByteArr;

var
  pBuffer: PByteArr;

//..............................................

  pBuffer := New(PByteArr);
  SetLength(pBuffer^, Cnt);


MFG

- Ernesto -
Phantom1
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 390



BeitragVerfasst: Fr 27.02.04 13:30 
oder wenn du kein PByteArray verwenden möchtest, so hier:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
Cnt: Integer; 
pBuffer, 
bRec: PByte; 

Cnt := Socket.ReceiveLength; 
GetMem(pBuffer, Cnt); 

Socket.ReceiveBuf(pBuffer^, Cnt); 

bRec := pBuffer;         
for i := 0 to Cnt-1 do begin 
   ... 
   Inc(bRec); 
end;
reimo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 75



BeitragVerfasst: Fr 27.02.04 13:41 
cool, danke für die Antworten

wusste garnicht, dass man die Länge eines arrays dynamisch ändern kann.

in diesem Fall kann ich gleich die Funktion SetLength verwenden und mir den Zugriff über Pointer ersparen (falls ichs richtig verstanden habe)

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Buffer : array of Byte;

Cnt := Socket....

SetLenght( Buffer, Cnt);               
Socket.Receive( Buffer, Cnt );

for i := 0 to Cnt do begin
   xx := Buffer[i]
end;


@Phantom1
was wäre bei deinem Vorschlag der Unterschied zu meinem 2ten Versuch?
du hast bRec als PByte deklariert, ich dagegen als ^Byte, ist das nicht das selbe?

mfg
reimo
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Fr 27.02.04 13:41 
ErnestoChe hat folgendes geschrieben:
Hallo,

ich nehme mal an, dass du versuchst es wie in C zu machen. Was Pointer und Arrays angeht unterscheidet sich Delphi von C. In deinem Fall würde ich einfach einen Pointer auf ein Byte-Arry machen:

ausblenden Delphi-Quelltext
1:
2:
3:
type
  TByteArr = array of Byte;
  PByteArr = ^TByteArr;

Aber was du hier deklarierst ist ein Zeiger auf ein dynamisches Array und das kann ganz schnell Probleme machen..!

In der Unit SysUtils ist bereits ein Type TByteArray bzw PByteArray deklariert:
ausblenden Delphi-Quelltext
1:
2:
  PByteArray = ^TByteArray;
  TByteArray = array[0..32767of Byte;

Und mit so einer Deklaration funktioniert dann auch der gewünschte Zugriff...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
ErnestoChe
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: Fr 27.02.04 14:40 
Hallo,

Zitat:
Aber was du hier deklarierst ist ein Zeiger auf ein dynamisches Array und das kann ganz schnell Probleme machen..!


Hast du eine weitere Begründung, außer kann ganz schnell Probleme machen?

Es war nur ein Beispiel, um einen Denkanstoß zu geben. Er muss selber wissen ob das Array dynamisch oder statisch sein muss. Wenn man mit dem dynamischen Array sauber umgeht, kann auch nichts passieren.

MFG

- Ernesto -
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Fr 27.02.04 16:29 
Ein dynamischer Array ist in Delphi (genauso wie auch Strings) nur ein Pointer der implizit dereferenziert wird. Mit einem Pointer auf einen dyn. Array hast du also praktisch einen Pointer auf einen Pointer und daher in diesem Fall unbrauchbar...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
ErnestoChe
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: Fr 27.02.04 17:49 
Hallo,

Zitat:
Mit einem Pointer auf einen dyn. Array hast du also praktisch einen Pointer auf einen Pointer und daher in diesem Fall unbrauchbar


Stimmt, dynamische Arrays sind implizit Zeiger. Daher ist es zwar nicht unbrauchbar aber wohl unnötig.

Apropos Zeiger auf Zeiger. Wieso machst du eigentlich in deinem Pointer-Tutorial sowas:

Zitat:
type PMultipleForm = ^TMultipleForm;


MFG

- Ernesto -
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Fr 27.02.04 18:16 
ErnestoChe hat folgendes geschrieben:
Stimmt, dynamische Arrays sind implizit Zeiger. Daher ist es zwar nicht unbrauchbar aber wohl unnötig.

In diesem Fall ist es schon unbrauchbar..! Probier mal diesen Code aus, dann siehst du auch warum:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
const
  MAX_COUNT = 255;

type
  PDynByteArray = ^TDynByteArray;
  TDynByteArray = array of Byte;

  PStatByteArray = ^TStatByteArray;
  TStatByteArray = array [1..MAX_COUNT] of Byte;


procedure TForm1.Button1Click(Sender: TObject);
var
  szArray: array [1..MAX_COUNT] of Byte;
  pDynArray: PDynByteArray;
  pStatArray: PStatByteArray;
  i: Integer;
begin
  Listbox1.Clear;
  Listbox2.Clear;

  // den Array füllen
  for i := 1 to MAX_COUNT do
    szArray[i] := i;

  pDynArray := @szArray[1]; // dem Zeiger auf den dyn. Array die Adresse des Arrays zuweisen
  pStatArray := @szArray[1]; // dem Zeiger auf den stat. Array die Adresse des Arrays zuweisen

  // Listbox1 mit den Werten des Zeigers auf den stat. Array füllen
  for i := 1 to MAX_COUNT do
    Listbox1.Items.Add(IntToStr(pStatArray^[i]));

  // Listbox2 mit den Werten des Zeigers auf den dyn. Array füllen
  for i := 1 to MAX_COUNT do
    Listbox2.Items.Add(IntToStr(pDynArray^[i]));
end;

Bei der zweiten Schleife (in der eigentlich die Werte in die Listbox2 eingetragen werden sollten) wirst du nämlich mit einer wunderschönen EAccessViolation Exception begüßt.... Warum? Weil ein Zeiger auf einen dyn. Array eben ein Zeiger auf einen Zeiger ist welcher implizit nochmal dereferenziert wird. Dh die ersten 4 Bytes des Arrays auf das der Zeiger zeigt werden nochmal dereferenziert womit du an der Adresse $01020304 landest an der dann versucht wird auf den eigentlichen Array zuzugreifen...

Zitat:
Apropos Zeiger auf Zeiger. Wieso machst du eigentlich in deinem Pointer-Tutorial sowas:

Zitat:
type PMultipleForm = ^TMultipleForm;

Weil ich hier den Einsatz von Pointern und dyn. Speicherallozierung zeigen wollte.. du hast recht es sind im Prinzip auch wieder Zeiger auf Zeiger, aber wenn ich mich recht erinnere hab ich ganz am Schluss auch extra geschrieben, dass man das ganze auch ohne extra Zeiger machen kann da Objekte ohnehin nur Zeiger sind... Ich weiß das Beispiel ist nicht unbedingt gut gewählt, aber es ist schon sehr lang her dass ich das Tutorial damals geschrieben hab und ich in der zwischenzeit auch viel neues dazu gelernt, aber ich war bis jetzt zu faul das Tutorial zu überarbeiten... ;)

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
ErnestoChe
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: Sa 28.02.04 23:25 
Hallo,

@Motzi
Du hast Recht. Naja, meine Muttersprache ist nun mal C/C++.

Motzi hat folgendes geschrieben:
Ich weiß das Beispiel ist nicht unbedingt gut gewählt, aber es ist schon sehr lang her dass ich das Tutorial damals geschrieben hab und ich in der zwischenzeit auch viel neues dazu gelernt, aber ich war bis jetzt zu faul das Tutorial zu überarbeiten...:wink:


OK, kann man verstehen :wink:

MFG

- Ernesto -