TwinCAT V2.11: Vergleichen von Strukturen

Chräshe

Level-2
Beiträge
873
Reaktionspunkte
274
Zuviel Werbung?
-> Hier kostenlos registrieren
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…

Code:
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.
Code:
IF sRezept[11] = sRezept[12] THEN
…
Leider bekomme ich Übersetzungsfehler 4010 gemeldet. :icon_rolleyes:(Unverträ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… :rolleyes:

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

PS: Habe diesen Beitrag gefunden. Allerdings komme ich mit dem Befehl MEMCMP auch nicht weiter.
Code:
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.) :cry:
 
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. :rolleyes:

Gruß
Chräshe
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi
Code:
Ungleich := MEMCMP(sRezept[11], sRezept[12], SIZEOF(sRezept[12]));

Also normalerweise würde das so geschrieben werden

Code:
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...
 
[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]
 
[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:

Code:
[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
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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.
 
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.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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.​

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))
 
Zuletzt bearbeitet:
Zurück
Oben