SIZEOF struct

selucky
2020-03-23
2020-03-25
  • selucky - 2020-03-23

    Guten Morgen zusammen,
    ich schreibe grad eine "Kommunikationsschnittstelle" zwischen einer Codesys 3.5 Steuerung und einem C# Programm.
    Die Steuerung und das C# Programm sollen einfach Daten über das Netzwerk austauschen können. Soweit klappt das auch alles.

    Die Daten, die Codesys sendet, sind in einer Struktur verpackt. Über SIZEOF weiß ich dann auch, wie groß die Message sein muss.

    Wenn ich meine Struktur zusammen bastel, wundert mich die Größenänderung bei SIZEOF etwas.
    Ein INT z.B. ist ja nur 2 Byte groß.
    Füge ich eine neue INT Variable in der Struktur ein, dann ändert sich die Größe durch SIZEOF um 2 aber auch mal um 4 Bytes.
    Gibt es da irgendeine Logik?

    In C# erstelle ich dann eine Liste mit Items, wo die Berechunungen der Position automatisch geschehen soll.

    Viele Grüße
    Sebastian

     
  • Thomas - 2020-03-23

    Moin Sebastian,
    wo genau fügst Du dein "Int" ein und wie sieht deine Struktur aus? Beim Raspi (ARM-Prozessor) muss ein REAL immer auf einer Adresse liegen, die durch 4 teilbar ist. Da könnte ich mir schon vorstellen, dass "Füllbytes" eingefügt werden.

    Du kannst dieses Verhalten mit dem Attribut "pack_mode" beeinflussen. Aber, sei vorsichtigt, eine Zugriff auf eine falsch "allignete" Adresse kann auch schnell mal zur Exception führen.

    https://help.codesys.com/webapp/_cds_pragma_attribute_pack_mode;product=codesys;version=3.5.15.0

    Gruß Thomas

     
  • selucky - 2020-03-23

    Hi,
    die Strukturen habe ich mal angefügt.

    Aufgefallen ist mir das beim Einfügen des Elements StellzeitWeg

    Konstanten sind
    ANZAHL_ZIEL_FOERDERWEG = 8
    ANZAHL_ZIEL_STELLORGANE = 16

    TYPE structZiel :
    STRUCT
        Nummer                  : INT;
        Mischer                 : INT;  (* 1 - 4 *)
        Puffer1                 : INT;
        Puffer2                 : INT;
        Puffer3                 : INT;
        Puffer4                 : INT;
        PufferMaxLaufzeit       : INT;  (* Minuten *)
        Nachlaufzeit            : INT;  (* sek *)
        Alarmzeit               : INT;  (* sek *)
        Alarmgewicht            : REAL; (* kg *)
        Mischermodus            : eMischermodusZiel;
        GewichtEinAb            : REAL; (* kg *)
        IntervallEin            : INT;  (* sek *)
        IntervallAus            : INT;  (* sek *)
        Schrotgeblaese          : INT;  (* 0 = aus, 1 - 4 *)
        Menge_Fest              : INT;  (* % *)
        Menge_Maximal           : INT;  (* % *)
        Menge_Optimal           : INT;  (* % *)
    
        Foerderweg              : ARRAY[1..ANZAHL_ZIEL_FOERDERWEG] OF structZielWeg;
        StellzeitWeg            : INT;  (* sek *)
        WegAusgange             : ARRAY[1..ANZAHL_ZIEL_STELLORGANE] OF structIO;
        WegEingaenge            : ARRAY[1..ANZAHL_ZIEL_STELLORGANE] OF structIO;
    END_STRUCT
    END_TYPE
    
    TYPE structZielWeg :
    STRUCT
        Vorhanden               : INT;
        IO                      : structIO;
        IOWarteAuf              : structIO;
        Wartezeit               : INT;  (* sek *)
        Nachlaufzeit            : INT;  (* sek *)
    END_STRUCT
    END_TYPE
    
    TYPE structIO :
    STRUCT
        Karte           : INT;
        Nummer          : INT;
    END_STRUCT
    END_TYPE
    

    Viele Grüße
    Sebastian

     
  • selucky - 2020-03-24

    Ich hab das jetzt mal mit pack_mode = 1 versucht. Sieht alles soweit gut aus, ohne Lücken und Füllbytes.

     
    • Ingo

      Ingo - 2020-03-24

      Ja, denk nur dran, dass es dadurch nicht portabel ist. Ob es funktioniert
      hängt dann davon ab welcher Prozessor in der Steuerung verbaut und wie
      dieser konfiguriert ist. Das kann bei einem wechsel der Steuerung zu
      seltsamen Effekten führen.

      Ich halte es für sinnvoller die Strukturen natürlich aligned zu lassen.

      https://en.wikipedia.org/wiki/Data_structure_alignment

      ... reads and writes to memory most efficiently when the data is naturally
      aligned, which generally means that the data's memory address is a multiple
      of the data size.
      

      Das heißt wenn du z.B. folgendes Layout hast:

      a: BYTE
      b: INT

      Dann wird vor dem INT oft ein Füllbyte benötigt. Um Problemen aus dem weg
      zu gehen, kannst du jetzt selbst dafür sorgen, dass alle Member der
      Struktur natürlich aligned sind indem du das Füllbyte selbst vorsiehst.
      Dann ist das Verhalten auf jedem Prozessor gleich.

      Also:
      a: BYTE
      dummy1 : BYTE
      b: INT

       
  • Thomas - 2020-03-24

    Moin Sebastian,
    deine Struktur enthält 4-Byte-Datentypen (REAL/UDINT). An diesen Bedürfnis muss sich der Compiler ausrichten, da deine Struktur wieder in anderen Strukturen oder Arrays verwendet werden könnte. 284 Byte + 2 Byte ergibt eine Größe von 286 Byte, die nicht durch 4 teilbar ist. == >> Daher 2 zusätzliche Füllbits. Ansonsten kann es beim Zugriff auf UDINT im zweiten Arrayelement zu Problemen kommen.

    Gruß Thomas

     
  • selucky - 2020-03-25

    Okay, danke für eure Antworten.
    Ich weiß dann jetzt zumindest woran es liegt.
    Die Strukturen bleiben jetzt natürlich angeordnet.
    In C# bastel ich mir dann eine Logik zusammen, die die Anordnung berechnet.
    Dankeschön und viele Grüße

     

Log in to post a comment.