Funktion Count/Len/Length um Anzahl der Elemente in einem Array auszulesen

Daimonion

Level-1
Beiträge
79
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo

Ich bin gerade dabei ein Projekt im TwinCat zu programmieren und wollte dabei, wie in Hochsprachen üblich, die Größe eines Arrays ermitteln. Leider kann ich keine Funktion (Count/len/Length (Array() ) finden die mir das übernimmt. Gibt es da so eine Funktion?

Dank im Voraus für die Antworten.

Grüße
Daimonion
 
Hallo,

hatte auch mal so eine Idee, ist aber nicht. (Antwort ist nicht von Beckhoff geprüft). :TOOL:

Wenn es geht, dann bitte auch die Funktion zum setzen der Feldgröße im Quelltext wie z.B. SetLength(Variable, neue Größe).

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
SIZEOF(myVar) liefern die Datengröße des Arrays. Das geteilt durch die Größe eines einzelnen Array-Elements liefert die Anzahl der Elemente:
(reine Mathematik) ;-)

Code:
VAR
    myArr : ARRAY [1..4] OF INT;
    size: INT;
    ElementCount: INT;
END_VAR
----------------------
size:= SIZEOF(myArr);

ElementCount := size/ SIZEOF(myArr[1]);
Array-Größe dynamisch zur Laufzeit ändern geht nicht. Ist glaube ich per se bei SPSen nicht möglich (Norm)?
 
Nun einmal Sorry, für den dummen Kommentar.

Warum sollte ein Programmierer eine Feldgröße abfragen können, wenn sie nicht verändert werden kann. Das heißt, sie wurde vom Programmierer definiert, also bekannt. Was für ein Blödsinn des Systems. :confused:

Gruß
 
Hi,

wenn z.B. 2 Maschinen mit Unterschiedlichen Optionen compiliert werden, könnte das Array myArr einmal 10, das andere mal 20 Elemente enthalten.

wenn du diese Möglichkeit hast, dann braucht man es meiner Meinung nach nicht.
Code:
#define MAX_ARR 10            ; Typ-1
oder
#define MAX_ARR 20            ; Typ-2
myArr = INT[0...MAX_ARR];
 
...
loop index = 0 to MAX_ARR - 1 do
   myArr[index] .....
endloop

wenn du aber so deklarieren musst

Code:
myArr = INT[10];              // Typ=1
oder
myArr = INT[20];              // Typ=2
 
...
loop index = 0 to ELEMENT-COUNT do
   myArr[index] .....
endloop

Dann macht das Sinn. Sonst musst du halt x-mal Code-Änderungen machen, mit beiden Methoden gehts sonst 'automatisch'

bg
bb
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja, das sehe ich.

Aber trotzdem sollte der Programmierer wissen was er tut.

Nun, dann wäre halt der Wunsch das Feld selbst zu definieren.

Gruß
 
Aber trotzdem sollte der Programmierer wissen was er tut.

Ja eh, hoffentlich :D

die Frage ist mit welchem Aufwand du das schaffst,

Ändere ich einmal 10 --> 20

oder

muss ich 17 mal im Code alles nachbessern nur weil die Arraygröße fix eingetragen wurde....

bg
bb
 
@bits, haste vollkommen Recht.

Also, wäre die Lösung man kann die Feldgröße verändern, nach den Bedürnissen. Ist üblich bei vielen anderen Sprachen. Wurde das hier vergessen ? :TOOL:

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

hatte auch mal so eine Idee, ist aber nicht. (Antwort ist nicht von Beckhoff geprüft). :TOOL:

Wenn es geht, dann bitte auch die Funktion zum setzen der Feldgröße im Quelltext wie z.B. SetLength(Variable, neue Größe).

Gruß

Dynamische Speicherverwaltung ist in der IEC Norm nicht vorgesehen.
In TwinCAT 3 wird sie aber in Grenzen zur Verfügung stehen.
Beim Steuerungshochauf kann dann einmal die Größe eines Arrays festgelegt werden.

Damit heist es mal wieder warten oder drauf verzichten.

Gruß

dummy
 
@dummy, Danke für diese Antwort.

Du hast mir bestätigt, es macht Sinn. Also weiter warten auf TwinCAT3.

Gruß
 
Hi,
also dynamisch anpassen (interpretiere ich so: während der Laufzeit des Systems, da ist auch der Hochlauf mit dabei) finde ich nicht notwendig.

Meine Beispiele oben gehen davon aus dass das Projekt noch mal durch den Compiler geht. Während der Laufzeit ist die Größe dann fix.

Wenn während der Laufzeit unterschiedliche Größen zu behandeln sind, muss dass meiner Meinung nach über Pointer und Memory-Alloc realisiert werden.

Ich keine eigentlich überhaupt keine Funktion welche Strukturen, also UDTs ändern kann, auch nicht außerhalb von SPS Programmierung. Gäbe es so was ?

bg
bb

ah ja, wollte noch sagen bei B&R funktioniert das bereits so ....
Code:
#define MAX_ARR 10            ; Typ-1  
myArr = INT[0...MAX_ARR];   

...

 loop index = 0 to MAX_ARR - 1 do   
 myArr[index] .....

 endloop
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn die Arraygröße variiert, dann sollte man für die Arraydefinition Konstanten vorsehen. Vielleicht ist das eine kleine Abhilfe.

Code:
VAR CONSTANT
    MaxArr: INT:= 10;
END_VAR

VAR
    myArr: ARRAY[0..MaxArr] OF INT;
END_VAR
Die Konstante lässt sich im Normalfall sogar per ADS auslesen (wenn die Übersetzungsoption "Konstanten ersetzen" nicht aktiviert ist), damit sich z.B. eine Visualisierung an die Arraygröße automatisch anpassen kann.

Gruß,
witkatz
 
Wenn die Arraygröße variiert, dann sollte man für die Arraydefinition Konstanten vorsehen. Vielleicht ist das eine kleine Abhilfe.

Code:
VAR CONSTANT
    MaxArr: INT:= 10;
END_VAR

VAR
    myArr: ARRAY[0..MaxArr] OF INT;
END_VAR
Die Konstante lässt sich im Normalfall sogar per ADS auslesen (wenn die Übersetzungsoption "Konstanten ersetzen" nicht aktiviert ist), damit sich z.B. eine Visualisierung an die Arraygröße automatisch anpassen kann.

Viel Spaß dabei dir deinen Speicher der SPS zu zerschießen.
Du kannst ja mal nach dem myArr eine INT Variable anlegen und dann ein MaxArr auf 11 erhöhen und einen Wert reinschreiben. Was meinst du welcher Wert in der folgenden Variable landet?

Das Programm wird kompiliert und nicht interpretiert! Falls dir das etwas sagen sollte...
 
Ich hab's schon so oft angewendet und auf diese Weise ohne Probleme online Änderungen durchgeführt, dass ich dir nicht glauben kann. Wenn du den Wert von MaxArr änderst, dann wird auch die Arraygröße angepasst und neu compiliert. Das passt schon. Das ist das gleiche wie eine Änderung der Definition der Arrayvariablen, nur eben mit einer benannten Konstanten statt eines Literals für die Arraygrenzen.

Natürlich darf man nicht außerhalb der Array-Grenzen schreiben. Das lässt sich zwar mit checkbounds abfangen, checkbounds frisst aber Ressourcen.

Gruß,
witkatz
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab's schon so oft angewendet und auf diese Weise ohne Probleme online Änderungen durchgeführt, dass ich dir nicht glauben kann. Wenn du den Wert von MaxArr änderst, dann wird auch die Arraygröße angepasst und neu compiliert. Das passt schon. Das ist das gleiche wie eine Änderung der Definition der Arrayvariablen, nur eben mit einer benannten Konstanten statt eines Literals für die Arraygrenzen.
Aber garantiert nicht wenn du wie du oben geschrieben hast über ADS den Wert von MaxArr anpasst!

Über TwinCat kann man den Wert wenn man online ist über 'Wert schreiben' ebenfalls ändern.
Ich würde vermuten dass die unter VAR CONSTANT abgelegten Variablen zwar als Variable angelegt werden, z.B. damit sie von anderen Programmteilen oder auch Visualisierungen als Wert abgefragt werden können, aber die Speicheradressen in der üblichen Manier beim Übersetzungsprozess eindeutig festgelegt werden.

Vom Programm aus sind die Variablen aus dem Bereivch 'VAR CONSTANT' auch nur lesefähig.
 
"VAR_CONSTANT" sind Konstanten und können während des Programmablaufs nicht verändert werden. Der Wert muss vor dem kompilieren feststehen.
Also ist gegen witzkatz's Methode nichts einzuwenden. Mache ich auch oft, z. B. wenn man eine Applikation mit unterschiedlicher Anzahl von identischen Module programmiert.
Dann lege ich ein Array von diesen Modulen an, wobei es je nach Anwendung mal 5 sind und mal 10 oder sonst was. Man braucht nur an der einen Stelle der Konstantendeklaration im Code die Zahl anpassen.
 
Also wenn man die Array-Grösse ändert, MUSS immer neu kompiliert werden, das geht zur Laufzeit sicher nicht. Die Grösse muss als VAR_CONSTANT deklariert sein...

Ich mache oft 2 Variablen, eine die max. Grösse, die erlaubt ist (damit instanziere ich das Array) und eine Anzahl Werte (Also wieviel ich vom Instanzierten Array verwende)

Dies ist zwar Speicherfressend, aber man kann zur Laufzeit die nutzbare Array-Grösse anpassen...

P.S. Aus Erfahrung auch nie Online-Changes nach dem Ändern der Arraygrösse machen, das kann ein wunderbares Durcheinander im Speicher verursachen :D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
So, ich meld mich dann auch mal wieder. War am WE unterwegs und konnte die Arbeit mal Arbeit sein lassen.

Vielen Dank für die rege Diskussion und auch vielen Dank an Trinittaucher dessen Lösung mir sehr gut gefällt. Ich werde mal schauen ob ich in dem Stress auf Arbeit mir eine Funktion schreiben kann, die das relativ Komfortabel löst.

Wenn man das Array mit Konstanten instanziiert ist es ja auch klar, dass man diese nicht zur Laufzeit ändern sollte. Nur recht neue Hochsprachen lassen wirkliche dynamische Arrays zu. Unter C, C++ ist da nix mit Dynamik ohne irgendwelche Zusätze. von daher ist das schon okay so wie Beckhoff das implementiert hat.
 
Hallo,

moderne Hochsprachen ?

Bei Delphi, geht das schon ganz lange, heisst min. 10 Jahre (und weiter, will gerade mal nicht zurückdenken). Und da C++, das A und das O ist bestimmt auch.

Gruß Voxe
 
Aber garantiert nicht wenn du wie du oben geschrieben hast über ADS den Wert von MaxArr anpasst!
Das ist eine böse Unterstellung. Ich habe deutlich geschrieben, dass man die Konstante per ADS auslesen kann, damit sich z.B. eine Visu-Applikation an das SPS Projekt zur Laufzeit anpassen kann.
Für eine Änderung der Konstanten ändert man den Quelltext, dokumentiert die Änderung und beim Einloggen in das laufende System per online change wird das Projekt recompiliert. Auf die Idee, auf Konstanten per ADS schreibend zuzugreifen wäre ich nie gekommen. Wer macht denn so was, das ist grob fahrlässig!

Gruß,
witkatz
 
Zuletzt bearbeitet:
Zurück
Oben