Strings länger als 255

Thomas_v2.1

Well-known member
Beiträge
8.810
Punkte Reaktionen
2.700
Zuviel Werbung?
->Hier kostenlos registrieren
Man kann in Codesys ja Strings länger als 255 Zeichen definieren, wobei dann die Standard-Stringfunktionen nicht mehr funkionieren.
Ich frage mich aber, wie bei Codesys Informationen über die Stringlänge gespeichert werden. Bei Pascal war es ja so dass in einem Byte die Längeninformation gespeichert wird. Ist das bei Codesys auch so, oder sind die Strings wie in C Nullterminiert?

Wenn ich nämlich meine eigenen Stringfunktionen schreiben will die auch mit längeren Strings arbeiten, muss ich ja wissen wie ein String bei Codesys aufgebaut ist.
Hier
http://www.sps-forum.de/showthread....blem-ein-Array-in-2-Strings?p=98204#post98204
gibt es eine Version von Werner29 (ist der nicht bei 3s?) in dem er einfach die Bytes 1:1 rüberkopiert. Ich sehe da keine Sonderbehandlung um irgendwie eine Stringlängenangabe zu setzen, oder den String auf jeden Fall mit einer Null zu terminieren wenn die aneinandergehängten Strings länger als die Maximallänge sein sollten. Unter C ist sowas ein berühmter Fehler bei der Verwendung von strncat. Muss man da bei Codesys irgendwas beachten?
 

mkd

Well-known member
Beiträge
197
Punkte Reaktionen
30
In TwinCAT wird bei Strings mit der aus C bekannten anullterminierung gearbeitet:

http://infosys.beckhoff.com/index.p...libstandard_string_functions_overview.htm&id=

Wobei im Beckhoff Infosys wieder nur (viel) zu wenig Informationen angegeben sind.

Bei meiner Arbeit mit Strings weit über 255 Zeichen ist mir nie eine Einschränkung der Standard Stringfunktionen aufgefalleb.

BTW: Ich wusste garnicht das die Stringlänge bei Pascal im letzten Byte angegeben wird.


Gruß
 
OP
T

Thomas_v2.1

Well-known member
Beiträge
8.810
Punkte Reaktionen
2.700
Zuviel Werbung?
->Hier kostenlos registrieren
Ich bin auch unter TwinCAT (2.10) - hoffentlich ist das nicht zu alt und da waren noch Bugs drin.

Nächste Merkwürdigkeit ist dass eine Variable welche im Var-Bereich als Datentyp String mit einem String initialisiert wird nur noch 253! Bytes haben darf.

Wenn man sich einen langen String mittels einer Schleife und mehreren Concat-Aufrufen zusammensetzen lässt funktionieren die Standard-Funktionen auch, obwohl die Parameter in der Dokumentation als string(255) angegeben sind.
Momentan lasse ich mir über einen Netzwerk-FB einen Puffer beschreiben, und diesen Puffer habe ich als Datentyp String angelegt. Im Twincat Plc Control werden die empfangenen Strings zwar korrekt angezeigt, aber die String-Funktionen wie z.B. MID funktionieren auf denen dann nicht. Da am Ende des Textes im Strings auf jeden Fall eine Null steht, sollten - wenn es denn eine Nullterminierung gibt - die Standardfunktionen doch eigentlich auch funktionieren.

Ich mache ja eher selten was mit Codesys/Twincat, aber so was muss doch irgendwo eindeutig beschrieben sein.
 

Werner29

Well-known member
Beiträge
297
Punkte Reaktionen
117
Hallo,

STRING ist bei CODESYS und TwinCAT nullterminiert. Die character sind ASCII-kodiert und beim ersten 0 oder '\0' endet der STRING.
Die Länge bei der Deklaration bestimmt den verfügbaren Speicherplatz, dabei wird die 0 nicht mitgezählt. Das heisst ein STRING(255) belegt
einen Speicher von 256 Bytes.

In dem angesprochenen Beispielcode (http://www.sps-forum.de/showthread.p...8204#post98204) wird sehr wohl die Länge der Strings berücksichtigt.
Und zwar in folgender Codezeile:

IF pbyte^=0 THEN

Der Pointer läuft über den ersten STRING und bei der ersten 0 wird auf den zweiten STRING gewechselt und wenn der zur 0 kommt, dann wird die Schleife verlassen.
 
OP
T

Thomas_v2.1

Well-known member
Beiträge
8.810
Punkte Reaktionen
2.700
STRING ist bei CODESYS und TwinCAT nullterminiert. Die character sind ASCII-kodiert und beim ersten 0 oder '\0' endet der STRING.
Die Länge bei der Deklaration bestimmt den verfügbaren Speicherplatz, dabei wird die 0 nicht mitgezählt. Das heisst ein STRING(255) belegt
einen Speicher von 256 Bytes.

Wenn der String nullterminiert ist, frage ich mich welche Aufgabe hat die Längenangabe eines Strings bei einem Funktionsparameter übernimmt. Geprüft wird da ja nichts. Zumindest wenn ein zu kurzer String als Funktionsrückgabewert angegeben wurde sollte es Mecker oder mindestens eine Warnung geben.

In dem angesprochenen Beispielcode (http://www.sps-forum.de/showthread.p...8204#post98204) wird sehr wohl die Länge der Strings berücksichtigt.
Und zwar in folgender Codezeile:

IF pbyte^=0 THEN

Der Pointer läuft über den ersten STRING und bei der ersten 0 wird auf den zweiten STRING gewechselt und wenn der zur 0 kommt, dann wird die Schleife verlassen.

Und was passiert wenn der resultierende String aus String1+String2 länger als 255 wird?
Meiner Meinung nach ist dann der String im Rückgabewert ohne Nullterminierung, bzw. wenn dann ist diese höchstens zufällig vorhanden. Oder ich übersehe da noch was.

Fangen die Bausteine in der Standard-Bibliothek so etwas ab?
 

Werner29

Well-known member
Beiträge
297
Punkte Reaktionen
117
Wenn der String nullterminiert ist, frage ich mich welche Aufgabe hat die Längenangabe eines Strings bei einem Funktionsparameter übernimmt. Geprüft wird da ja nichts. Zumindest wenn ein zu kurzer String als Funktionsrückgabewert angegeben wurde sollte es Mecker oder mindestens eine Warnung geben.

Wie immer, die Länge definiert den verfügbaren Speicher. Auch bei einer Funktionsrückgabe, bei einer Zuweisung wird jeweils das Minimum der beiden Grössen kopiert, evtl. wird dann abgeschnitten.

Und was passiert wenn der resultierende String aus String1+String2 länger als 255 wird?
Meiner Meinung nach ist dann der String im Rückgabewert ohne Nullterminierung, bzw. wenn dann ist diese höchstens zufällig vorhanden. Oder ich übersehe da noch was.

Fangen die Bausteine in der Standard-Bibliothek so etwas ab?
Ja, du übersiehst da was: die Nullterminierung des zweiten Strings wird mitkopiert, und das ist kein Zufall. Natürlich sollten die Standard-Lib
Bausteine das abfangen.
 
OP
T

Thomas_v2.1

Well-known member
Beiträge
8.810
Punkte Reaktionen
2.700
Ja, du übersiehst da was: die Nullterminierung des zweiten Strings wird mitkopiert, und das ist kein Zufall. Natürlich sollten die Standard-Lib
Bausteine das abfangen.

Wenn man die Strings einkürzt mit
Code:
FUNCTION My_CONCAT : STRING(5)

VAR_INPUT
    STR1:STRING(5);
    STR2:STRING(5);
END_VAR

Und das dann mit
Code:
strResult := My_CONCAT(STR1 := 'ABCDE', STR2 := 'FGHIJ');
wird keine Nullterminierung mitkopiert.

Es wird davon ausgegangen dass an
ADR(My_CONCAT) + 6
der Wert Null steht.

Dazu müsste man aber wissen wie der Speicher bei Funktionsrückgabewerten verwaltet wird, bzw. ob dieser immer komplett mit Null initialisiert wird. Über solche Dinge lässt sich die Dokumentation aber nicht aus.

Aber dass mit der Nullterminierung ist schonmal gut zu wissen. Ich fülle nämlich momentan einen String über eine Netzwerkfunktion. D.h. ich brauche einfach nach der Anzahl der empfangenen Zeichen in den String eine binäre Null zu schreiben und kann dann die Stringfunktionen darauf loslassen.
 

Werner29

Well-known member
Beiträge
297
Punkte Reaktionen
117
Zuviel Werbung?
->Hier kostenlos registrieren
Normalerweise sollte einen der Speicher nicht interessieren, daher wird das in der Dokumentation nicht erklärt.
Aber: der Speicher wird nicht komplett genullt, die Daten bekommen aber ihre Default-Initialisierung, d.h. in diesem Fall
wird der String in der Rückgabe mit dem Leerstring initialisiert.
Das heisst ausserdem, dass der Code für den Fall, dass nicht beide Strings in den Zielstring kopiert werden, falsch ist.
Es sollte auf alle Fälle noch am Ende eine 0 geschrieben werden. Das ganze funktioniert nur deswegen, weil beim kopieren
des Ergebnisstrings der Funktion an ein Ziel noch eine 0 explizit an das Ende des Strings geschrieben wird.
Also es funktioniert schon so, aber schön ist es nicht, ich habe das an der Originalstelle geändert.
 
Oben