array [0..0] in einem record auf array[0..1] ändern

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
jus
Beiträge: 52
Registriert: Fr 6. Mai 2011, 13:29

array [0..0] in einem record auf array[0..1] ändern

Beitrag von jus »

Hallo,
ich habe folgendes Problem, dass ich in meinem Programm unter Mac folgende Recordstruktur benötige:

Code: Alles auswählen

NCMConcatProfileSet = record
    cmm: OSType;        
    flags: UInt32;          
    flagsMask: UInt32;   
    profileCount: UInt32;         
    profileSpecs: array [0..1] of NCMConcatProfileSpec;   // <-------- Array mit 2 Elemente
  end;
sprich ein Record, das 2 mal NCMConcatProfileSpec enthält.

in der Lazarus Unit wird es wie folgt definiert:

Code: Alles auswählen

NCMConcatProfileSet = record
		cmm: OSType;    
		flags: UInt32;      
		flagsMask: UInt32;
		profileCount: UInt32;
		profileSpecs: array [0..0] of NCMConcatProfileSpec;  // <-------- Array mit 1 Element
	end;
Ich habe mich derzeit damit beholfen, dass ich mir ein neues record mit MeinNCMConcatProfileSet definiert habe, und funktioniert auch. Aber wie kann aber die ursprüngliche Recorddefinition mitten im Programm dynamisch anpassen?

lg,
jus

u-boot
Beiträge: 308
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von u-boot »

Ich bin nicht unbedingt Spezialist, aber ich denke es wird nicht grundlos statisches Array genannt.

Für dynamisches Array wäre die Deklaration folgende:

Code: Alles auswählen

profileSpecs: array of NCMConcatProfileSpec;
Mit setlength kann man dann die Länge des Arrays dynamisch festlegen. Im Initialzustand kann das Array 0 Elemente aufnehmen.
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von Hitman »

u-boot hat geschrieben:Ich bin nicht unbedingt Spezialist, aber ich denke es wird nicht grundlos statisches Array genannt.

Für dynamisches Array wäre die Deklaration folgende:

Code: Alles auswählen

profileSpecs: array of NCMConcatProfileSpec;
Mit setlength kann man dann die Länge des Arrays dynamisch festlegen. Im Initialzustand kann das Array 0 Elemente aufnehmen.
Das wäre in dem Fall mit Sicherheit keine gute Idee. Die Datenstruktur hat an der Stelle konkrete Werte, wohingegen ein dynamisches Array nur ein Pointer wäre und die eigentlichen Daten damit außerhalb der erwarteten Struktur liegen würden.

Zur ursprünglichen Frage: ohne Neudeklaration (wie du es jetzt bereits machst) wird es nicht gehen ... im Prinzip ist es halt eine andere Datenstruktur. Man könnte sich lediglich das Layout im Speicher zunutze machen, und im "neuen" Record zuerst ein Feld vom Typ des ersten Records zu halten und von einem weiteren [0..0] Array folgen zu lassen. Richtig zuverlässig würde das aber wohl auch nur gehen, wenn beide Records packed wären.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von pluto »

Warum brauchst du einmal eine Länge von 1 und einmal eine Länge von 0? Ich würde in diesen Fall einfach zwei variablen hinzufügen:
profileSpecs1 und profileSpecs2 Fertig. Ein Array macht für mich keinen Wirklichen Sinn an dieser Stelle, da die Anzahl sehr Überschaubar ist.

Aber es gibt eine Eventuelle Möglichkeit: Du kannst mit Kompiliere Direktiven Arbeiten. Vielleicht hilft auch schon case in diesen Fall:
http://www.delphi-treff.de/object-pasca ... pen/#c4901" onclick="window.open(this.href);return false;
Unter "Variante Records"

edit01: Verstehe ich es richtig? Es ist eine LCL Datenstruktur? Keine eigene? Schade...
MFG
Michael Springwald

martin_frb
Beiträge: 586
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von martin_frb »

Code: Alles auswählen

NCMConcatProfileSet = record
    cmm: OSType;        
    flags: UInt32;          
    flagsMask: UInt32;
    profileCount: UInt32;         
    profileSpecs: array [0..0] of NCMConcatProfileSpec;
end;
Das sieht aus, wie eine Struktur die an das OS, der eine Library übergeben wird, und zwar via pointer?
Das heißt beim Aufruf setzt man " profileCount := 2", und die Einträge stehen im array?

Da das array ja inline seien muss, *und* dynamisch lässt sich das in Pascal nicht deklarieren.

Eine solche Struktur wird normalerweise mit Pointern und getmem verwendet.

type PNCMConcatProfileSet = ^NCMConcatProfileSet
var Foo: PNCMConcatProfileSet ;

Foo = GetMem( Sizeof(PNCMConcatProfileSet) + (ProfCnt-1)*SizeOf(NCMConcatProfileSpec) );

"-1" weil ja bereits platz fuer ein Eintrag da ist.

Compiliert OHNE range-checks kann man dann
Foo^.profileSpecs[x]

fuer x zwischen 0 und ProfCnt-1

Am ende FreeMem....

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von pluto »

Möchtest du damit sagen, dass man ein Statischen Array durchaus erweitern kann, über Tricks? Aber was bringt mir ein Array von der Länge 0 oder 1?
Denn Sinn sehe ich einfach nicht. Dann lohnt sich gar kein Array oder?
MFG
Michael Springwald

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6780
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von af0815 »

pluto hat geschrieben:Möchtest du damit sagen, dass man ein Statischen Array durchaus erweitern kann, über Tricks? Aber was bringt mir ein Array von der Länge 0 oder 1?
Denn Sinn sehe ich einfach nicht. Dann lohnt sich gar kein Array oder?
Das mit der Definition [0..0] sagt dem Compiler wie die Struktur beschaffen ist, damit kann er zB. die Größe einer Dimension ausrechnen. Somit sind die alle nötigen Informationen für den COmpiler vorhanden. Damit greift auch ein 'SizeOf', damit kann man den richtigen Platz auch vom System anfordern. Für den richtigen Zugriff, Allokierung des Speichers, Freigabe desselben etc. ist hier ganz alleine der Programmierer verantwortlich. Die Bereichsprüfung muß aus diesem Grund auch deaktiviert sein, denn die kann ja mit [0..0] ja nicht wirklich was anfangen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

jus
Beiträge: 52
Registriert: Fr 6. Mai 2011, 13:29

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von jus »

martin_frb hat geschrieben: ...
Das sieht aus, wie eine Struktur die an das OS, der eine Library übergeben wird, und zwar via pointer?
Das heißt beim Aufruf setzt man " profileCount := 2", und die Einträge stehen im array?

Da das array ja inline seien muss, *und* dynamisch lässt sich das in Pascal nicht deklarieren.

Eine solche Struktur wird normalerweise mit Pointern und getmem verwendet.

type PNCMConcatProfileSet = ^NCMConcatProfileSet
var Foo: PNCMConcatProfileSet ;

Foo = GetMem( Sizeof(PNCMConcatProfileSet) + (ProfCnt-1)*SizeOf(NCMConcatProfileSpec) );

"-1" weil ja bereits platz fuer ein Eintrag da ist.

Compiliert OHNE range-checks kann man dann
Foo^.profileSpecs[x]

fuer x zwischen 0 und ProfCnt-1

Am ende FreeMem....
ja, ich muß zugeben, dass die meisten gefundenen C-Source den Speicher mit Getmem allokieren.
af0815 hat geschrieben:
pluto hat geschrieben:Möchtest du damit sagen, dass man ein Statischen Array durchaus erweitern kann, über Tricks? Aber was bringt mir ein Array von der Länge 0 oder 1?
Denn Sinn sehe ich einfach nicht. Dann lohnt sich gar kein Array oder?
Das mit der Definition [0..0] sagt dem Compiler wie die Struktur beschaffen ist, damit kann er zB. die Größe einer Dimension ausrechnen. Somit sind die alle nötigen Informationen für den COmpiler vorhanden. Damit greift auch ein 'SizeOf', damit kann man den richtigen Platz auch vom System anfordern. Für den richtigen Zugriff, Allokierung des Speichers, Freigabe desselben etc. ist hier ganz alleine der Programmierer verantwortlich. Die Bereichsprüfung muß aus diesem Grund auch deaktiviert sein, denn die kann ja mit [0..0] ja nicht wirklich was anfangen.
Die Antworten bestärken mich darin, dass Ich wohl weiterhin den Weg über die Eigenneudefinition des Records gehen werde. Ich möchte mich für eure zahlreichen Antworten bedanken.

Lg,
jus

martin_frb
Beiträge: 586
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von martin_frb »

pluto hat geschrieben:Möchtest du damit sagen, dass man ein Statischen Array durchaus erweitern kann, über Tricks? Aber was bringt mir ein Array von der Länge 0 oder 1?
Denn Sinn sehe ich einfach nicht. Dann lohnt sich gar kein Array oder?
Das array lohnt sich, weil ich dann per index auf die elemente zugreifen kann.
var Foo Array [0..0] ot TBar;
Foo[7]; // Durchaus erlaubt, WENN man dafuer gesorgt hat, das Memory korrekt vorhanden ist UND Range-Checks aus sind.

Natuerlich gefaehrlich....

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von pluto »

var Foo Array [0..0] ot TBar;
Foo[7]; // Durchaus erlaubt, WENN man dafuer gesorgt hat, das Memory korrekt vorhanden ist UND Range-Checks aus sind.
Interessant. Genau so ein Problem, hatte ich letzten: Ich wollte ein Statisches Array haben von einer Länge von 8, aber die Länge sollte Freiwählbar sein. Also habe ich ein Dynamisches Array genommen.
Wie würde das denn aussehen, so ein Array von 0 auf 7 zu setzten?
MFG
Michael Springwald

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6780
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von af0815 »

Betrachten wir das mal anders:
Du mußt mit einem anderen Prozess (nicht in Pascal geschrieben) kommunizieren und der liefert einen Speicherblock. In der API bzw. Doku ist beschrieben das der Speicherblock einen Header hat, in dem steht, wieviele Records einer bestimmten Zusammensetzung folgen.

Um das in Pascal abbilden zu können UND den Compiler auch die Möglichkeit zu geben dir zu helfen, muß du ihm eine Definition wie im Thrad zu Anfang beschrieben zur Verfügung stellen. Es ist klar, das das in Pascal vielleicht einfacher und sicherer lösen kannst. ABER nicht unbedingt so, das andere Sprachen das verwenden können.

Wenn du mit Betriebssystem API kommunizieren musst, so wird du oft auf solche Definitionen stossen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von pluto »

Ach so. Nun ist alles klar...
MFG
Michael Springwald

martin_frb
Beiträge: 586
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: array [0..0] in einem record auf array[0..1] ändern

Beitrag von martin_frb »

pluto hat geschrieben:
var Foo Array [0..0] ot TBar;
Foo[7]; // Durchaus erlaubt, WENN man dafuer gesorgt hat, das Memory korrekt vorhanden ist UND Range-Checks aus sind.
Interessant. Genau so ein Problem, hatte ich letzten: Ich wollte ein Statisches Array haben von einer Länge von 8, aber die Länge sollte Freiwählbar sein. Also habe ich ein Dynamisches Array genommen.
Wie würde das denn aussehen, so ein Array von 0 auf 7 zu setzten?
Wenn du genau hinsiehst ist die besprochene Struktur ja auch sowas wie ein dynamisches Array.

Du must das memory sogar noch selbst reservieren/freigeben. Und der Zzugriff finded auch (das ist Voraussetzung) ueber Pointer statt.

Nen dyn-Array ist auch ein pointer, nur versteckt.

Das einzige was hier anders ist, ist das dem array noch eine Struktur vorgestellt ist.

Antworten