# TwinCAT V2.11: Vergleichen von Strukturen



## Chräshe (9 August 2011)

Hallo Ihr, 

  bisher war ich der Meinung, dass der Umgang mit Strukturen bei TwinCAT recht einfach und unkompliziert ist. Kann ich doch Strukturen direkt in ein Array of STRUCT kopieren und umgekehrt…


```
VAR
  sRezept       : ARRAY[1..50] OF Rezeptur_01;  (* Rezept-Daten *)
  sAktRezept  : Rezeptur_01;  (* aktuelles Rezept *)
END_VAR
   
  sAktRezept := sRezept[11];
```
  Jetzt wollte ich prüfen, ob zwei Strukturen die gleichen Inhalte haben.

```
IF sRezept[11] = sRezept[12] THEN
…
```
Leider bekomme ich Übersetzungsfehler 4010 gemeldet. :icon_rolleyesUnverträgliche Typen: Kann '<Name>' nicht in '<Name>' konvertieren.)

  Mache ich was falsch, oder geht das tatsächlich nicht?!?
  Klar kann ich den Inhalt der Rezepte einzeln vergleichen. Es wäre aber schon schön, wenn das der Compiler machen würde… 

  Gruß
  Chräshe
   -----------------------------

  PS: Habe diesen Beitrag gefunden. Allerdings komme ich mit dem Befehl MEMCMP auch nicht weiter. 

```
Ungleich := MEMCMP(sRezept[11], sRezept[12], SIZEOF(sRezept[12]));
```
Nur wird jetzt der Fehler 4012 gemeldet (Unzulässiger Typ für Eingang '<Name>' von '<Name>' : Kann'<Name>' nicht in '<Name>' konvertieren.)


----------



## Chräshe (9 August 2011)

*Problem gelöst…*

Hallo Ihr,

  wer lesen kann ist klar im Vorteil: In der ersten Antwort war bereits die Lösung…
  … da muss man sich erst mal dran gewöhnen. 

  Gruß
  Chräshe


----------



## bits'bytes (9 August 2011)

Hi

```
Ungleich := MEMCMP(sRezept[11], sRezept[12], SIZEOF(sRezept[12]));
```
 
Also normalerweise würde das so geschrieben werden


```
Ungleich := MEMCMP([B]ADR[/B](sRezept[11]), [B]ADR[/B](sRezept[12]), SIZEOF(sRezept[12]));
```
 
hmm, gibts ja ADR() oder ? Das stammt jetzt von der B&R Welt 

dann sollte es jedenfalls gehen. Selber geschrieben geht natürlich auch, musst du aber damit rechnen dass die Funktion schon etwas länger braucht. Zumindest würde man anfangs mal DINT vergleichen (spart man sich schon einige Schleifen-Durchläufe) und dann bytes...


----------



## Chräshe (9 August 2011)

[FONT=Arial, sans-serif]Ja das ADR hatte ich übersehen, es darf nur die Anfangsadresse der Struktur der Funktion MEMCMP übergeben werden. Das ist auch alles korrekt dokumentiert – man muss eben nur lesen...[/FONT]

 [FONT=Arial, sans-serif]Zufrieden bin ich mit der Erkenntnis trotzdem nicht. Wenn folgender Code funktioniert wie ich erwarte,[/FONT]

[FONT=Arial, sans-serif]sAktRezept := sRezept[11];        (* Funktioniert *)[/FONT] 

 [FONT=Arial, sans-serif]was soll dann hier ein Problem darstellen?[/FONT]

[FONT=Arial, sans-serif]IF sRezept[11] = sRezept[12] THEN (* - geht nicht - *)[/FONT] 
[FONT=Arial, sans-serif]...[/FONT] 
 [FONT=Arial, sans-serif]Da würde doch jeder Anfänger zurechtkommen, weil es logisch und übersichtlich ist, was man hiervon eher nicht sagen kann:[/FONT]  [FONT=Arial, sans-serif]

Ungleich := MEMCMP(ADR(sRezept[11]), ADR(sRezept[12]), SIZEOF(sRezept[12]));[/FONT]   [FONT=Arial, sans-serif] (* Funktioniert *)[/FONT]

 → [FONT=Arial, sans-serif]4 Funktionen und eine Hilfsvariable....  :s8::s8::s8:
[/FONT]


----------



## bits'bytes (10 August 2011)

Chräshe schrieb:


> [FONT=Arial, sans-serif]sAktRezept := sRezept[11]; (* Funktioniert *)[/FONT]
> 
> [FONT=Arial, sans-serif]was soll dann hier ein Problem darstellen?[/FONT]
> 
> [FONT=Arial, sans-serif]IF sRezept[11] = sRezept[12] THEN (* - geht nicht - *)[/FONT]


 
ja, gebe ich dir recht...

aber



> Ungleich := MEMCMP(ADR(sRezept[11]), ADR(sRezept[12]), SIZEOF(sRezept[12])); [FONT=Arial, sans-serif](* Funktioniert *)[/FONT]
> 
> → [FONT=Arial, sans-serif]4 Funktionen und eine Hilfsvariable.... :s8::s8::s8:[/FONT]


 
stimmt so nicht ganz:


```
[COLOR=#ff00ff]if ([COLOR=#0000ff]MEMCMP[/COLOR][COLOR=#ff00ff]([/COLOR][COLOR=#0000ff]ADR[/COLOR][COLOR=#ff00ff](sRezept[11]), [/COLOR][COLOR=#0000ff]ADR[/COLOR][COLOR=#ff00ff](sRezept[12]), [/COLOR][COLOR=#0000ff]SIZEOF[/COLOR][COLOR=#ff00ff](sRezept[12])) <> 0) then[/COLOR][/COLOR]
[COLOR=#ff00ff]... (ungleich)[/COLOR]
[COLOR=#ff00ff]else[/COLOR]
[COLOR=#ff00ff]... (gleich)[/COLOR]
[COLOR=#ff00ff]endif[/COLOR]
```
 
keine Hilfsvariable, ADR ist keine Funktion sondern wird vom Compiler übersetzt genauso wie sizeof() keine Laufzeitfunktion ist sondern Compiler Angelegenheit. D.h. zur Laufzeit hast du 2 Adressen und 1 Größe für Speichervergleich....

(wieder: ich denke dass das bei dir auch so funktionieren wird, das hier entspricht B&R Code)

bg
bb


----------



## soma (10 August 2011)

> ADR ist keine Funktion sondern wird vom Compiler übersetzt genauso wie  sizeof() keine Laufzeitfunktion ist sondern Compiler Angelegenheit. D.h.  zur Laufzeit hast du 2 Adressen und 1 Größe für Speichervergleich....



unter vom Compiler übersetzt verstehe ich das der Compiler den Ausdruck mit einem Wert ersetzt. Dem ist jedoch nicht so.
sizeof und adr sind für mich ganz klar Funktionen. Dort wird nichts ersetzt sondern zur laufzeit berechnet.


----------



## bits'bytes (10 August 2011)

soma schrieb:


> .. Dem ist jedoch nicht so.
> sizeof und adr sind für mich ganz klar Funktionen. Dort wird nichts ersetzt sondern zur laufzeit berechnet.


 
Würde ich mal nein sagen, siehe z.B.

http://de.w3support.net/index.php?db=so&id=671790


und ADR() ist sowieso nur das Gegenstück zu ANSI-C "&" -> Address-Funktion
...


----------



## soma (10 August 2011)

ADR
Wenn ich mir eine Funktion schreibe die als Parameter einen Pointer hat,
dann kann ich innerhalb der Funktion adr auf den Pointer aufrufen.
Da  der Compiler nicht weiß womit ich die Funktion aufrufe, kann er die Adresse nicht zum Compilierzeitpunkt berechnen.
De facto muss das Programm jedoch für jede Variable die Speicheradresse wissen, somit stelle ich mir vor, dass adr als Funktion sich dieses Tables bedient, jedoch nicht mit einem Wert ersetzt wird.

SIZEOF
Bei SizeOf bin ich mir mittlerweile nicht mehr sicher. Natürlich greift hier ebenfalls die oben aufgeführte Annahme, jedoch muss ich den Datentyp auf  den der Pointer zeigt angeben. somit kann die Größe ersetzt werden da sie sich nicht verändern kann.​


----------



## bits'bytes (10 August 2011)

soma schrieb:


> ADR​
> 
> 
> 
> ...


 
Hi,

also ich versuch mir das einfach so wie bei einem C-Programm vorzustellen und ich glaube dass ich damit nicht so falsch liege. Es ist doch so dass bei ADR(Var_X) der Compiler weiß wo die Var_X im Variablenspeicher liegt. Und das wird eingetragen. 

Wenn das immer zur Laufzeit bestimmt werden würde, das wäre ja ein Wahnsinn an Resourcen-Verschwendung. 

Wenn du in deinem Projekt Variablen dazufügst, wird ja immer der entsprechende Programmteil compiliert (lokal oder global, je nachdem). Das wäre ja dann gar nicht notwendig wenn zur Laufzeit das alles gemacht würde. z.B. du erweiterst eine globale Variable in Form eines Array von Var_X[5] --> Var_X[6]. Es wird das gesamte Projekt kompiliert, da sich das Datenabbild geändert hat und unter Anderem die ADR() Parameter neu bestimmt werden müssen...


... der compiler nicht weiß ....

Der Compiler weiß natürlich genau mit was du die Funktion aufrufst.

Die Zielfunktion weiß nicht woher die Adresse kommt, aber das liegt im Verantwortungsbereich des Programmierers hier die richtigen Parameter zu verwenden

z.B. 
memcpy(ADR(x1), .....)


compiler weiß dass x1 verwendet wird.


int memcpy(unsigned char * pCH1, .... )

den compiler interessiert nicht woher pCH1 kommt, der Programmierer ist verantwortlich dass das zusammenpasst (die Datentypen))


----------

