Char 2 Byte gross !

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Mathias
Beiträge: 6952
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Char 2 Byte gross !

Beitrag von Mathias »

Ich code ja schon seit Jahren und ging immer davon aus, das ein Char immer 1 Byte gross ist.

Und jetzt lese ich dies hier.

https://docwiki.embarcadero.com/Librari ... ystem.Char

Hat jetzt ein Char auf einmal 2 Bytes ?

Dies gibt bei mir wie erwarte 1 aus:

Code: Alles auswählen

WriteLn(SizeOf(Char));  // -> 1
Auch dann wen ich delphi erzwinge.

Code: Alles auswählen

program project1;

{$mode delphi}
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Char 2 Byte gross !

Beitrag von Jorg3000 »

Hi!
In FreePascal ist Char immer = AnsiChar, also 1 Byte groß, außer wenn man den Compiler-Schalter {$mode delphiunicode} verwendet, dann verhält es sich wie Delphi 2009 oder höher, wo ein String = UnicodeString und Char = WideChar ist.

Der Schalter {$mode delphi} bezieht sich auf Delphi 7 -Kompatibilität, wo auch in Delphi noch String = AnsiString der Standard war.

Mathias
Beiträge: 6952
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Char 2 Byte gross !

Beitrag von Mathias »

Mit anderen Worten, solange man nicht {$mode delphiunicode} in FPC verwendet besteht kein Gefahr, das der Char auf einmal 2 Byte wird ?
, dann verhält es sich wie Delphi 2009 oder höher, wo ein String = UnicodeString und Char = WideChar ist.
Wen ich das so lese, ist auf einem Modernen Delphi ein Char per Default 2 Byte ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Char 2 Byte gross !

Beitrag von Jorg3000 »

Zweimal Ja.
So ist es.

Da FreePascal einen String = AnsiString inzwischen standardmäßig in UTF-8 kodiert und sich UTF-8 in der IT-Welt etabliert hat, vermute ich, dass für FreePascal kein Wechsel mehr vorgesehen ist.

Man muss sich bei UTF-8 bewusst sein, dass ein Zeichen außerhalb von ASCII ggf. 2 oder 3 oder 4 Bytes belegt, z.B. ein Umlaut 2 Bytes, asiatische Schriftzeichen 3 Bytes, und Emojis u.ä. sogar 4 Bytes.
Grüße, Jörg

Mathias
Beiträge: 6952
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Char 2 Byte gross !

Beitrag von Mathias »

Kann man mit eine Compiler Schalter erzwingen, das der Char garantiert 8Bit hat. Vor allem, würde dies Sinn machen, wen man eine Unit auch in einem Modernen Delphi nutzen will,
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Char 2 Byte gross !

Beitrag von Jorg3000 »

Mathias hat geschrieben: Di 3. Jun 2025, 16:57 wen man eine Unit auch in einem Modernen Delphi nutzen will,
Wenn der eigene Quellcode zu allen Delphi-Versionen kompatibel sein soll, könnte man anstatt "String" explizit AnsiString (8-Bit-Grundlage) oder UnicodeString (16-Bit-Grundlage) schreiben.
Mathias hat geschrieben: Di 3. Jun 2025, 16:57 Kann man mit eine Compiler Schalter erzwingen, das der Char garantiert 8Bit hat.
Nein, so pauschal funktioniert das nicht.
Wenn du garantieren kannst, dass deine verwendeten String-Inhalte nur lateinische und westeuropäische Zeichen enthalten (z.B. deutsche Umlaute, französische Akzentzeichen etc.) könntest du mit Ansi-CodePage 1252 arbeiten.

Man kann sich einen eigenen String-Typ mit CodePage 1252 (Westeuropäisch) definieren, aber damit hatte ich zumindest früher mal Probleme, glaube ich mich zu erinnern.

Code: Alles auswählen

type AnsiString1252 = type AnsiString(1252);
Man kann einen einzelnen String per SetCodePage() in eine bestimmte Codepage konvertieren, z.B. halt CP 1252 = westeuropäisch.

Code: Alles auswählen

function StringToCP1252(const s: AnsiString): RawByteString; 
begin
  Result := s; 
  SetCodePage(Result, 1252, true);
end;
Wenn ein Zeichen nicht in Codepage 1252 gehört, wird es als "?" übersetzt.
So kannst du sicher sein, dass westeuropäische Zeichen genau 1 Byte belegen. Das macht aber nur Sinn, wenn du den String wirklich Byte für Byte durchlaufen musst.
Grüße, Jörg

Mathias
Beiträge: 6952
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Char 2 Byte gross !

Beitrag von Mathias »

Jorg3000 hat geschrieben: Di 3. Jun 2025, 15:56 Zweimal Ja.
So ist es.

Da FreePascal einen String = AnsiString inzwischen standardmäßig in UTF-8 kodiert und sich UTF-8 in der IT-Welt etabliert hat, vermute ich, dass für FreePascal kein Wechsel mehr vorgesehen ist.

Man muss sich bei UTF-8 bewusst sein, dass ein Zeichen außerhalb von ASCII ggf. 2 oder 3 oder 4 Bytes belegt, z.B. ein Umlaut 2 Bytes, asiatische Schriftzeichen 3 Bytes, und Emojis u.ä. sogar 4 Bytes.
Grüße, Jörg
Da habe ich mir selbst eine Falle gestellt. Daher habe ich gerade in meine SDL3 Bindung alle Char durch AnsiChar ersetzt. Es wäre echt schade wen es an so einer Kleinigkeit mit Delphi scheitern würde.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Char 2 Byte gross !

Beitrag von Jorg3000 »

Mathias hat geschrieben: Di 3. Jun 2025, 20:11 meine SDL3 Bindung alle Char durch AnsiChar ersetzt.
Ich kenne SDL3 nicht, aber ausschlaggebend ist das Interface der Library.
Und das wird festgelegt vermutlich entweder PAnsiChar oder PWideChar benötigen. Da würde ich vorsichtshalber nicht einfach "Char" nehmen, wenn deine Unit für FreePascal und Delphi sein soll.

PascalDragon
Beiträge: 961
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Char 2 Byte gross !

Beitrag von PascalDragon »

Jorg3000 hat geschrieben: Di 3. Jun 2025, 15:56 Da FreePascal einen String = AnsiString inzwischen standardmäßig in UTF-8 kodiert und sich UTF-8 in der IT-Welt etabliert hat, vermute ich, dass für FreePascal kein Wechsel mehr vorgesehen ist.
Das ist nicht korrekt. Die aktuelle RTL in main ist darauf vorbereit mit Char = UnicodeChar und String = UnicodeString gebaut zu werden. Wir haben es noch nicht finalisiert, aber es wird wahrscheinlich verschiedene Distributionen für verschiedene Plattformen geben (z.B. die String = UnicodeString Variante für Windows und die String = AnsiString Variante für die *nix Plattformen). Das ist dann noch zusätzlich dazu, dass die RTL Delphi-kompatible Namespaces haben wird oder nicht.
FPC Compiler Entwickler

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Char 2 Byte gross !

Beitrag von Jorg3000 »

PascalDragon hat geschrieben: Do 5. Jun 2025, 21:46 Die aktuelle RTL in main ist darauf vorbereit mit Char = UnicodeChar und String = UnicodeString gebaut zu werden. Wir haben es noch nicht finalisiert, aber es wird wahrscheinlich verschiedene Distributionen für verschiedene Plattformen geben (z.B. die String = UnicodeString Variante für Windows und die String = AnsiString Variante für die *nix Plattformen).
Oh oh, dann passiert möglicherweise der gleiche Mist, weshalb ich früher die Umstellung auf Delphi 2009 nicht ohne weiteres mitmachen konnte - nämlich weil einige meiner Prozeduren fest von 8-Bit-Kodierung ausgingen (weil es vorher in Delphi und Pascal immer so war).
Das schreckt mich zwar heutzutage nicht mehr, aber falls man aus Gründen eine 8-Bit-Basis wünscht, sollte man also vorsichtshalber schon jetzt "AnsiString" anstelle von String in seine Sources schreiben - oder sich darauf vorbereiten, dass ein String und Char entweder aus 1-Byte- oder 2-Byte-Zeichen bestehen kann (je nach zukünftiger Lazarus-Distribution).
Ich sehe jetzt schon vor meinem geistigen Auge, dass die Foren voll sein werden von Beiträgen, wo die Leute über solche Unterschiede stolpern.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6845
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Char 2 Byte gross !

Beitrag von af0815 »

Jorg3000 du hast da etwas nicht berücksichtigt, Lazarus und FPC arbeiten längst mit UTF8, das kann 1 bis 4 Bytes je Zeichen belegen. Die komische Annahme mit fixen 2 Bytes (UCS-2) hat Delphi mal getroffen. Das ist auch schon deprecated.

Warum du noch nicht so drüber gestolpert bist, wenn du keinen Mehrbytecodepoint als Zeichen verwendest, verhält sich UTF-8 wie ein Single Byte Sting, wehe du schmeißt dort dann einen Umlaut rein, dann ist es mit den 1 Byte Annahmen schnell vorbei.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Char 2 Byte gross !

Beitrag von Jorg3000 »

.
Das hatte ich oben ja bereits geschrieben: ... ggf. 2 oder 3 oder 4 Bytes belegt, z.B. ein Umlaut 2 Bytes, asiatische Schriftzeichen 3 Bytes, und Emojis u.ä. sogar 4 Bytes.

Ich meinte 1 Byte als Basis (AnsiString/Utf8String) oder 2 Byte Basis (WideString/UnicodeString) unabhängig davon, dass in beiden Systemen ein Zeichen mehrere String-Elemente[Index] belegen kann, in beiden Systemen bis zu 4 Byte Kapazität pro Zeichen.

Was ich meinte: Wenn es zukünftig vom Betriebssystem und der Lazarus-Distribution abhängig ist, was ein String und ein Char ist, wird es uneinheitlich. Darauf muss man dann achten, z.B. muss man ggf. mit bedingter Kompilierung einen String-Typ in einen anderen konvertieren, je nachdem ob ein Char 1 oder 2 Byte groß ist und was man evtl. in einem Spezialfall benötigt.

Und die Kluft zwischen Windows und Linux wird wieder größer, wenn die Distribution für Windows Char=WideChar nutzt, hingegen die Linux-Distribution Char=AnsiChar verwendet.

Mathias
Beiträge: 6952
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Char 2 Byte gross !

Beitrag von Mathias »

Oh oh, dann passiert möglicherweise der gleiche Mist, weshalb ich früher die Umstellung auf Delphi 2009 nicht ohne weiteres mitmachen konnte - nämlich weil einige meiner Prozeduren fest von 8-Bit-Kodierung ausgingen (weil es vorher in Delphi und Pascal immer so war).
Das schreckt mich zwar heutzutage nicht mehr, aber falls man aus Gründen eine 8-Bit-Basis wünscht, sollte man also vorsichtshalber schon jetzt "AnsiString" anstelle von String in seine Sources schreiben - oder sich darauf vorbereiten, dass ein String und Char entweder aus 1-Byte- oder 2-Byte-Zeichen bestehen kann (je nach zukünftiger Lazarus-Distribution).
Ich sehe jetzt schon vor meinem geistigen Auge, dass die Foren voll sein werden von Beiträgen, wo die Leute über solche Unterschiede stolpern.
Man könnte es wenigstens mit eine Compilerschalter machen.
Bei den ShortString hatten sie es mit {$H+} gemacht.
Dann würde der alte Code kompatibel bleiben, wen mal etwas am Char geändert wird.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 2139
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Char 2 Byte gross !

Beitrag von Warf »

PascalDragon hat geschrieben: Do 5. Jun 2025, 21:46 Das ist nicht korrekt. Die aktuelle RTL in main ist darauf vorbereit mit Char = UnicodeChar und String = UnicodeString gebaut zu werden. Wir haben es noch nicht finalisiert, aber es wird wahrscheinlich verschiedene Distributionen für verschiedene Plattformen geben (z.B. die String = UnicodeString Variante für Windows und die String = AnsiString Variante für die *nix Plattformen). Das ist dann noch zusätzlich dazu, dass die RTL Delphi-kompatible Namespaces haben wird oder nicht.
Das klingt nach einer sehr sehr schlechten Idee die sehr viele existierende Cross Platform code bases brechen wird. Vor allem ist mir keine Programmiersprache bekannt die das so macht. Java und C# sind immer UTF-16, C und C++ haben "char" als single byte char (wobei die Größe eines Bytes jeh nach Platform unterschiedlich sein kann und bis zu 64 bit groß sein kann).
Selbst Delphi benutzt ausschließlich 16 bit chars auf allen Platformen die unterstützt werden, und nichtmal Microsoft kam auf die Idee in Visual C++ 16 bit chars einzuführen.

Die Entscheidung auf 16 bit chars zu gehen könnte ich ja irgendwo noch verstehen aus Delphi Kompatibilität. Aber so ein misch-masch aus 8 und 16 bit Chars das hilft doch absolut niemandem. Und wenn das Ziel kompatibilitätsmaximierung ist dann wäre UTF-32 mit 4 byte Chars der richtige Weg

Mathias
Beiträge: 6952
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Char 2 Byte gross !

Beitrag von Mathias »

Was nützt eigentlich ein 16bit Char. Mit utf8 ist doch das Problem gelöst, das man fast unendlich viele Zeichen darstellen kann.
Und wen doch einmal einer auf die Idee kommt und eine 16bit Char will, gibt es ja WideChar.
Es reicht ja schon, das es beim Integer keine Garantie gibt, das er 32bit hat.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten