# Pointer auf Array - Dereferenzierung



## ksc (20 Dezember 2011)

Hallo zusammen,

ich bin zur Zeit am Programmieren einer SPS mit TwinCAT in Strukturierter Text. Dabei bin ich auf ein Problem gestoßen:
Ich übergebe einem Funtionsblock eine Struktur die folgendermaßen aussieht:


```
TYPE user_struct :
STRUCT
    pWorkArray_ADR       : POINTER TO LREAL := 0;
    nWorkArray_SIZEOF   : UINT             := 0;
END_STRUCT
END_TYPE
```

Also ein Pointer auf ein Array vom Typ LREAL und die Größe des Array.

Nun möchte ich innerhalb des FB auf die einzelnen Elemente des durch den Poniter übergebenen Array's zugreifen.
Leider hab ich noch keine Möglichkeit den Pointer auf das Array korrekt zu dereferenzieren...

Ich habe schon folgendes probiert:


```
user_struct_var.pWorkArray_ADR^[i];
(user_struct_var.pWorkArray_ADR)^[i];
(user_struct_var.pWorkArray_ADR^)[i];
user_struct_var.pWorkArray_ADR[i]^;
user_struct_var.pWorkArray_ADR[i];
```

wobei i die Laufvariable von einer FOR-Schleife ist.

Leider kommt immer der Fehler: 4110: '[<index>]' ist nur für Arrayvariablen zulässig

In der Hilfe von TwinCAT oder Codesys bin ich leider nicht fündig geworden und auch das Internet
hat nicht weiterhelfen können...

Ich hoffe ihr könnt mir einen Hinweis geben.

Danke.


----------



## Thomas_v2.1 (20 Dezember 2011)

Wenn die Größe deines Array nicht konstant ist, wirst du nicht um Zeigerarithmetik herumkommen.

Ist die Arraygröße konstant, könntest du den Pointertyp direkt angeben, z.B,

```
pWorkArray_ADR       : POINTER TO ARRAY[0..9] OF LREAL
```

So wie du es jetzt hast kannst du nicht auf die Array-Elemente mittels Array-Index zugreifen, sondern das wäre dann nur mit Zeigerarithmetik möglich.

Dann müsstest du den Zeiger auf das erste Element des Arrays setzen, dann kannst du den Zeiger immer um ein Element erhöhen:

```
pWorkArray_ADR := pWorkArray_ADR + SIZEOF(pWorkArray_ADR^);
```


----------



## ksc (20 Dezember 2011)

Hallo Thomas_v2.1,

vielen Dank für die schnelle Antwort.
Das mit der Zeigerarithmetik hatte ich fast schon befürchtet.
Ich werde es nachher mal testen.


----------



## Thomas_v2.1 (20 Dezember 2011)

Hab grade den letzten Eintrag geändert, denn das geht so nicht.
Was aber geht (steht so auch in der Hilfe) ist, nicht den Zeiger zu verändern sondern erst eine Adresse vom Typ UDINT daraus zu machen und mit dieser den Offset zu berechnen.

Zusätzliche Variable anlegen und einen 'Arbeitszeiger' damit man den Zeiger auf den Index 0 nicht ändert:

```
uiAdrWorkArray : UDINT;
pWorkPtr : POINTER TO LREAL;
```

und dann 

```
i := 5;
uiAdrWorkArray := pWorkArray_ADR;
pWorkPtr := uiAdrWorkArray + i * SIZEOF(pWorkPtr^);

foo := pWorkPtr^;
```

Schön ist aber was anderes ;-)


----------



## StructuredTrash (20 Dezember 2011)

Thomas_v2.1 schrieb:


> Schön ist aber was anderes ;-)


Ja, nämlich so wie in Deinem ersten Vorschlag.

```
pWorkArray_ADR : POINTER TO ARRAY[0..MaxSize-1] OF LREAL;
```
Was spricht dagegen, das Array so gross wie maximal notwendig zu deklarieren? Aufpassen, dass man nicht jenseits der tatsächlichen Arraygrenzen zugreift, múss man doch sowieso selbst.


----------



## RobiHerb (20 Dezember 2011)

Immer beachten! Ich meine, die Sache mit der Pointer Arithmetik nicht in der IEC Norm geregelt, also letztendlich vom Hersteller des Compilers abhängig. 

Soweit ich weiss, ist in Codesys 2.x alle Arithmetik Byte basiert also nicht wie in C und verwandten Sprachen an den Datentyp des Objektes angepasst. 

Es ist also wildes Casten (Typumwandlung) und vorsichtiges Rechnen angesagt, es gibt keinen doppelten Boden bei Laufzeitfehlern und alles stürzt ab, wenn mann daneben greift.


----------

