# Struct vergleich mit pointer und sizeof



## hago10 (30 Januar 2011)

Hallo!
  Erst mal vielen Dank an alle die sich meinem Problem widmen.
  Ich möchte zwei Strukturen auf deren Aufbau miteinander vergleichen. 

  Fall 1 Beispiel:
  [FONT=&quot]TYPE tstruct1 :[/FONT]
  [FONT=&quot]STRUCT[/FONT]
  [FONT=&quot]     test1 : BOOL;[/FONT]
  [FONT=&quot]     test2 : REAL;[/FONT]
  [FONT=&quot]     test3 : BOOL;[/FONT]
  [FONT=&quot]END_STRUCT[/FONT]
  [FONT=&quot]END_TYPE[/FONT]
  [FONT=&quot] [/FONT]
  [FONT=&quot]TYPE tstruct2 :[/FONT]
  [FONT=&quot]STRUCT[/FONT]
  [FONT=&quot]     test1 : BOOL;[/FONT]
  [FONT=&quot]     test2 : REAL;[/FONT]
  [FONT=&quot]     test3 : BOOL;[/FONT]
  [FONT=&quot]END_STRUCT[/FONT]
  [FONT=&quot]END_TYPE[/FONT]

  In diesem Fall sind beide Strukturen gleich. 

  Fall2 Beispiel:

  [FONT=&quot]TYPE tstruct2 :[/FONT]
  [FONT=&quot]STRUCT[/FONT]
  [FONT=&quot]     test1 : INT;[/FONT]
  [FONT=&quot]     test2 : REAL;[/FONT]
  [FONT=&quot]     test3 : BOOL;[/FONT]
  [FONT=&quot]END_STRUCT[/FONT]
  [FONT=&quot]END_TYPE[/FONT]

  In diesem Fall sind die Strukturen unterschiedlich und es soll eine Fehlermeldung ausgegeben werden.

  Mein erster Ansatz schaut folgendermaßen aus: Ich speichere die Größe der verwendeten Datentypen des Strukts  in einem Array und vergleich diese miteinander:

  [FONT=&quot]VAR[/FONT]
  [FONT=&quot]p : POINTER TO INT;[/FONT]
  [FONT=&quot]counter: INT;[/FONT]
  [FONT=&quot]array: ARRAY [0..10] OF INT;[/FONT]
  [FONT=&quot]i: INT;[/FONT]
  [FONT=&quot]END_VAR[/FONT]
[FONT=&quot]
[/FONT]
  [FONT=&quot]     [/FONT]
  [FONT=&quot]          WHILE (counter<=SIZEOF(struct_name)) DO[/FONT]
  [FONT=&quot]                counter:=counter+SIZEOF(p^);[/FONT]
  [FONT=&quot]                array_:=SIZEOF(p^);[/FONT]
  [FONT=&quot]                p:=p+SIZEOF(p^);[/FONT]
  [FONT=&quot]                [/FONT][FONT=&quot]i:=i+1;[/FONT]
  [FONT=&quot]          END_WHILE[/FONT]

  Nur leider funktioniert dieser Ansatz nicht, da [FONT=&quot]SIZEOF(p^)[/FONT]immer =2 ist, egal auf welchen Datentyp er zeigt.  
  Es würde mich freuen wenn jemand den Fehler in meiner Lösung sieht od. wenn er einen anderen Ansatz kennt wie man das Problem besser lösen könnte.
Vielen Dank und LG_


----------



## bits'bytes (31 Januar 2011)

Hallo,
wenn ich davon ausgehe dass die Elemente also immer 
test1
test2
test3 heissen, dann könntest du verschiedene Prüfungen machen um die Gleichheit der Strukturen zu überprüfen.

1) sizeof (struct_name), liefert in diesem Falls schon mal unterschiedliche Ergebnisse. Es könnte allerdings auch öfters gleiches Ergebnis bringen obwohl die Strukturen unterschiedlich sind (also gleiche Größe aber andere Datentypen oder anders angeordnet).

2) als weitere prüfung könntest du eine Reihe von Rechenoperationen durchführen, mit jedem Element der Struktur.

2.1 Definiere eine Variable von Type Sturktur-1 oder Struktur-2 und weise den Elementen einen Wert zu, 
test1 = 1
test2 = 2
test3 = 3

2.2 Mach einen Pointer von Struktur-1 auf diese Variable (von 2.1) und rechne
z.b
temp = test1 + test2
temp = temp + test3 

2.3 Mach einen Pointer von Sturktur-2 auf diese Variable (von 2.1) und rechne dasselbe wie 2.2

Wenn die Datentypen unterschiedlich sind kommt bei temp von 2.2 ein anderes ergebnis raus als von 2.3.

bg
bb


----------



## hago10 (31 Januar 2011)

Hallo und vielen Dank für die Vorschläge!
  Leider kann ich nicht davon ausgehen dass die Variablen gleich benannt sind. 
  Da die Structs in zwei unterschiedlichen Tasks verwendetet werden und bis zu 200 Variablen beinhalten, kann ich leider auch nicht deine vorgeschlagenen Berechnungen anwenden.  
  Mein Ziel ist es zu erkennen ob jemand Veränderungen an einem der beiden Structs vornimmt wodurch eine Datenintegrität am Global Memory nicht mehr gegeben wäre.
  Die erste Absicherung ist es einfach die Größen der beiden Structs (unterschiedliche Tasks) mit Sizeof zu vergleichen. 
  Da ich damit aber nicht sicherstellen kann, dass Speicherverschiebungen (Austausch, Hinzufügen usw. von Datentypen) im Struct vorhandene sind möchte ich ein Array mit der Abfolge der verwendeten Datentypen erstellen, dieses CRC codieren und anschließend von beiden Tasks die berechnet CRC miteinander vergleichen.
  [FONT=&quot]Ich würd mich über jeder weitere Idee von dir freuen![/FONT]


----------



## argv_user (31 Januar 2011)

Die Abfolge der Datentypen kannst Du eigentlich nur vom Compiler erfahren.
OK , den Linker nehm ich noch dazu.


----------



## hago10 (31 Januar 2011)

Naja es ist ja nicht zwingend notwendig den genauen Datentypen zu erkennen. Mir würd der reservierten Speicher für die Variable im Struct reichen.

  Wie bereits im Start Posting geschrieben möchte ich mit:
  p:=ADR(variable_name);
  size:=SIZEOF(p^);
  die Speichergröße des Datentyps von variable_name ermitteln.


Was genau liefert SIZEOF(p^)?


----------



## Werner29 (31 Januar 2011)

Hallo,

SIZEOF(p^) liefert die grösse des Datentyps auf den p zeigt, also bei dir ist p ein Pointer to int und liefert immer SIZEOF(INT) = 2. Der Wert ist also konstant und hat nichts damit zu tun, was du dem Pointer zur Laufzeit zuweist.

Dazu bräuchte man sowas wie Runtime Type Information in C++ und die gibts nicht in CoDeSys. 
Du kannst höchstens für eine spezielle, bekannte Struktur eine Funktion schreiben, um ein paar Eigenschaften zu speichern, beispielsweise die Gesamtgrösse der Struktur und die Offsets der Komponenten in der Struktur:
wenn du eine Variable vom Typ der Struktur hast, dann kannst du mit SIZEOF die Gesamtgrösse abfragen (das tust du ja schon).
Mit ADR(struct_1.compox) - ADR(struct_1) kannst du den Offset der Komponente compox in der Struktur erfragen. (Das geht auch über Pointer: pstruct_1^.compox aber natürlich brauchst du einen Pointer auf die richtige Struktur).
Sollte dann jemand irgendwo in der Struktur ein neues Element einfügen, dann ändert sich der Offset der alten Elemente. Auch durch das Vertauschen von Elementen ändern sich deren Offsets.
Wenn jemand ein Element löscht, dann erhältst du schon einen Übersetzungsfehler. So eine Funktion musst du aber für jede Struktur neu schreiben.

Bernhard


----------



## StructuredTrash (31 Januar 2011)

SizeOf(p^) liefert die Grösse des Datentyps, auf den der Zeiger laut Deklaration zeigt. In Deinem Fall (Pointer to INT) also immer 2.


----------



## hago10 (31 Januar 2011)

Nochmals Danke für alle Antworten. 
Der Vorschlag mit der Offset Berechnung triffts genau auf den Punkt.

Nur sollte dies dynamisch funktionieren.
 Wenn es wie Werner beschrieben hat, keine Möglichkeit gibt zur Laufzeit festzustellen auf welchen Datentyp ein Pointer zeigt, ist es daher auch nicht realisierbar?


----------



## BerndAllgäu (31 Januar 2011)

Was für ein Zielsystem verwendest du? (Beckhoff?)

Gruß Bernd


----------



## hago10 (31 Januar 2011)

Hallo Bernd,

ja das Zielsystem ist eine Beckoff PLC.

LG


----------



## BerndAllgäu (31 Januar 2011)

Dann kannst du ja über die ads-funktionen die struktur auslesen... ist zwar ein "umweg" aber funktioniert...

Gruß Bernd


----------



## Werner29 (31 Januar 2011)

hago10 schrieb:


> Wenn es wie Werner beschrieben hat, keine Möglichkeit gibt zur Laufzeit festzustellen auf welchen Datentyp ein Pointer zeigt, ist es daher auch nicht realisierbar?


Ich wüsste nicht wie, und ich habe den Compiler geschrieben...
Die Konsistenz der Daten musst du irgendwie anders sicherstellen.


----------



## BerndAllgäu (31 Januar 2011)

Stimmt hast recht... war ein "unfertiger" Gedanke meinerseits...

dachte man könnte mit dem FB "PLC_ReadSymInfoByName" (PLC Lib : Utilities) über  den Symbolnamen lokal überprüfen ob es sich wenigstens um den gleichen strukturnamen handelt... aber da müßte man wieder die variablennamen mit pflegen...

Mich würde interessieren wofür man genau diese Anforderung braucht... vlt. gibts ja einen ganz anderen Lösungsansatz für das problemchen...

Gruß Bernd


----------



## Werner29 (31 Januar 2011)

Hi Bernd,

Ich hatte deinen Beitrag überlesen, aber so ganz falsch ist dein Gedanke nicht. Die Symbolinformation ist ja sowas wie Runtime Type information, aber da müsste ich mich selber erstmal schlau machen, was man darüber alles rausbekommt. 
Rein mit den Mitteln der Programmiersprache geht es jedenfalls nicht.

Bernhard, auch Allgäu...


----------



## BerndAllgäu (31 Januar 2011)

Werner29 schrieb:


> Hi Bernd,
> 
> Ich hatte deinen Beitrag überlesen, aber so ganz falsch ist dein Gedanke nicht. Die Symbolinformation ist ja sowas wie Runtime Type information, aber da müsste ich mich selber erstmal schlau machen, was man darüber alles rausbekommt.
> Rein mit den Mitteln der Programmiersprache geht es jedenfalls nicht.
> ...



Wir Allgäuer müssen es wieder richten... lol

in der .Net DLL hat man da mehr funktionen - da hat man die möglichkeit eine ganze struktur aufzudröseln (mit viel schreibarbeit)

aber die Bausteine von der Lib sind da etwas eingeschränkter soweit ich weiß... evtl hock ich mal heut aben hin und schau mal was geht...


Gruß Bernd


----------



## hago10 (31 Januar 2011)

Hey nochmals Danke an euch beide! Freut mich dass dieses Thema auf so großes Interesse stößt.
  @Bernd: Wofür ich diese Anforderung brauche: Wie bereits erwähnt habe ich zwei Tasks auf der PLC laufen, welche beide die gleiche Struktur am Globalen Memory  instanziieren (wird so benötigt). Sollte bei einem Task jemand die Struktur ändern, kommt es natürlich zu einer Dateninkonsistenz. Um diese zu erkennen möchte ich eine „Fußabdruck“ der verwendeten Struktur von jedem Task individuell erstellen und in Folge miteinander vergleichen.
Hoff mal es ist halbwegs verständlich ;-)

  LG


----------



## BerndAllgäu (31 Januar 2011)

Dann erkär koch einen Task als "master" der über die ADS Funktion die ich beschrieben habe die strukturdaten vom anderen Task holt (muß irgendwo deklariert sein)

wenn du dann den namen und die größe vergleichst kann doch kaum noch was schief gehen... zumindest keine schreibversuche über die strukturgrenzen hinaus... 

Gruß Bernd


----------



## bits'bytes (31 Januar 2011)

Hallo nochmals,
ich habe  noch nicht auf Beckhoff programmiert. Aber ich werde dir mal kurz schreiben wie ich es bei B&R machen würde, vielleicht gibts ja bei Beckhoff ganz ähnliche Funktionen....

1) Über die PV-Library kann man die einzelnen Strukturelemente aus dem System auslesen und anschließend den Datentyp bestimmen. Das würde ganz genau zur gestellten Anforderung passen. 

2) Es gibt eine Library ("CSV_xxx") mit welcher Variablen (auch ganze Strukturen) in eine CSV Datei geschrieben werden. Falls Beckhoff sowas hat, kannst du dir 2 Dateien erzeugen und diese dann quasi Zeile für Zeile vergleichen ob Name, Datentyp übereinstimmt. Bei B&R ist dass Format nämlich so
----
Struktur1.test1;BOOL;1.0
Struktur1.test2;UINT;33.0
usw.
...
----
Vielleicht hat ja Beckhoff ähnliche Funktionen und somit könntest du das Problem einfach lösen...

bg
bb


----------

