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



## Daimonion (8 Juli 2011)

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


----------



## Voxe (8 Juli 2011)

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ß


----------



## trinitaucher (8 Juli 2011)

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) ;-)


```
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)?


----------



## Voxe (8 Juli 2011)

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. 

Gruß


----------



## bits'bytes (8 Juli 2011)

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.

```
#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


```
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


----------



## Voxe (8 Juli 2011)

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ß


----------



## bits'bytes (8 Juli 2011)

> Aber trotzdem sollte der Programmierer wissen was er tut.


 
Ja eh, hoffentlich 

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


----------



## Voxe (8 Juli 2011)

@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ß


----------



## Dummy (8 Juli 2011)

Voxe schrieb:


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



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


----------



## Voxe (8 Juli 2011)

@dummy, Danke für diese Antwort.

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

Gruß


----------



## bits'bytes (8 Juli 2011)

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 ....

```
#define MAX_ARR 10            ; Typ-1  
myArr = INT[0...MAX_ARR];   

...

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

 endloop
```


----------



## witkatz (9 Juli 2011)

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


```
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


----------



## Thomas_v2.1 (9 Juli 2011)

witkatz schrieb:


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



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...


----------



## witkatz (9 Juli 2011)

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


----------



## Thomas_v2.1 (9 Juli 2011)

witkatz schrieb:


> 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.


----------



## trinitaucher (9 Juli 2011)

"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.


----------



## gloeru (9 Juli 2011)

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


----------



## Daimonion (11 Juli 2011)

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.


----------



## Voxe (12 Juli 2011)

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


----------



## witkatz (20 Juli 2011)

Thomas_v2.1 schrieb:


> 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


----------



## Thomas_v2.1 (20 Juli 2011)

witkatz schrieb:


> 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!



Hi,
ja Entschuldigung, ich hatte das völlig mißverstanden und gedacht du wolltest per ADS die Konstante überschreiben und darauf hoffen dass das Array größer wird.


----------



## Ottmar (26 November 2012)

Hi!

Gibt es jetzt hier eigentlich außer gezicke auch eine Antwort auf die Frage?
Gibt es einen Befehl (S7-1200) mit der man auslesen kann wieviele Array-Elemente ein Array hat?

Danke,


gruß,

Ottmar


----------



## Daimonion (26 November 2012)

Was hat die S7-1200 mit CodeSys zu tun? Ansonsten steht die Antwort im 3. Post.


----------

