Wikibooks
dewikibooks
https://de.wikibooks.org/wiki/Hauptseite
MediaWiki 1.47.0-wmf.19
first-letter
Medium
Spezial
Diskussion
Benutzer
Benutzer Diskussion
Wikibooks
Wikibooks Diskussion
Datei
Datei Diskussion
MediaWiki
MediaWiki Diskussion
Vorlage
Vorlage Diskussion
Hilfe
Hilfe Diskussion
Kategorie
Kategorie Diskussion
Regal
Regal Diskussion
TimedText
TimedText talk
Modul
Modul Diskussion
Veranstaltung
Veranstaltung Diskussion
Traktorenlexikon: Porsche-Diesel
0
10375
1090834
1090455
2026-09-14T12:57:21Z
~2026-48865-68
116867
/* Allgaier System Porsche (1950-1955) */
1090834
wikitext
text/x-wiki
{{:Traktorenlexikon: Navigation}}
{{Wikipedia|Porsche Traktor}}
[[Datei:1048 Porsche Diesel Traktoren.jpg|thumb|upright=1.5|Porsche-Diesel-Traktoren]]
==Geschichte==
Ferdinand Porsche hatte das, was man ein universelles technisches Gefühl nennen kann. Er beschränkte sich nicht auf irgendein Spezialgebiet, sondern befasste sich mit allen mechanischen Fortbewegungsmitteln.
Den ersten großen Erfolg schreibt die Geschichte im Jahr 1900. Damals war die benzin-elektrische Kutsche des gerade 25-jährigen Konstrukteurs der Firma Lohner aus Wien die Sensation auf der Pariser Weltausstellung. Es gibt seither kaum eine Gattung von Fahrzeugen, an denen sich Porsche nicht versuchte und bei deren Konstruktion er nicht auch Erfolge erzielt hätte. Auf der einen Seite stehen die berühmten Rennwagen: der Austro- Daimler, der Mercedes SSK, der 16 Zylinder Auto Union oder die legendären Porsche-Sportwagen, auf der anderen Seite stehen viele volkstümliche Konstruktionen, eine Krönung ist sicher der Volkswagen „Käfer“.
So wie der Volkswagen nicht nur den Reichen und Bevorrechtigten gehören sollte, so sollte auch ein „Volksschlepper“ für alle da sein. Eine einfache, robuste und zuverlässige Zugmaschine, die dem Bauern das Pferd und den Ochsen ersetzte.
Schon im Jahr 1915 arbeitete Ferdinand Porsche bei Austro-Daimler an einem „Pflugtraktor“ und an dem „Landwehr-Train“, eine Zugmaschine mit Benzinmotor und einer Reihe von Anhängern mit Elektroantrieb. 1937 begann die Entwicklung und der Bau einiger Prototypen des „Volksschleppers“. Dieses Projekt, eine Art Parallele zum Volkswagenwerk, sollte es ermöglichen, die Motorisierung in der Landwirtschaft entscheidend voranzutreiben. Doch die Kriegslage zwang im Jahr 1941 die Pläne des „Volkstraktorwerks“ in Waldbröl bei Köln aufzugeben. 1942 folgte der „Ostradschlepper“, eine Zugmaschine mit riesigen Rädern, speziell für das Sumpfgelände des Ostens.
Nach dem zweiten Weltkrieg, im Jahr 1946, baute Porsches langjähriger Chefkonstrukteur Karl Rabe in Gmünd in Kärnten aus den Erfahrungen und den noch vorhandenen Bauteilen des von Ferdinand Porsche konstruierten Volksschleppers einen mit 20 PS Leistung und Vergasermotor angetriebenen Schlepper. In Brasilien, an der staatlichen Versuchsanstalt „IPANEMA“, wurde dieser Schlepper umfangreich getestet. Aufgrund der gewonnenen Erfahrungen wurde diese Maschine grundlegend überarbeitet und als „Dieselschlepper Typ 313 “ neu konstruiert. Er besitzt einen 4 Takt-Zweizylinder-Diesel-Motor mit Luftkühlung und 17 PS Dauerleistung. Ausstattungen wie Zapfwelle, Riemenscheibe, Mähantrieb, Anhängevorrichtung und eine Hebeeinrichtung für Anbaugeräte waren vorhanden.
Auch ein Einzylinder-Diesel-Kleinschlepper mit 8 PS Leistung (Typ 323) wurde für Gebirgs- und Weinbergbauern entwickelt und gebaut.
In seiner Gesamtheit stellten die Porsche-Schlepper, die auf der Industrie- und Gewerbeausstellung in Klagenfurt gezeigt wurden, einen ganz gewaltigen Schritt in der Schlepperkonstruktion dar. Leider war es damals unter den schwierigen Umständen unmöglich, in Österreich eine eigene Schlepperproduktion aufzubauen.
Später wurden in Österreich doch noch Ackerschlepper von [[Traktorenlexikon: HSCS|Hofherr-Schrantz]] mit Allgaier-Lizenz gebaut. Ein Beispiel ist der Austro Junior, welcher einem Porsche Junior mit verringerter Motorleistung entspricht.
Unter Ferry Porsche und Chefkonstrukteur Karl Rabe entstand im Jahr 1948 aus Volkswagenteilen der erste Porsche Sportwagen Typ 356. Dieser Sportwagen, ein Spider mit Aluminium-Karosserie auf Käfer-Chassis mit dem Boxermotor vor der Hinterachse, fand sofort weltweit seine Liebhaber. Die Konstruktion war damals der Zeit weit voraus, und ist noch heute die Grundlage der Firma Porsche.
Der schwäbische Schlepperproduzent Allgaier in Uhingen übernahm auf Basis des Typ 313 die Lizenzproduktion der „Volksschlepper“. Als 1950 der erste Allgaier-Schlepper „System Porsche“ Modell AP 17 auf den Markt kam, wirkte das faszinierend auf die ganze Landwirtschaft. Durch viele technische Neuheiten, wie Luftkühlung, Leichtbauweise, ölhydraulische Kupplung und dem konkurrenzlosen Anschaffungspreis von 4450 DM waren die Auftragsbücher schnell gefüllt. Die Produktion wurde in Friedrichshafen-Manzell direkt am Bodensee aufgebaut. Das neue attraktive Werksgelände hat technische Tradition. Hier stieg um 1900 das erste Luftschiff des Grafen Zeppelin auf. Das weltweit größte Flugboot Do X mit 12 Motoren startete 1930 zum Probeflug, um mit Passagieren über England nach Amerika zu fliegen.
Am 3. September 1950 feierte Professor Porsche seinen 75. Geburtstag. Wenige Monate vor seinem Tode, im Januar 1951, kann er noch die ersten großen Erfolge aus seinem Lebenswerk, den Allgaier-Schlepper AP 17 System Porsche, miterleben.
Mit einer modernen Schlepperbaureihe A111 bis A144 System Porsche behauptete sich Allgaier von 1953 bis Mitte der 50er Jahre die Spitzenposition auf dem Deutschen Schleppermarkt. Es wurden zusätzlich zum AP 17 vier weitere Schleppertypen mit 11, 22, 33 und 44 PS gebaut. Schon zu dieser Zeit arbeitete man das Programm nach einem Baukastensystem aus. Der kleine 11 PS Schlepper (Basis ist der Kleinschlepper Typ 323) war ein luftgekühlter Einzylinder, die nächstgrößeren Typen bekamen je einen Zylinder dazu, mit gleichen Kolben, Pleueln und Ventiltrieb. Man kann heute 80 Prozent aller Einzelteile unter den einzelnen Schleppertypen System Porsche austauschen. Nur die Getriebe, Achsen und Lenkung sind nicht bei allen Typen gleich. Mehr als 25 000 Schlepper mit dem Namen Allgaier System Porsche verließen bis 1955 die Werkshallen in Uhingen und Friedrichshafen. Der Schlepperbau bei Allgaier in Uhingen wurde zu Jahresende 1955 eingestellt.
1956 wurde die Allgaier Maschinenbau GmbH in die Porsche-Diesel-Motorenbau GmbH in Friedrichshafen am Bodensee umgewandelt. Die neue Firma, ein Unternehmen des Mannesmann-Konzerns, fertigte von dort an in den neu erstellten Produktionshallen Diesel-Motoren sowie Land- und Industriebaumaschinen.
Den von Porsche-Diesel gebauten Motoren lagen die Konstruktionserfahrungen von Ferdinand Porsche zugrunde. Mit der Entwicklungsstätte in Zuffenhausen bestand eine enge Zusammenarbeit. Die Schlepper haben ähnliche Typenbezeichnungen erhalten wie die Porsche-Sportwagen. Namen wie Junior, Standard, Super und Master waren damals bei den Bauern in aller Munde und standen für fortschrittliche Konstruktion. Die formschöne, mit mehreren Zierleisten geschmückte, weit nach vorne gezogene rot lackierte Motorverkleidung wirkte sehr elegant und modern.
Auf dem Höhepunkt ihres Erfolgs erreichten die rot lackierten Schlepper vom Bodensee 1959 und 1960 den zweiten Platz in der deutschen Zulassungsstatistik. Rund 120 000 Porsche-Diesel-Schlepper wurden in acht Jahren bis 1963 gebaut. Dann kam das Ende einer Ära, Porsche-Diesel stellt den Schlepperbau ein.
Heute sind Allgaier- und Porsche-Diesel-Schlepper, nachdem sie jahrelang ihren Dienst taten, gesuchte und begehrte Liebhaberstücke. Diese faszinierenden Schlepper werden mit viel Sachverstand von ihren Besitzern restauriert. In neuem Glanz strahlen die Schmückstücke vom Bodensee wieder eine ganz besondere Faszination aus.
1954: Gründung der '''Porsche-Diesel-Motorenbau GmbH''' mit Unterstützung des Mannesmann-Konzerns
1956: Werksgründung mit einem Stammkapital von 100.000 DM. Die Mannesmann AG stockt das Kapital auf beachtliche 2,5 Millionen DM auf. Geplant ist die Fertigung von 20.000 Traktoren jährlich. Der Typ "AP 18" verfügt über eine Teleskop-Einzelradfederung vorne. Zapfwelle und Kraftheber runden die Serie von 12 PS bis 44 PS ab.
Die '''Porsche-Diesel-Motorenbau GmbH''' übernimmt die Schlepperproduktion der [[Traktorenlexikon: Allgaier | '''Allgaier Werke GmbH''']] in Friedrichshafen am Bodensee.
1957: Vorstellung einer neuen Modell-Palette und Produktionsbeginn mit 4 Schleppern von 14-50 PS. Die geplante Stückzahl wurde zur Hälfte erreicht.
1958: Zusammenarbeit mit [[Traktorenlexikon: Deutz|Deutz]] Die geplante Jahresproduktion wird mit 17.000 Einheiten fast erreicht. Der Marktanteil steigt von 7% auf 12,1%
1959: Umfangreiche Modellpalette von 20 PS bis 40 PS. Die Ausstattung ist umfangreich und zweckmäßig. Sie umfasste luftgekühlte Porsche-Diesel-Motoren, gut gelagerte Getriebe, mehrere Zapfwellen, Mähwerkantrieb und Kraftheber
1960: neue Modellreihe mit 5 Schlepper von 14 - 35 PS
1962: Übernahme der [[Traktorenlexikon: MAN|MAN]]-Traktorenfertigung und später Einstellung der Schlepper-Produktion und Verkauf an [[Traktorenlexikon: Renault|Renault]]
1963: Montage des letzten Porsche-Traktors. Die Werkanlagen werden von Daimler-Benz übernommen, während Vertrieb und Einzelteilversorgung an Renault übergehen.
1964: [[Traktorenlexikon: Iseki|Iseki]] beginnt in Japan mit den 1963 geschlossen Lizenzvereinbarungen, Teilen und Werkzeugen mit der Fertigung von Traktoren, die die Porsche-Herkunft erkennen lassen.
==Typen==
===Konstruktionsbüro Porsche (1938-1949)===
{{:Traktorenlexikon:_Create|Typ 110}} (1938-1939) Prototyp
{{:Traktorenlexikon:_Create|Typ 111}} (1939-1940) Prototyp
{{:Traktorenlexikon:_Create|Typ 112}} (1940-1941) Prototyp
{{:Traktorenlexikon:_Create|Typ 323}} (1946-1949) für die Firma Dusio in Italien (keine Serienfertigung)
===Allgaier System Porsche (1950-1955)===
[[Datei:Allgaier AP 17-51.JPG|thumb|Allgiaer AP 17-51 (Baujahr 1952)]]
* [[Traktorenlexikon: Allgaier AP17|Allgaier AP17]] (1950-1951) [[Traktorenlexikon: Porsche-Diesel AP17|AP17]]
* [[Traktorenlexikon: Allgaier AP17-51|Allgaier AP17-51]] (1951-1954)
* [[Traktorenlexikon: Allgaier AP17S|Allgaier AP17S]] (1951-1954) Schmalspur
* [[Traktorenlexikon: Allgaier P312|Allgaier P312]] (1954) Kaffeebomber
* [[Traktorenlexikon: Allgaier AP22|Allgaier AP22]] (1952-1955)
* [[Traktorenlexikon: Allgaier AP22S|Allgaier AP22S]] (1950-1954) Schmalspur
* [[Traktorenlexikon: Allgaier AP16|Allgaier AP16]] (1954-1955) [[Traktorenlexikon: Porsche-Diesel AP16|AP16]]
[[Datei:Allgaier A122.jpg|thumb|Allgiaer A 122]]
* [[Traktorenlexikon: Allgaier A111|Allgaier A111]] (1952-1955)
* [[Traktorenlexikon: Allgaier A122|Allgaier A122]] (1953-1955)
* [[Traktorenlexikon: Allgaier A133|Allgaier A133]] (1953-1955)
* [[Traktorenlexikon: Allgaier A144|Allgaier A144]] (1953-1955)
===Porsche Diesel Motorenbau GmbH (1956-1963)===
====Allgaier Traktoren bei Porsche (1956-1957)====
Nach der Übernahmen von [[Traktorenlexikon: Allgaier|Allgaier]] zum 1.1.1956 wurden ab Juli 1956 die A111-A144 als P111-P144 in rot und mit ''Porsche Diesel'' Aufschrift ausgeliefert.
{{:Traktorenlexikon:_Create|P111}} (1956/7-1957)
{{:Traktorenlexikon:_Create|P111K}} (1956/7-1957)
{{:Traktorenlexikon:_Create|P122}} (1956/7-1957)
{{:Traktorenlexikon:_Create|P133}} (1956/7-1957)
{{:Traktorenlexikon:_Create|P144}} (1956/7-1957)
Ab September wurde das [[Traktorenlexikon: Allgaier|Allgaier]] AP-Program reduziert angeboten. Der [[Traktorenlexikon: Allgaier AP22|Allgaier AP22]] wurde direkt übernommen und aus dem [[Traktorenlexikon: Allgaier AP16|Allgaier AP16]] wurde der AP18 mit einem gedrosselten AP22-Motor.
{{:Traktorenlexikon:_Create|AP18}} (1956/9-1957)
{{:Traktorenlexikon:_Create|AP22}} (1956/9-1957)
{{:Traktorenlexikon:_Create|AP22S}} (1956/9-1957)
====Junior (1957-1963)====
[[Datei:03581 Porsche Diesel Junior Logo.jpg|thumb|Porsche Diesel Junior]]
[[Datei:0381 Porsche Diesel F 108.jpg|thumb|Porsche Diesel F 108]]
[[Datei:0384 Porsche Diesel F 108.jpg|thumb||Porsche Diesel F 108]]
{{:Traktorenlexikon:_Create|Junior 4}}
{{:Traktorenlexikon:_Create|Junior K}}
{{:Traktorenlexikon:_Create|Junior L}}
{{:Traktorenlexikon:_Create|Junior S}}
{{:Traktorenlexikon:_Create|Junior V}}
{{:Traktorenlexikon:_Create|Junior}}
====Standard (1957-1963)====
{{:Traktorenlexikon:_Create|Standard 208}}
{{:Traktorenlexikon:_Create|Standard}}
{{:Traktorenlexikon:_Create|Standard S}}
{{:Traktorenlexikon:_Create|Standard AP}}
{{:Traktorenlexikon:_Create|Standard AP/S}}
{{:Traktorenlexikon:_Create|Standard T}}
{{:Traktorenlexikon:_Create|Standard Star 238}}
{{:Traktorenlexikon:_Create|Standard Star 239}}
{{:Traktorenlexikon:_Create|Standard Star 219}}
{{:Traktorenlexikon:_Create|Standard 218}}
{{:Traktorenlexikon:_Create|Standard V 218}}
====Super (1957-1963)====
[[Datei:0345_Porsche_Super_308N.jpg|thumb||Porsche Diesel Super 308N]]
{{:Traktorenlexikon:_Create|Super N308}}
{{:Traktorenlexikon:_Create|Super L308}}
{{:Traktorenlexikon:_Create|Super S308}}
{{:Traktorenlexikon:_Create|Super B308}}
{{:Traktorenlexikon:_Create|Super N309}}
{{:Traktorenlexikon:_Create|Super S309}}
{{:Traktorenlexikon:_Create|Super B309}}
{{:Traktorenlexikon:_Create|Super F308}}
{{:Traktorenlexikon:_Create|Super L 318}}
{{:Traktorenlexikon:_Create|Super L 319}}
{{:Traktorenlexikon:_Create|Super Export 329}}
{{:Traktorenlexikon:_Create|Super Export 339}}
====Master (1958-1963)====
Die Porsche Master sind Traktoren mit Vier-Zylinder-Motoren und einer Leistung von 50 PS. Gebaut wurden sie auch in einer vereinfachten Version ohne Frontzapfwelle und mit Muschelschalenkotflügel für den Export, welche mit '''V''' bezeichnet wurde. Die normale Version bekam dann den Zusatzbuchstaben '''N'''. Gelegentlich taucht auch noch ein '''S''' auf was auf eine Ausführung mit Schnellganggetriebe hinweist. Die Baureihe starte mit dem '''Master 408''' welcher aus dem [[Traktorenlexikon: Porsche-Diesel P144|P 144]] durch einen überarbeiten Motor und dem ZF Triebwerk A 20/18 II entstand. Durch das neuen ZF Triebwerk A 216 entstand dann der '''Master 418'''. Nach der allgemeinen Überarbeitung der Motoren wurde daraus der '''Master 419'''. Um eine preiswertere alternative anbieten zu können, wurde der Master 419 mit den ZF Triebwerk A 17, das im P144 verbaut war, ausgerüstet, welcher als '''Master 429''' bezeichnet wird. Dies Variante wurde auch teilweise mit den alten Motoren des Master 418 ausgerüstet was zum Baumuster '''Master 428''' führte. Zuletzt entstand noch aus dem Master 419 der '''Master 409''' mit dem Getriebe des Master 408. 1962 war der Master technisch nicht mehr auf dem neusten Stand, es waren Sechs-Zylinder-Motoren und Allrad gefragt.
[[Datei:Porsche Diesel Master 428 am Waldrand.jpg|thumb||Porsche Diesel Master 428]]
* [[Traktorenlexikon: Porsche-Diesel Master N408|Master 408]], 3/1958-1960, 7V+1R
* [[Traktorenlexikon: Porsche-Diesel Master N418|Master 418]], 4/1960-12/1960, (2V+1R)*4
* [[Traktorenlexikon: Porsche-Diesel Master N419|Master 419]], 12/1960-07/1963, (2V+1R)*4
* {{:Traktorenlexikon:_Create|Master 428}}, 1961, 5V+1R
* [[Traktorenlexikon: Porsche-Diesel Master V429|Master 429]], 1961-1962, 5V+1R
* {{:Traktorenlexikon:_Create|Master 409}}, 1962-07/1963, 7V+1R
==Literatur==
* {{Literatur
| Autor=Armin Bauer
| Titel=Allgaier und Porsche-Diesel: 1945 - 1962 (Typenkompass)
| Auflage=2.
| Verlag=Motorbuch
| Ort=Obershagen
| Datum=2009
| ISBN=978-3-6130-3097-8
| Seiten=112
}}
* {{Literatur
| Autor=Armin Bauer
| Titel=Porsche-Diesel – Prospekte, Druckschriften, Dokumente
| Auflage=1.
| Verlag=Schwungrad Verlag
| Ort=Obershagen
| Datum=2008
| ISBN=978-3-9334-2621-5
| Seiten=176
}}
* {{Literatur
| Autor=Armin Bauer
| Titel=Allgaier und Porsche-Diesel – Datenbuch aller Schlepper und Motoren
| Auflage=1.
| Verlag=Schwungrad Verlag
| Ort=Obershagen
| Datum=2005
| ISBN=978-3933-42612-3
| Seiten=224
}}
* {{Literatur
| Autor=Armin Bauer
| Titel=Porsche Schlepper 1937 bis 1966
| Auflage=2.
| Verlag=Schwungrad Verlag
| Ort=Obershagen
| Datum=2003
| ISBN=3-933426-11-1
| Seiten=267
}}
* {{Literatur
| Autor=Ulf Kaack
| Titel=Porsche Traktoren - Schlepper von geballter Kraft
| Auflage=1.
| Verlag=Delius Klasing
| Ort=
| Datum=2016
| ISBN=978-3-6671-0692-6
| Seiten=112
}}
* {{Literatur
| Autor=Bernhard Köser
| Titel=Porsche-Diesel Traktoren restaurieren und reparieren
| Auflage=
| Verlag=Eugen Ulmer Verlag
| Ort=Stuttgart
| Datum=2010
| ISBN=978-3-8001-5787-7
| Seiten=207
}}
* {{Literatur
| Autor=Manfred Krämer
| Titel=Porsche-Diesel Traktoren – Mythos & Leidenschaft
| Auflage=
| Verlag=Eugen Ulmer Verlag
| Ort=Stuttgart
| Datum=2010
| ISBN=978-3-8001-5986-4
| Seiten=240
}}
* {{Literatur
| Autor=Albert Mößmer
| Titel=Porsche und Allgaier - Das Typenbuch
| Auflage=
| Verlag=Geramond Verlag
| Ort=München
| Datum=2009
| ISBN=ISBN 978-3-7654-7721-8
| Seiten=192
}}
* {{Literatur
| Autor=Udo Paulitz
| Titel=Porsche Traktoren
| Auflage=1.
| Verlag=KOMET
| Ort=2009
| Datum=2009
| ISBN=978-3-8983-6819-3
| Seiten=144
}}
==Weblinks==
{{Wikipedia1|Porsche-Diesel Motorenbau}}
{{Wikipedia1|Liste der Traktormodelle der Porsche-Diesel-Motorenbau}}
{{Commons|Category:Porsche-Diesel tractors|Porsche-Diesel-Traktoren}}
* [https://www.tractorbook.de/traktoren/porsche/ Technische Daten Porsche Allgaier]
* [http://www.porsche-diesel-classic.de Porsche Diesel Homepage]
* [https://www.pdiesel.fr Porsche Schlepper Teile]
* [https://www.youtube.com/watch?v=TPzUnKhxx6M PORSCHE - Vergessene Traktoren eines Weltkonzerns 2025, 06:09 Min (YouTube)]
{{:Traktorenlexikon: Navigation}}
lzyrd4rqinsso1derb18m6opptp0dhf
Traktorenlexikon: Fendt Farmer 260 S/SA
0
66565
1090837
890775
2026-09-14T18:16:26Z
JoachimKohler-HB
65671
1090837
wikitext
text/x-wiki
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Fendt |HERSTELLER= Fendt}}
{{:Traktorenlexikon: Modell-Infobox
| HERSTELLER = [[Traktorenlexikon: Fendt|Fendt]]
| MODELLREIHE = Farmer 200
| MODELL = Farmer 260 S
| BILD = Fendt Farmer 260S in Niedersachsen (2026).jpg
| BILDBESCHREIBUNG = Fendt Farmer 260 S
| BAUWEISE = Blockbauweise
| PRODUKTIONSBEGINN = 1988
| PRODUKTIONSENDE = 2003 ( A: 2001 )
| STÜCKZAHL = 831 ( A: 2981 )
| EIGENGEWICHT = 2520 ( A: 2770 )
| LÄNGE = 3535
| BREITE = 1880
| HÖHE = 2310
| RADSTAND = 2050
| BODENFREIHEIT = 378 ( A: 332 )
| SPURWEITE =
| SPURWEITE VORNE = 1480 ( A: 1494 )
| SPURWEITE HINTEN = 1502
| WENDERADIUS MIT LENKBREMSE =
| WENDERADIUS OHNE LENKBREMSE = 3600 ( A: 3850 )
| BEREIFUNG VORNE = 7.50-18 ( A: 11.2 R 20 )
| BEREIFUNG HINTEN = 14.9 R 30
| LEISTUNG KW = 44
| LEISTUNG PS = 60
| NENNDREHZAHL = 2400
| ZYLINDER = 3
| HUBRAUM = 3064
| DREHMOMENTANSTIEG = 16
| KRAFTSTOFF = Diesel
| KÜHLSYSTEM = Luftkühlung
| ANTRIEBSTYP = Hinterrad-oder Allradantrieb
| GETRIEBE = 21V/6R
| HÖCHSTGESCHWINDIGKEIT = 40
| KATEGORIESORTIERUNG = Fendt Farmer 260 S
}}
Der '''Farmer 260 S''' ist ein Traktor aus der Farmer-200er Serie von [[Traktorenlexikon: Fendt|Fendt]], der von 1988 bis 2003 gebaut wurde.
==Motor==
* KHD, Typ: F3L 913, luftgekühlter Viertakt-Dreizylinder-Reihen-Dieselmotor mit Direkteinspritzung, hängenden Ventilen, Druckumlaufschmierung durch Zahnradpumpe, Trockenluftfilter mit Vorabscheider, vierfach-gelagerte Kurbelwelle, Motorölkühler, Kaltstarteinrichtung, Kolbenbodenkühlung, elektrischer Filterwächter, Bosch-Kolben-Einspritzpumpe, 5-Loch-Düse, Fliehkraftregler und Axial-Kühlgebläse.
* Technische Bezeichnung = T 296.010 ( 831 Exemplare )
* Technische Bezeichnung, Allrad = T 296.210 ( 2981 Exemplare )
* Leistungsgewicht = 67,4 kg/kW
* Bohrung = 102 mm, Hub = 125 mm
* Verdichtungsverhältnis = 19:1
* Max. Drehmoment = 203 Nm bei 1550 U/min.
* Mittlere Kolbengeschwindigkeit = 10,4 m/s bei 2500 U/min.
* Mittlerer Effektivdruck = 6,89 bar bei 2400 U/min.
==Kupplung==
Trockene Doppelkupplung mit getrennt schaltbarer Zapfwellenkupplung, mechanisch betätigt
* Typ: Fichtel & Sachs-DUT 295 L
==Getriebe==
* Fendt, Vollsynchron-Gruppen-Overdrive-Getriebe mit Seitenschaltung
* Wechselgetriebe mit drei Vorwärts-und einem Rückwärtsgang
* Gruppengetriebe mit Acker-und Straßengruppe
* Feinstufenschaltung in Dreifachsplittung mit den Bereichen: L, M, S
* Drei Overdrive-Schnellgänge ( 25, 30, 40 km/h.)
* Geometrisch abgestufte Vorwärtsgänge mit Geschwindigkeiten von 1,4-40 km/h.
* 21 Vorwärts- und 6 Rückwärtsgänge
Wahlweise als 30 km/h.-Ausführung mit zwei Overdrive-Schnellgänge
* 20 Vorwärts-und 6 Rückwärtsgänge
Optional mit Kriechgruppe
* 30 Vorwärts-und 9 Rückwärtsgänge
==Geschwindigkeiten vor- und rückwärts==
* Höchstgeschwindigkeit vorwärts 40 km/h, rückwärts 17 km/h
* viele einzelne Getriebestufen (langsam, mittel, schnell) und die üblichen Gänge (Hase und Igel)
Ackergruppe/Feinstufe-L
* 1.Gang = 1,40 km/h; 2.Gang = 2,24 km/h; 3.Gang = 3,54 km/h; Rückwärtsgang = 2,03 km/h.
Ackergruppe/Feinstufe-M
* 1.Gang = 1,71 km/h; 2.Gang = 2,73 km/h; 3.Gang = 4,32 km/h; Rückwärtsgang = 2,47 km/h.
Ackergruppe/Feinstufe-S
* 1.Gang = 2,01 km/h; 2.Gang = 3,22 km/h; 3.Gang = 5,09 km/h; Rückwärtsgang = 2,92 km/h.
Straßengruppe/Feinstufe-L
* 1.Gang = 5,60 km/h; 2.Gang = 8,96 km/h; 3.Gang = 14,15 km/h; Rückwärtsgang = 8,11 km/h.
Straßengruppe/Feinstufe-M
* 1.Gang = 6,83 km/h; 2.Gang = 10,93 km/h; 3.Gang = 17,26 km/h; Rückwärtsgang = 9,89 km/h.
Straßengruppe/Feinstufe-S
* 1.Gang = 8,06 km/h; 2.Gang = 12,89 km/h; 3.Gang = 20,35 km/h; Rückwärtsgang = 11,66 km/h.
Overdrive-Schnellgänge
* 1.Gang = 22,98 km/h; 2.Gang = 28,93 km/h; 3.Gang = 35,96 km/h.
==Zapfwelle==
* Unabhängige-lastschaltbare Motorzapfwelle, 1 3/8"-6 Keile
* Zweifach schaltbar, 540 und 750 U/min.
* 540 U/min. bei 2286 U/min.- Motordrehzahl ( Leistung = 54,3 PS ) oder 566 U/min. bei Nenndrehzahl ( Leistung = 55,5 PS )
* 750 U/min. bei 1731 U/min.- Motordrehzahl
* Optional = 540/540E/1000 U/min oder 540/540E/Wegzapfwelle
Optional mit lastschaltbarer Frontzapfwelle
* Antrieb direkt von der Kurbelwelle
* 1000 U/min. bei 2031 U/min.- Motordrehzahl
==Bremsen==
* Hydraulik betätigte Trommelbremse auf die Hinterräder wirkend
* Unabhängige-mechanische Innenbackenbremse als Feststellbremse
* Allradvorderachse mit Kardanwellenbremse
==Achsen==
* Einzelradgefederte Fendt-Pendelachse ( optional mit verstellbarer Spurweite )
* Oder Lenktrieb-Pendelachse, Typ: Dana 214 F SD 50 mit zentralem Antrieb
* Elektromagnetische Allradzuschaltung und Lamellen-Selbstsperrdifferential "Locomatic"
* Automatische Abschaltung des Allradantrieb bei einem Lenkwinkel über 35 Grad
* Achslast vorne = 1160 kg, hinten = 1590 kg
==Lenkung==
hydrostatische Lenkung mit Gleichlaufzylinder, load sensing Ventil zweigt nur bei tatsächlichen Lenkbewegungen die benötigte Ölmenge ab
* Typ: OSPC 70 LSR
==Hydrauliksystem und Kraftheber==
* EHR serienmäßig, EW mit Lage Zugkraft oder Mischregelung und Außenbedienung am linken Kotflügel oder EHL Kraftheber
auf Wunsch Frontkraftheber EW
* Fendt-Regelhydraulik mit elektronischer Hubwerksregelung ( EHR ) und Unterlenkerregelung
* Dreipunktaufhängung mit Schnellkuppler und Dreipunktgestänge der Kategorie II
* Zugkraft-, Lage-und Mischregelung, Schnellaushub, Schnelleinzug, Tiefenregelung und Regelempfindlichkeit
* Senkdrossel zur Regulierung der Absinkgeschwindigkeit und zur Hubhöhengegrenzung
* Unabhängige Zahnrad-Förderpumpe mit Load-Sensing-Ventil
* Fördermenge = 41,5 l/min. bei 150 bar ( max. 176 bar )
* Max. Hubkraft = 2790 kg / Hubweg = 620 mm
Wahlweise, Fendt-Regelhydraulik mit EHL-Hubwerksregelung
* Ohne Schnelleinzug, Tiefenregelung und Zugkraftregelung
Optional mit integrierter Fronthydraulik
* Dreipunktaufhängung der Kategorie II
* Max. Hubkraft = 1060 daN / Hubweg = 590 mm
==Steuergeräte==
* Serienmäßig mit einem einfachwirkendem Steuerventil
* Optional, 5 Zusatzsteuerventile ( drei einfachwirkende-und zwei doppeltwirkende Steuerventile )
4 dw und ein ew mit Mengenregulierung, zwei Ventile über Kreuzschalthebel
==Elektrische Ausrüstung==
* 12 Volt-Einrichtung nach StVZO
* Batterie 12V-88 Ah
* Anlasser 12V-2,7 kW
* Lichtmaschine 14V-55 A, 770 W
==Maße und Abmessungen ==
* Länge = 3535 mm
* Breite mit Serienbereifung = 1880 mm
* Höhe mit Kabine = 2310 mm
* Optionale Spurweitenverstellung, vorne = 1370-1520 mm
==Gewicht==
* Versandgewicht der 40 km/h.-Ausführung = 2370 kg
* Leergewicht der 40 km/h.-Ausführung = 2520 kg
* Versandgewicht der 30 m/h.- Ausführung = 2320 kg
* Leergewicht der 30 km/h.- Ausführung = 2470 kg
* Versandgewicht der Allrad-Ausführung ( 40 km/h.) = 2620 kg
* Leergewicht der Allrad-Ausführung ( 40 km/h.) = 2770 kg
* Zul. Gesamtgewicht = 4000 kg; A = 4.500 kg; seit 1996:5000 kg.
===Bereifung===
* Serienbereifung der Hinterrad-Ausführung, vorne = 7.50-18 ASF, hinten = 14.9 R 30
* Optional vorne = 7.50-20 ASF
* Serienbereifung der Allrad-Ausführung, vorne = 11.2 R 20, hinten = 14.9 R 30
* Optional vorne = 12.4 R 20, hinten = 16.9 R 30
kann man hinten Reifen 11-12,4-32 fahren sind auf meinem Schlepper mo0ntiert. ->Ja, das Reifungskonzept ist sehr breit angelegt, die größten Reifen mit 1,485m sind 16.9R30 (480/70R30); Vorne dann 335/80R20 (405/70R20).
==Füllmengen==
* Kraftstofftank: 60 l
* Motor Ölmenge mit Filter 10 Liter
* Getriebe 26,4 Liter
* Vorderachse 5,5 Liter
* Hinterachsportalantriebe Je 3 Liter
* Hydrauliköl 14 liter
==Verbrauch==
* Optimaler Kraftstoffverbrauch bei Nenndrehzahl = 216 g/kWh oder 159 g/PSh
==Kabine==
* Gummigelagerte Edscha-CSS 066 Sicherheitkabine mit zwei Türen, Komfortsitz, Beifahrersitz, ausstellbare Front-und Heckscheibe, ausstellbare Dachluke, Heizung, digitale Instrumente, dreistufen-Lüftungsgebläse, schwingungsisoliert, schallisoliert 90 db(A)
* Klimaanlage und Schadstofffilter auf Wunsch
==Sonderausrüstung==
* Frontzapfwelle
* Fronthydraulik
* Zusatzsteuergeräte
* Wegzapfwelle
* Zapfwelle 1000 U/min.
* Mähwerk
* Frontlader
* Zwillingsbereifung
* Geschwindigkeitssteckdose
* Dauerstromsteckdose
* Drehgriff am Lenkrad
* Zugpendel
* EHL-System
* Zusatzgewichte
* Kriechgänge
* 30 km/h-Getriebe
* Niedrigdach
* Zusatzbeleuchtung vorne
* Arbeitsscheinwerfer hinten
* Schadstofffilter
==Sonstiges==
* Listenpreis der Hinterrad-Ausführung 1988 = 54.629,- DM
* Listenpreis der Allrad-Ausführung 1988 = 64.752,- DM
==Literatur==
* Fendt, Typen und Daten ( G. Kremer ), Seite 346
* Fendt, Schlepper-Prospekte von 1979 bis 1999 ( G. Kremer ), Seiten 39-50
==Weblinks==
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Fendt |HERSTELLER= Fendt}}
7u9w6ssjqbc5kccz7ov3abn176dksf5
Traktorenlexikon: Steyr 650
0
84356
1090838
1083289
2026-09-15T04:11:05Z
Stef5047
101897
/* */
1090838
wikitext
text/x-wiki
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Steyr |HERSTELLER= Steyr}}
{{:Traktorenlexikon: Modell-Infobox
| HERSTELLER = Steyr-Daimler-Puch
| MODELLREIHE = Plus-Serie
| MODELL = 650 (a)
| BILD = Steyr 650.jpg
| BILDBESCHREIBUNG =
| BAUWEISE = Blockbauweise
| PRODUKTIONSBEGINN = 1971
| PRODUKTIONSENDE = 1977
| STÜCKZAHL =
| EIGENGEWICHT = 2.180 (A: 2.430)
| LÄNGE = 3.510
| BREITE = 1.678
| HÖHE = 2.145
| RADSTAND = 2.125
| BODENFREIHEIT = 400
| SPURWEITE =
| SPURWEITE VORNE = 1.350/1.510 (A: 1.370)
| SPURWEITE HINTEN = 1.350/1.500
| WENDERADIUS MIT LENKBREMSE = 3.430
| WENDERADIUS OHNE LENKBREMSE = 3.910
| BEREIFUNG VORNE = 6.00-16 ASF (A: 7.50-18 AS)
| BEREIFUNG HINTEN = 11-32 AS
| LEISTUNG KW = 36,8
| LEISTUNG PS = 50
| NENNDREHZAHL = 2.200
| ZYLINDER = 4
| HUBRAUM = 3141
| DREHMOMENTANSTIEG = 16
| KRAFTSTOFF = Diesel
| KÜHLSYSTEM = Wasserkühlung
| ANTRIEBSTYP = Heck- oder Allradantrieb
| GETRIEBE = 8V/8R
| HÖCHSTGESCHWINDIGKEIT = 30
| KATEGORIESORTIERUNG = STEYR
}}
Der Steyr Plus 50 gehörte auch zur ersten Generation der Plus-Baureihe, die später auf eine dreistellige Typenbezeichnung umgestellt wurde. Somit wurde der Plus 50 (a) ohne große Änderungen zum Steyr 650 (a). Zeitgleich mit der Umbenennung wechselte die Lage des Auspuffs von unten nach oben. Wie schon beim Steyr 540 wurde während des Produktionszeitraums ein Motor mit gesteigertem Hubraum eingesetzt. Durch den gesteigerten Hubraum konnte bei identischer Leistung die Nenndrehzahl um 200 U/min gesenkt werden.
==Motor==
Steyr, Typ: WD-408.81, stehender wassergekühlter Viertakt-Vierzylinder-Reihen-Saugdieselmotor mit Direkteinspritzverfahren, nasse auswechselbare Zylinderlaufbuchsen, Öl-Spaltfilter, fünffach gelagerte Kurbelwelle, zahnradgetriebene Nockenwelle, hydraulischer Bosch Fliehkraft-Verstellregler, Leichtmetallkolben, hängende Ventile, IFE-Ölbadluftfilter mit Zyklon-Vorfilter, Bosch Verteilereinspritzpumpe, Druckumlaufschmierung mittels Zahnradpumpe, Bosch Mehrloch-Einspritzdüsen, Zweikreis-Wasserkühlung und Thermostat
{|
|-
| Nennleistung: || 50 DIN PS oder 52 SAE PS
|-
| Bohrung: || 100 mm
|-
| Hub: || 100 mm
|-
| Verdichtung: || 16,8:1
|-
| Max. Drehmoment: || 192 Nm bei 1.500 U/min
|-
| Geregelter Drehzahlbereich: || 600 bis 2.400 U/min
|-
| Max. Einspritzdruck: || 215 + 5 bar (Angabe laut Handbuch: 220 + 5 atü (225 atü = 220 bar)
|-
| Verteilereinspritzpumpe: || Bosch, Typ: EP/VA 4/90 H 1 200 BR 144
|-
| Einspritzdüsen: || Bosch, Typ: DLL 150 S 396 oder F.& M. Typ: LMK 150/21
|-
| Ölbadluftfilter: || IFE, Typ: 808-6000 E
|-
|}
==Kupplung==
* Pedalbetätigte, trockene Fichtel & Sachs-Doppelkupplung, Typ: Do 250/250
==Getriebe==
* Im Ölbad laufendes Steyr-Daimler-Puch Gruppen-Wendegetriebe
* Wechselgetriebe mit 4 Vorwärts- und 4 Rückwärtsgängen
* Gruppengetriebe mit 2 Gruppen, in die Bereiche Acker und Straße unterteilt
* 8 Vorwärts- und 8 Rückwärtsgänge, später 16 Vorwärts- und 8 Rückwärtsgänge
* Optional mit 4 Kriechgängen
Gesamtübersetzung:
{| class="wikitable"
|-
! Gruppe || colspan="2" style="text-align:center" | Ackergruppe || colspan="2" style="text-align:center" | Straßengruppe
|-
! Gänge || Vorwärts || Rückwärts || Vorwärts || Rückwärts
|-
| 1. Gang || 356,20:1 || 421,18:1 || 101,94:1 || 120,54:1
|-
| 2. Gang || 202,39:1 || 239,31:1 || 57,92:1 || 68,49:1
|-
| 3. Gang || 123,24:1 || 145,72:1 || 35,27:1 || 41,70:1
|-
| 4. Gang || 72,15:1 || 86,49:1 || 20,93:1 || 24,75:1
|-
|}
==Geschwindigkeiten vor- und rückwärts==
Geschwindigkeiten der Standard-Ausführung mit Bereifung 11-32 AS:
{| class="wikitable"
|-
! Gruppe || colspan="2" style="text-align:center" | Ackergruppe || colspan="3" style="text-align:center" | Straßengruppe
|-
! Gänge || Vorwärts || Rückwärts || Vorwärts || Rückwärts || Kriechgänge
|-
| 1. Gang || 1,61 km/h || 1,36 km/h || 5,63 km/h || 4,76 km/h || 0,34 km/h
|-
| 2. Gang || 2,83 km/h || 2,40 km/h || 9,90 km/h || 8,38 km/h || 0,61 km/h
|-
| 3. Gang || 4,65 km/h || 3,94 km/h || 16,26 km/h || 13,75 km/h || 1,00 km/h
|-
| 4. Gang || 7,84 km/h || 6,63 km/h || 27,40 km/h || 23,17 km/h || 1,68 km/h
|-
|}
==Zapfwelle==
* Unabhängige zweistufige Motorzapfwelle, als gangabhängige Zapfwelle schaltbar
* Stummel: 1 3/8", 6 Keile (Form A)
* Zweifach schaltbar: 540 oder 1.000 U/min
* 583 oder 1.047 U/min bei Nenndrehzahl
* Übertragbare Leistung: 44,7 PS
* Wegzapfwelle nur in der Ackergruppe schaltbar
* Fahrstrecke je Zapfwellenumdrehung: 0,0765 m
* 52,1 Zapfwellenumdrehungen je Radumdrehung
* Optional aufsteckbare Riemenscheibe mit 250 mm Durchmesser und 160 mm Breite
* 916 oder 1.646 U/min bei Nenndrehzahl
* Riemengeschwindigkeit: 720 oder 1.292 m/min
* Übertragbare Leistung: 42,6 PS
* Frontzapfwelle mit direktem Anschluss für Mähwerk
* Stummel: 1 3/8", 6 Keile (Form A)
* 1.047 U/min bei Nenndrehzahl
* Mähantrieb mit 925 U/min
==Bremsen==
* Pedalbetätigte Innenbackenbremse, auf die Hinterräder wirkend, als Einzelradbremse ausgebildet
* Allrad-Ausführung mit hydraulischer Vierradbremse
* Hydraulische Innenbackenbremse, wahlweise auf das rechte oder linke Hinterrad wirkend
* Ein Verteilerventil verhindert das gleichzeitige Bremsen der Vorderräder bei der Einzelradbremsung
* Mechanisch betätigte, unabhängige Feststellbremse
* Max. mittlere Verzögerung: 3,5 m/s² bei 29 kp Pedaldruck (Bremsweg: 7,45 m bei 25 km/h)
* Optional mit Anhänger-Druckluftbremse
==Achsen==
* Pendelnd gelagerte Stahl-Vorderachse, auf Wunsch mit Einzelradfederung
* Zwei Spurweiten mittels Radumschlag: 1.350 oder 1.510 mm
* Optional mit fünffacher Spurverstellung: 1.350, 1.450, 1.550, 1.650 und 1.750 mm
* Allradantrieb mittels Klauenkupplung, unter Last schaltbarer, pendelnd gelagerten Lenktriebachse mit seitlicher Gelenkwelle
* Spurweite: 1.370 mm
* Radeinschlag: 39°
* Auf Wunsch mit hydraulischer Allradbremse
* Starre Portal-Hinterachse mit Kegelradgetriebe
* Mechanisch betätigtes, sperrbares Kegelraddifferential
* Zwei Spurweiten mittels Radumschlag: 1.350 und 1.500 mm
* Optional mit fünffacher Spurverstellung: 1.350, 1.400, 1.450, 1.500, 1.600 und 1.700 mm
* Vordere Achslast: 805 kg (Allrad: 1750kg)
* Hintere Achslast: 1.360 kg (Allrad: 3220 kg)
==Lenkung==
* Mechanische ZF-Gemmerlenkung, Typ: Gd 7340
* Optional als Spindel-Hydrolenkung
==Hydrauliksystem und Kraftheber==
* Hydraulisches Steyr Regelhubwerk mit mechanischer Oberlenkerregelung
* Dreipunktaufhängung der Kategorie I/II mit "Simplematic"
* Bosch Steuergerät, Typ: HY/SR 10 H 2/175/4
* Zweistufige Zugkraftsteuerung, Schwimmstellung und Lageregelung
* Direkt vom Motor angetriebene, kupplungsunabhängige Zahnrad-Hydraulikpumpe
* Max. Förderleistung: 34,0 l/min bei 175 atü
* Max. Hubkraft an der Ackerschiene: 2.400 kg
==Steuergeräte==
* Ein einfachwirkendes Bosch Steuergerät
==Elektrische Ausrüstung==
* 12 Volt Einrichtung nach StVZO
* Zwei Batterien, je 6 V 112 Ah
* Bosch Anlasser, Typ: JD (R) 12 V-3,0 PS
* Bosch Lichtmaschine, Typ: G (R) 14 V-16 A 21
==Maße & Abmessungen==
* Länge: 3.510 mm, mit Frontgewichten: 3.620 mm
* Breite: 1.678 bis 1.800 mm, je nach Spurweite
* Höhe über Lenkrad: 1.534 mm
* Radstand: 2.125 mm
* Bodenfreiheit unter der Vorderachse: 400 mm
* Leergewicht: 2.165 kg
* Zul. Gesamtgewicht: 4.000 kg
==Bereifung==
Standardbereifung:
* Vorn: 6.00-16 AS Front (Allrad: 7.50-18 AS)
* Hinten: 11-32 AS
Optional:
* Vorn: 6.50-16 AS Front
* Hinten: 12.4-32, 13-28, 9-36 oder 11-36 AS
==Füllmengen==
* Tankinhalt: 83 l
* Motoröl: 7 l
* Kühlsystem: 12,4 l
* Ölbadluftfilter: 1 l
* Hinterachse und Getriebe: 33,5 l
* Portalantrieb: je 1,5 l
* Hydraulik: 14 l
==Verbrauch==
* Kraftstoffverbrauch: 10,7 l/h oder 178 g/PSh bei 51,6 PS und Nenndrehzahl
==Kabine==
* Fahrerstand mit Grammer Gesundheitssitz, Typ: SF 4000, analoge Anzeigen, Traktormeter, Fernthermometer und linkem Kotflügelsitz
* Optional mit Schutzrahmen oder Kabine, Muschelkotflügel, Arbeitsscheinwerfer und rechtem Kotflügelsitz
==Sonderausrüstung==
* Zusatzgewichte
* Zwillingsbereifung
* Innere Stützstreben für Dreipunktaufhängung
* Arbeitsscheinwerfer
==Literatur==
* Steyr - Das Typenbuch (Albert Mößmer), Seite 66
==Weblinks==
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Steyr|HERSTELLER= Steyr}}
npxwi5l9fjjf2lmm3lhd3ehscj7u294
Vokabeltexte Chinesisch/ Vokabellektionen/ Lektion 558
0
100974
1090852
1012661
2026-09-15T11:19:19Z
Christian-bauer
6469
kleinere Ergänzungen und Korrekturen
1090852
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor|
zurücktext=Lektion 557|
zurücklink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 557|
hochtext=Buch Vokabellektionen|
hochlink=Vokabeltexte_Chinesisch/_Vokabellektionen|
vortext=Lektion 559|
vorlink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 559}}
</noinclude>
== Zeichen ==
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung !! Lernhilfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |貌}} || mao4 || Anschein, Erscheinung, Aussehen || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=貌}}
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒}} || ju4 || ablehnen, abweisen, abstoßen, erwehren, abwehren, widerstehen, widersetzen || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=拒}}
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |犮}} || ba2 || Form eines rennenden Hundes, Variante von 跋: auf etwas treten, Variante von 拔: ziehen || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=犮}}
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髟}} || biao1 || Radikal Nr. 190 = lange Haare, langes Haar, zottig || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=髟}} [[Datei:髟-bronze-shang.svg|40px]][[Datei:髟-silk.svg|40px]][[Datei:髟-seal.svg|40px]]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮}} || fa1 || (traditionelle Schreibweise von 发), (ab)senden, ausstrahlen, schicken, aufbrechen, abfeuern, schießen, äußern, erzeugen, hervorbringen, quellen lassen, keimen, enthüllen, aufdecken, entdecken, empfinden, Haare || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=髮}}
|}
== Zusammengesetzte Wörter ==
=== 貌 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung !! Lernhilfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |风貌}} || feng1 mao4 || Stil und Merkmale, Erscheinungsbild, Aspekt || (HSK 3.0 Band 7-9)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |全貌}} || quan2 mao4 || Panorama
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |貌似}} || mao4 si4 || anscheinend
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |美貌}} || mei3 mao4 || ansehnlich, Schönheit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |面貌}} || mian4 mao4 || Anschein, Erscheinungsbild, Aussehen, Antlitz, besondere Eigenschaften, Besonderheiten, Gesicht, Visage || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |形貌}} || xing2 mao4 || Aussehen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |外貌}} || wai4 mao4 || Erscheinung, Aussehen || (HSK 3.0 Band 7-9)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |礼貌}} || li3 mao4 || Höflichkeit, Manieren || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |禮貌}} || li3 mao4 || (traditionelle Schreibweise von 礼貌), Höflichkeit, Manieren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |体貌}} || ti3 mao4 || Äußeres
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |體貌}} || ti3 mao4 || (traditionelle Schreibweise von 体貌), Äußeres
|-
| rowspan='2'| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |相貌}} || xiang4 mao4 || Äußere, Gesichtszug
|-
| xiang4 mao5 || [Äußere; Gesichtszug]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |原貌}} || yuan2 mao4 || ursprüngliches Aussehen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |容貌}} || rong2 mao4 || Anschein, Antlitz, Äußere, Gesicht, Gesichtszug, Visage
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |概貌}} || gai4 mao4 || Überblick, überblicken
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |地貌学}} || di4 mao4 xue2 || Geomorphologie
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |地貌學}} || di4 mao4 xue2 || (traditionelle Schreibweise von 地貌学), Geomorphologie
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不礼貌}} || bu4 li3 mao4 || unehrenhaft, unerzogen, unhöflich, unschicklich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不禮貌}} || bu4 li3 mao4 || (traditionelle Schreibweise von 不礼貌), unehrenhaft, unerzogen, unhöflich, unschicklich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有礼貌}} || you3 li3 mao4 || Höflichkeit, Zuvorkommenheit, Manieren haben, höflich, zuvorkommend, freundlich, manierlich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有禮貌}} || you3 li3 mao4 || (traditionelle Schreibweise von 有礼貌), Höflichkeit, Zuvorkommenheit, Manieren haben, höflich, zuvorkommend, freundlich, manierlich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |无礼貌}} || wu2 li3 mao4 || Freiheit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |無禮貌}} || wu2 li3 mao4 || (traditionelle Schreibweise von 无礼貌), Freiheit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |沒礼貌}} || mei2 li3 mao4 || keine Manieren haben
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |沒禮貌}} || mei2 li3 mao4 || (traditionelle Schreibweise von 沒礼貌), keine Manieren haben
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |面貌一新}} || mian4 mao4 yi1 xin1 || mausern
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人为地貌}} || ren2 wei2 di4 mao4 || künstliche Geländebeschaffenheit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人為地貌}} || ren2 wei2 di4 mao4 || (traditionelle Schreibweise von 人为地貌), künstliche Geländebeschaffenheit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |貌合神离}} || mao4 he2 shen2 li2 || nur dem Anschein nach eine tiefe Gemeinsamkeit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |貌合神離}} || mao4 he2 shen2 li2 || (traditionelle Schreibweise von 貌合神离), nur dem Anschein nach eine tiefe Gemeinsamkeit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |其貌不扬}} || qi2 mao4 bu4 yang2 || unansehnlich, keine auffallende Erscheinung sein
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |花容月貌}} || hua1 rong2 yue4 mao4 || sehr schön
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |生活风貌}} || sheng1 huo2 feng1 mao4 || Lebensstil
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |生活風貌}} || sheng1 huo2 feng1 mao4 || (traditionelle Schreibweise von 生活风貌), Lebensstil
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |男才女貌}} || nan2 cai2 nü3 mao4 || "tolles Paar"
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |才貌出众}} || cai2 mao4 chu1 zhong4 || außergewöhnliches Talent und hervorragendes Aussehen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |才貌出眾}} || cai2 mao4 chu1 zhong4 || (traditionelle Schreibweise von 才貌出众), außergewöhnliches Talent und hervorragendes Aussehen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不礼貌地}} || bu4 li3 mao4 de5 || unhöflich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不禮貌地}} || bu4 li3 mao4 de5 || (traditionelle Schreibweise von 不礼貌地), unhöflich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |城市的貌}} || cheng2 shi4 de5 mao4 || Gesicht der Stadt
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |政治面貌}} || zheng4 zhi4 mian4 mao4 || Zugehörigkeit zu Parteien und Organisationen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |以貌取人}} || yi3 mao4 qu3 ren2 || Leute nach dem Äußeren beurteilen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |合乎礼貌}} || he2 hu1 li3 mao4 || anständig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |合乎禮貌}} || he2 hu1 li3 mao4 || (traditionelle Schreibweise von 合乎礼貌), anständig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |貌似有理}} || mao4 si4 you3 li3 || einleuchtend, leidlich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |郎才女貌}} || lang2 cai2 nü3 mao4 || (perfekt zusammen passende) talentierter Mann und schöne Frau
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人不可貌相}} || ren2 bu4 ke3 mao4 xiang1 || einen Menschen soll man nicht nach seinem Aussehen beurteilen
|}
=== 拒 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung !! Lernhilfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒收}} || ju4 shou1 || Abweisung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒付}} || ju4 fu4 || Nichteinlösung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒斥}} || ju4 chi4 || repulsiv
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝}} || ju4 jue2 || Aberkennung, Abfuhr, Bestreitung, Negation, Nichtanerkennung, Quark, Trotz, Weigerung, missbilligen, rauswerfen, trotzen, versagen, verschließen, verschmähen, verwerfen, weigern, zurückweisen, abschläglich || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒签}} || ju4 qian1 || to refuse (a visa application etc)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒载}} || ju4 zai4 || to refuse to take a passenger (of taxi)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒接}} || ju4 jie1 || to reject, to refuse to take a call
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒保}} || ju4 bao3 || to refuse to insure, to exclude from insurance coverage
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒马}} || ju4 ma3 || cheval de frise (a type of barrier)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒馬}} || ju4 ma3 || (traditionelle Schreibweise von 拒马), cheval de frise (a type of barrier)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |被拒绝}} || bei4 ju4 jue2 || abweisen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝了}} || ju4 jue2 liao3 || abgelehnt, ablehnen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |可拒绝}} || ke3 ju4 jue2 || überquerbar
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝请求}} || ju4 jue2 qing3 qiu2 || Befangenheitsantrag, Ablehnungsgesuch
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝工作}} || ju4 jue2 gong1 zuo4 || Arbeitverweigerung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝证书}} || ju4 jue2 zheng4 shu1 || Protest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒付证书}} || ju4 fu4 zheng4 shu1 || Protest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝支付}} || ju4 jue2 zhi1 fu4 || Zahlungsverweigerung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒兑声明}} || ju4 dui4 sheng1 ming2 || Protest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝承认}} || ju4 jue2 cheng2 ren4 || dementieren, dementiert
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝会面}} || ju4 jue2 hui4 mian4 || nicht einlassen dürfen, ein Treffen ablehnen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒付声明}} || ju4 fu4 sheng1 ming2 || Protest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒付聲明}} || ju4 fu4 sheng1 ming2 || (traditionelle Schreibweise von 拒付声明), Protest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒付通知}} || ju4 fu4 tong1 zhi1 || Zahlungsverweigerung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝验收}} || ju4 jue2 yan4 shou1 || Abnahmeverweigerung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝被拆迁}} || ju4 jue2 bei4 chai1 qian1 || sich der Umsiedlung widersetzen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |侮辱性的拒绝}} || wu3 ru4 xing4 de5 ju4 jue2 || Verschmähung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拒绝求职申请}} || ju4 jue2 qiu2 zhi2 shen1 qing3 || eine Bewerbung ablehnen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你申请签证被拒}} || ni3 shen1 qing3 qian1 zheng4 bei4 ju4 || Ihr Antrag auf ein Visum ist abgelehnt worden.
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |票据拒付证明书}} || piao4 ju4 ju4 fu4 zheng4 ming2 shu1 || Protest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你被拒绝进入德国}} || ni3 bei4 ju4 jue2 jin4 ru4 de2 guo2 || ist ihre Einreise in die BRD abgelehnt worden
|}
=== 髮 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |剪髮}} || jian3 fa3 || (traditionelle Schreibweise von 剪发), Haare schneiden
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |直髮}} || zhi2 fa4 || (traditionelle Schreibweise von 直发), glattes Haar
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮網}} || fa4 wang3 || (traditionelle Schreibweise von 发网), Haarnetz
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |散髮}} || san4 fa1 || (traditionelle Schreibweise von 散发), sich ausbreiten, entsenden
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |美髮}} || mei3 fa3 || (traditionelle Schreibweise von 美发), Haarschnitt
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |卷髮}} || quan2 fa3 || (traditionelle Schreibweise von 卷发), Haarlocke
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |白髮}} || bai2 fa1 || (traditionelle Schreibweise von 白发), graues Haar, weißes Haar, graumeliert, grauhaarig, weißhaarig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮色}} || fa3 se4 || (traditionelle Schreibweise von 发色), Haarfarbe
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮廊}} || fa3 lang2 || (traditionelle Schreibweise von 发廊), Friseuse die der Prostitution nachgeht
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮刷}} || fa4 shua1 || (traditionelle Schreibweise von 发刷), Haarbürste
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |脫髮}} || tuo1 fa4 || (traditionelle Schreibweise von 脱发), Haarausfall
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |削髮}} || xue4 fa3 || (traditionelle Schreibweise von 削发), kahlscheren
|-
| rowspan='2'| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮}} || tou2 fa3 || (traditionelle Schreibweise von 头发), Kopfhaar
|-
| tou2 fa5 || [Haar]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |紅髮}} || hong2 fa4 || (traditionelle Schreibweise von 红发), rothaarig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |長髮}} || chang2 fa4 || (traditionelle Schreibweise von 长发), lange Haare, langes Haar
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |金髮}} || jin1 fa3 || (traditionelle Schreibweise von 金发), blond
|-
| rowspan='2'| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮覺}} || fa1 jue2 || (traditionelle Schreibweise von 发觉), feststellen, merken, entdecken
|-
| fa4 jue2 || [feststellen, merken, entdecken]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮式}} || fa4 shi4 || (traditionelle Schreibweise von 发式), Frisur
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |銀髮}} || yin2 fa3 || (traditionelle Schreibweise von 银发), ergrauen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毛髮}} || mao2 fa3 || (traditionelle Schreibweise von 毛发), Körperbehaarung, Haarwuchs, Haar
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |染髮}} || ran3 fa4 || (traditionelle Schreibweise von 染发), Haare färben
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |假髮}} || jia3 fa4 || (traditionelle Schreibweise von 假发), Perücke
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮夾}} || fa4 jia1 || (traditionelle Schreibweise von 发夹), Haarspange
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮}} || li3 fa4 || (traditionelle Schreibweise von 理发), Haare schneiden, frisieren, Friseur
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮館}} || li3 fa4 guan3 || (traditionelle Schreibweise von 理发馆), Friseursalon
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |梳頭髮}} || shu1 tou2 fa5 || (traditionelle Schreibweise von 梳头发), die Haare kämmen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |洗髮精}} || xi3 fa3 jing1 || (traditionelle Schreibweise von 洗发精), Shampoo, Haarwaschmittel (Konzentrat)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |潤髮精}} || run4 fa3 jing1 || (traditionelle Schreibweise von 润发精), Spülung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮師}} || li3 fa4 shi1 || (traditionelle Schreibweise von 理发师), Friseur
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |洗髮露}} || xi3 fa4 lu4 || (traditionelle Schreibweise von 洗发露), Haarshampoo
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |剪頭髮}} || jian3 tou2 fa5 || (traditionelle Schreibweise von 剪头发), Haare schneiden
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |洗頭髮}} || xi3 tou2 fa5 || (traditionelle Schreibweise von 洗头发), Haarwäsche, Haarewaschen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |髮網袋}} || fa4 wang3 dai4 || (traditionelle Schreibweise von 发网袋), Haarnetz
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |美髮師}} || mei3 fa4 shi1 || (traditionelle Schreibweise von 美发师), Friseur
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮器}} || li3 fa4 qi4 || (traditionelle Schreibweise von 理发器), Haarschneidemaschine
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |馬尾髮}} || ma3 wei3 fa3 || (traditionelle Schreibweise von 马尾发), Pferdeschwanz, Zopf
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吹頭髮}} || chui1 tou2 fa5 || (traditionelle Schreibweise von 吹头发), Haare föhnen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮店}} || li3 fa4 dian4 || (traditionelle Schreibweise von 理发店), Friseurladen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮点}} || li3 fa3 dian4 || (traditionelle Schreibweise von 理发点), Friseursalon
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |令人髮指}} || ling4 ren2 fa3 zhi3 || (traditionelle Schreibweise von 令人发指), schändlich, empörend
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |美容美髮}} || mei3 rong2 mei3 fa3 || (traditionelle Schreibweise von 美容美发), Frisieren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |未被髮覺}} || wei4 bei4 fa4 jue2 || (traditionelle Schreibweise von 未被发觉), unbemerkt
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮顏色}} || tou2 fa5 yan2 se4 || (traditionelle Schreibweise von 头发颜色), Haarfarbe
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮再生}} || tou2 fa5 zai4 sheng1 || (traditionelle Schreibweise von 头发再生), Nachwuchs
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |令人髮怒}} || ling4 ren2 fa4 nu4 || (traditionelle Schreibweise von 令人发怒), ärgern
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮灰白}} || tou2 fa5 hui1 bai2 || (traditionelle Schreibweise von 头发灰白), ergrauen, grauhaarig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |卷髮夾子}} || juan3 fa4 jia1 zi5 || (traditionelle Schreibweise von 卷发夹子), Lockenwickler
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |灰白頭髮}} || hui1 bai2 tou2 fa3 || (traditionelle Schreibweise von 灰白头发), grau
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |金髮女郎}} || jin1 fa3 nü3 lang2 || (traditionelle Schreibweise von 金发女郎), Blonde, Blondine
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮蓬亂}} || tou2 fa5 peng2 luan4 || (traditionelle Schreibweise von 头发蓬乱), zerzausen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |長髮公主}} || chang2 fa4 gong1 zhu3 || (traditionelle Schreibweise von 长发公主), Rapunzel (Märchen der Gebrüder Grimm))
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |未被髮現}} || wei4 bei4 fa4 xian4 || (traditionelle Schreibweise von 未被发现), unbeobachtet
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |長髮姑娘}} || chang2 fa4 gu1 niang5 || (traditionelle Schreibweise von 长发姑娘), Rapunzel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不會被髮現}} || bu4 hui4 bei4 fa4 xian4 || (traditionelle Schreibweise von 不会被发现), unauffindbar
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮亂蓬蓬}} || tou2 fa3 luan4 peng2 peng2 || (traditionelle Schreibweise von 头发乱蓬蓬), wie ein Struwwelpeter
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮的保養}} || tou2 fa3 de5 bao3 yang3 || (traditionelle Schreibweise von 头发的保养), Haarpflege
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |把頭髮束起來}} || ba3 tou2 fa1 shu4 qi3 lai2 || (traditionelle Schreibweise von 把头发束起来), das Haar festbinden, das Haar zu einen Zopf binden, das Haar zum Pferdeschwanz binden
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |塞維利亞的理髮師}} || sai1 wei2 li4 ya4 de5 li3 fa3 shi1 || (traditionelle Schreibweise von 塞维利亚的理发师), Il Barbiere di Siviglia
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |魔鬼頭上的三根金髮}} || mo2 gui3 tou2 shang4 de5 san1 gen1 jin1 fa3 || (traditionelle Schreibweise von 魔鬼头上的三根金发), Der Teufel mit den drei goldenen Haaren)
|}
== Sätze ==
=== 貌 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在吃饭的时候说话是不礼貌的行为。}} || zai4 chi1 fan4 de5 shi2 hou4 shuo1 hua4 shi4 bu4 li3 mao4 de5 hang2/xing2 wei2/wei4 。|| Es ist unhöflich, beim Essen zu reden. (Mandarin, [https://tatoeba.org/eng/sentences/show/8798301 Tatoeba] [https://tatoeba.org/eng/user/profile/crescat crescat] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吃饭时发出声音是不礼貌的。}} || chi1 fan4 shi2 fa1 chu1 sheng1 yin1 shi4 bu4 li3 mao4 de5 。|| It is bad manners to make a noise while you eat. (Mandarin, [https://tatoeba.org/eng/sentences/show/2075160 Tatoeba] [https://tatoeba.org/eng/user/profile/fercheung fercheung])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他一點禮貌也沒有。}} || ta1 yi1 dian3 li3 mao4 ye3 mei2/mo4 you3 。|| Er hat überhaupt keine Manieren. (Mandarin, [https://tatoeba.org/eng/sentences/show/802024 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/wolfgangth wolfgangth])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她是礼貌的化身。}} || ta1 shi4 li3 mao4 de5 hua4 shen1 。|| She is politeness itself. (Mandarin, [https://tatoeba.org/eng/sentences/show/875044 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他们认为,去反驳一个不认识的人有些不礼貌。}} || ta1 men5 ren4 wei2/wei4 , qu4 fan3 驳 yi1 ge4 bu4 ren4 zhi4 de5 ren2 you3 xie1 bu4 li3 mao4 。|| Sie finden es unhöflich, jemandem zu widersprechen, den sie nicht gut kennen. (Mandarin, [https://tatoeba.org/eng/sentences/show/2052135 Tatoeba] [https://tatoeba.org/eng/user/profile/Gustav249 Gustav249] [https://tatoeba.org/eng/user/profile/Fingerhut Fingerhut])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她很有礼貌。}} || ta1 hen3 you3 li3 mao4 。|| Sie hat sehr gute Manieren. (Mandarin, [https://tatoeba.org/eng/sentences/show/623186 Tatoeba] [https://tatoeba.org/eng/user/profile/xiuqin xiuqin] [https://tatoeba.org/eng/user/profile/meloncurtains meloncurtains])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |Tom没有礼貌。}} || Tom mei2/mo4 you3 li3 mao4 。|| Tom hat keine Manieren. (Mandarin, [https://tatoeba.org/eng/sentences/show/346464 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MikeMolto MikeMolto])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你至少可以试着多一点礼貌,即使那不是你的本质。}} || ni3 zhi4 shao3 ke3/ke4 yi3 shi4 zhao2/zhe2 duo1 yi1 dian3 li3 mao4 , ji2 shi3/shi4 na4/nei4 bu4 shi4 ni3 de5 ben3 zhi4 。|| Du könntest zumindest versuchen, ein bisschen höflicher zu sein, auch wenn das nicht in deiner Natur liegt. (Mandarin, [https://tatoeba.org/eng/sentences/show/334701 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你回答得这麼简短,不觉得有点没礼貌吗?}} || ni3 hui2 da2 de2/de5/dei3 zhe4/zhei4 me5 jian3 duan3 , bu4 jiao4/jue2 de2/de5/dei3 you3 dian3 mei2/mo4 li3 mao4 ma5 ?|| Don't you think it's rude to give people such a curt reply like that? (Mandarin, [https://tatoeba.org/eng/sentences/show/542602 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在音樂會中講話是不禮貌的。}} || zai4 yin1 le4/yue4 hui4 zhong1/zhong4 jiang3/jiang5 hua4 shi4 bu4 li3 mao4 de5 。|| Es ist unhöflich, sich während eines Konzerts zu unterhalten. (Mandarin, [https://tatoeba.org/eng/sentences/show/894413 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你应该试著更有礼貌。}} || ni3 ying1/ying4 gai1 shi4 zhao1/zhu4/zhuo2 geng4 you3 li3 mao4 。|| Du solltest versuchen, höflicher zu sein. (Mandarin, [https://tatoeba.org/eng/sentences/show/902943 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你不应该以貌取人。}} || ni3 bu4 ying1/ying4 gai1 yi3 mao4 qu3 ren2 。|| Du solltest einen Menschen nicht aufgrund seines Aussehens beurteilen. (Mandarin, [https://tatoeba.org/eng/sentences/show/373182 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Plusquamperfekt Plusquamperfekt])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在音樂會中說話是不禮貌的。}} || zai4 yin1 le4/yue4 hui4 zhong1/zhong4 shuo1 hua4 shi4 bu4 li3 mao4 de5 。|| Es ist unhöflich, sich während eines Konzerts zu unterhalten. (Mandarin, [https://tatoeba.org/eng/sentences/show/874522 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不要被外貌蒙蔽了。}} || bu4 yao4 bei4 wai4 mao4 meng2 蔽 le5 。|| Der Schein trügt. Der Eindruck täuscht. (Mandarin, [https://tatoeba.org/eng/sentences/show/4517819 Tatoeba] [https://tatoeba.org/eng/user/profile/yuiyu yuiyu] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern] [https://tatoeba.org/eng/user/profile/jast jast])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的容貌改变了许多。}} || ta1 de5 rong2 mao4 gai3 bian4 le5 xu3 duo1 。|| Sein Aussehen hat sich sehr verändert. (Mandarin, [https://tatoeba.org/eng/sentences/show/334283 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/tatomeimei tatomeimei])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的美貌会随着时间而流逝。}} || ta1 de5 mei3 mao4 hui4 sui2 zhao2/zhe2 shi2 jian1 er2 liu2 shi4 。|| Ihre Schönheit wird mit der Zeit vergehen. (Mandarin, [https://tatoeba.org/eng/sentences/show/764041 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Zaghawa Zaghawa])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |從這塔上可以看到城市的全貌。}} || cong2 zhe4/zhei4 ta3 shang4 ke3/ke4 yi3 kan4 dao4 cheng2 shi4 de5 quan2 mao4 。|| Dieser Turm ermöglicht einen Rundblick über die Stadt. (Mandarin, [https://tatoeba.org/eng/sentences/show/366825 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你的礼貌不是很好。}} || ni3 de5 li3 mao4 bu4 shi4 hen3 hao3 。|| Your manners aren't very good. (Mandarin, [https://tatoeba.org/eng/sentences/show/842320 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在音乐会中说话是不礼貌的。}} || zai4 yin1 le4/yue4 hui4 zhong1/zhong4 shuo1 hua4 shi4 bu4 li3 mao4 de5 。|| Es ist unhöflich, sich während eines Konzerts zu unterhalten. (Mandarin, [https://tatoeba.org/eng/sentences/show/874522 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你不應該以貌取人。}} || ni3 bu4 ying1/ying4 gai1 yi3 mao4 qu3 ren2 。|| Du solltest einen Menschen nicht aufgrund seines Aussehens beurteilen. (Mandarin, [https://tatoeba.org/eng/sentences/show/373182 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Plusquamperfekt Plusquamperfekt])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |信息不是知识,知识不是智慧,智慧不是真相,真相不是美貌,美貌不是爱,爱不是音乐,音乐是最好的。}} || xin4 xi1 bu4 shi4 zhi1 zhi4 , zhi1 zhi4 bu4 shi4 zhi4 hui4 , zhi4 hui4 bu4 shi4 zhen1 xiang1/xiang4 , zhen1 xiang1/xiang4 bu4 shi4 mei3 mao4 , mei3 mao4 bu4 shi4 ai4 , ai4 bu4 shi4 yin1 le4/yue4 , yin1 le4/yue4 shi4 zui4 hao3 de5 。|| Information ist kein Wissen, Wissen ist keine Weisheit, Weisheit ist keine Wahrheit, Wahrheit ist keine Schönheit, Schönheit ist keine Liebe, Liebe ist keine Musik, Musik ist am besten. (Mandarin, [https://tatoeba.org/eng/sentences/show/9007592 Tatoeba] [https://tatoeba.org/eng/user/profile/jacintoo jacintoo] [https://tatoeba.org/eng/user/profile/alik_farber alik_farber])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在音乐会中讲话是不礼貌的。}} || zai4 yin1 le4/yue4 hui4 zhong1/zhong4 jiang3/jiang5 hua4 shi4 bu4 li3 mao4 de5 。|| Es ist unhöflich, sich während eines Konzerts zu unterhalten. (Mandarin, [https://tatoeba.org/eng/sentences/show/894413 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她是禮貌的化身。}} || ta1 shi4 li3 mao4 de5 hua4 shen1 。|| She is politeness itself. (Mandarin, [https://tatoeba.org/eng/sentences/show/875044 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你的禮貌不是很好。}} || ni3 de5 li3 mao4 bu4 shi4 hen3 hao3 。|| Your manners aren't very good. (Mandarin, [https://tatoeba.org/eng/sentences/show/842320 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |开口要有礼貌,不讲下流话。}} || kai1 kou3 yao4 you3 li3 mao4 , bu4 jiang3/jiang5 xia4 liu2 hua4 。|| One must be respectful when speaking, and not say obscene things. (Mandarin, [https://tatoeba.org/eng/sentences/show/421250 Tatoeba] [https://tatoeba.org/eng/user/profile/sysko sysko] [https://tatoeba.org/eng/user/profile/minshirui minshirui])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |否则,用左手传递食物会被认为是不礼貌的,因为左手是用来洗澡的。}} || pi3 ze2 , yong4 zuo3 shou3 chuan2/zhuan4 di4 shi2 wu4 hui4 bei4 ren4 wei2/wei4 shi4 bu4 li3 mao4 de5 , yin1 wei2/wei4 zuo3 shou3 shi4 yong4 lai2 xi3/xian3 zao3 de5 。|| Otherwise, it is considered impolite to pass food with the left hand, because the left hand is used for bathing. (Mandarin, [https://tatoeba.org/eng/sentences/show/742974 Tatoeba] [https://tatoeba.org/eng/user/profile/GlossaMatik GlossaMatik] [https://tatoeba.org/eng/user/profile/eastasiastudent eastasiastudent])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |就美貌而言,她不比她妹妹差。}} || jiu4 mei3 mao4 er2 yan2 , ta1 bu4 bi4 ta1 mei4 mei4 cha4/chai1 。|| Sie steht ihrer Schwester an Schönheit in nichts nach. (Mandarin, [https://tatoeba.org/eng/sentences/show/10342220 Tatoeba] [https://tatoeba.org/eng/user/profile/DaoSeng DaoSeng] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在中国有一种说法:人不可貌相。}} || zai4 zhong1/zhong4 guo2 you3 yi1 chong2/zhong3/zhong4 shuo1 fa3 : ren2 bu4 ke3/ke4 mao4 xiang1/xiang4 。|| In China sagt man, dass man einen Menschen nicht nach seinem Aussehen beurteilen darf. (Mandarin, [https://tatoeba.org/eng/sentences/show/449218 Tatoeba] [https://tatoeba.org/eng/user/profile/sysko sysko] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人们都以为日本人是讲究礼貌的。}} || ren2 men5 dou1/du1 yi3 wei2/wei4 ri4 ben3 ren2 shi4 jiang3/jiang5 jiu1 li3 mao4 de5 。|| Das japanische Volk wird als höflich betrachtet. (Mandarin, [https://tatoeba.org/eng/sentences/show/1946779 Tatoeba] [https://tatoeba.org/eng/user/profile/bigfatpanda bigfatpanda] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他把座位让给了一个老人,这显示出他很有礼貌。}} || ta1 ba3 zuo4 wei4 rang4 gei3 le5 yi1 ge4 lao3 ren2 , zhe4/zhei4 xian3 shi4 chu1 ta1 hen3 you3 li3 mao4 。|| Er zeigte gute Umgangsformen, als er einem alten Menschen den Platz überließ. (Mandarin, [https://tatoeba.org/eng/sentences/show/847733 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他一点礼貌也没有。}} || ta1 yi1 dian3 li3 mao4 ye3 mei2/mo4 you3 。|| Er hat überhaupt keine Manieren. (Mandarin, [https://tatoeba.org/eng/sentences/show/802024 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/wolfgangth wolfgangth])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的美貌會隨着時間而流逝。}} || ta1 de5 mei3 mao4 hui4 sui2 zhao2/zhe2 shi2 jian1 er2 liu2 shi4 。|| Ihre Schönheit wird mit der Zeit vergehen. (Mandarin, [https://tatoeba.org/eng/sentences/show/764041 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Zaghawa Zaghawa])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |別以貌取人。}} || bie2 yi3 mao4 qu3 ren2 。|| Bewerte Menschen nicht nach ihrem Äußeren. (Mandarin, [https://tatoeba.org/eng/sentences/show/10361418 Tatoeba] [https://tatoeba.org/eng/user/profile/DaoSeng DaoSeng] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人不可貌相,海水不可斗量。}} || ren2 bu4 ke3/ke4 mao4 xiang1/xiang4 , hai3 shui3 bu4 ke3/ke4 dou4 liang2/liang4 。|| You can't judge a person by appearance, just as you can't measure the sea with a pint pot. (Mandarin, [https://tatoeba.org/eng/sentences/show/3664074 Tatoeba] [https://tatoeba.org/eng/user/profile/gleki gleki])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你應該試著更有禮貌。}} || ni3 ying1/ying4 gai1 shi4 zhao1/zhu4/zhuo2 geng4 you3 li3 mao4 。|| Du solltest versuchen, höflicher zu sein. (Mandarin, [https://tatoeba.org/eng/sentences/show/902943 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |Jane又胖、又没礼貌、又烟不离手,可是Ken却觉得她可爱、动人,所谓「爱情是盲目的」,大概就是这个意思了吧。}} || Jane you4 pang4 、 you4 mei2/mo4 li3 mao4 、 you4 yan1/yan5 bu4 li2 shou3 , ke3/ke4 shi4 Ken que4 jiao4/jue2 de2/de5/dei3 ta1 ke3/ke4 ai4 、 dong4 ren2 , suo3 wei4 「 ai4 qing2 shi4 mang2 mu4 de5 」, da4 gai4 jiu4 shi4 zhe4/zhei4 ge4 yi4 si1 le5 ba5 。|| Jane ist fett, primitiv und raucht zu viel. Aber Ken findet sie liebenswert und bezaubernd. Darum sagt man auch: Liebe macht blind. (Mandarin, [https://tatoeba.org/eng/sentences/show/708567 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/virgil virgil])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |从这塔上可以看到城市的全貌。}} || cong2 zhe4/zhei4 ta3 shang4 ke3/ke4 yi3 kan4 dao4 cheng2 shi4 de5 quan2 mao4 。|| Dieser Turm ermöglicht einen Rundblick über die Stadt. (Mandarin, [https://tatoeba.org/eng/sentences/show/366825 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不要以貌取人。}} || bu4 yao4 yi3 mao4 qu3 ren2 。|| Bewerte Menschen nicht nach ihrem Äußeren. (Mandarin, [https://tatoeba.org/eng/sentences/show/345288 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他这个人不讲礼貌。}} || ta1 zhe4/zhei4 ge4 ren2 bu4 jiang3/jiang5 li3 mao4 。|| Er ist ein unhöflicher Mensch. (Mandarin, [https://tatoeba.org/eng/sentences/show/10269064 Tatoeba] [https://tatoeba.org/eng/user/profile/DaoSeng DaoSeng] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他這個人不講禮貌。}} || ta1 zhe4/zhei4 ge4 ren2 bu4 jiang3/jiang5 li3 mao4 。|| Er ist ein unhöflicher Mensch. (Mandarin, [https://tatoeba.org/eng/sentences/show/10269064 Tatoeba] [https://tatoeba.org/eng/user/profile/DaoSeng DaoSeng] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他今天非常礼貌。}} || ta1 jin1 tian1 fei1 chang2 li3 mao4 。|| Er ist heute furchtbar höflich. (Mandarin, [https://tatoeba.org/eng/sentences/show/2394391 Tatoeba] [https://tatoeba.org/eng/user/profile/fenfang557 fenfang557] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你出国的时候学一些当地的礼貌用语还是很有用的。}} || ni3 chu1 guo2 de5 shi2 hou4 xue2 yi1 xie1 dang1/dang4 de4/di4 de5 li3 mao4 yong4 yu3 hai2/huan2 shi4 hen3 you3 yong4 de5 。|| When you go abroad, it is useful to learn at least some polite phrases in the local language. (Mandarin, [https://tatoeba.org/eng/sentences/show/1517484 Tatoeba] [https://tatoeba.org/eng/user/profile/gonnastop gonnastop] [https://tatoeba.org/eng/user/profile/iris iris])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公主的美貌无法形容。}} || gong1 zhu3 de5 mei3 mao4 wu2 fa3 xing2 rong2 。|| Die Prinzessin war von einer unbeschreiblichen Schönheit. (Mandarin, [https://tatoeba.org/eng/sentences/show/512493 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这是因为日本人和美国人对礼貌的观念有所不同。}} || zhe4/zhei4 shi4 yin1 wei2/wei4 ri4 ben3 ren2 he2/he4/huo2 mei3 guo2 ren2 dui4 li3 mao4 de5 guan4 nian4 you3 suo3 bu4 tong2 。|| This is because of the difference between Japanese politeness and American politeness. (Mandarin, [https://tatoeba.org/eng/sentences/show/554635 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/voxbubnya voxbubnya])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那个护士人很好,又有礼貌。}} || na4/nei4 ge4 hu4 shi4 ren2 hen3 hao3 , you4 you3 li3 mao4 。|| Die Krankenschwester ist sehr nett und höflich. (Mandarin, [https://tatoeba.org/eng/sentences/show/463855 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |边吃东西边谈话是非常没有礼貌的。}} || bian1 chi1 dong1 xi1 bian1 tan2 hua4 shi4 fei1 chang2 mei2/mo4 you3 li3 mao4 de5 。|| It is rude to talk when your mouth is full. (Mandarin, [https://tatoeba.org/eng/sentences/show/363532 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用手指点别人不礼貌。}} || yong4 shou3 zhi3 dian3 bie2 ren2 bu4 li3 mao4 。|| Es gehört sich nicht, auf Leute zu zeigen. (Mandarin, [https://tatoeba.org/eng/sentences/show/5091092 Tatoeba] [https://tatoeba.org/eng/user/profile/mirrorvan mirrorvan] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那个没礼貌的人给我留下了很坏的印象。}} || na4/nei4 ge4 mei2/mo4 li3 mao4 de5 ren2 gei3 wo3 liu2 xia4 le5 hen3 huai4 de5 yin4 xiang4 。|| That rude man gave me a bad impression. (Mandarin, [https://tatoeba.org/eng/sentences/show/801935 Tatoeba] [https://tatoeba.org/eng/user/profile/egg0073 egg0073] [https://tatoeba.org/eng/user/profile/mailohilohi mailohilohi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |指著别人是不礼貌的。}} || zhi3 zhao1/zhu4/zhuo2 bie2 ren2 shi4 bu4 li3 mao4 de5 。|| It is rude to point at others. (Mandarin, [https://tatoeba.org/eng/sentences/show/801345 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |這個男孩不懂禮貌。}} || zhe4/zhei4 ge4 nan2 hai2 bu4 dong3 li3 mao4 。|| Dieser Junge kann sich nicht benehmen. (Mandarin, [https://tatoeba.org/eng/sentences/show/894962 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆以前有礼貌的。}} || tang1 mu3 yi3 qian2 you3 li3 mao4 de5 。|| Tom used to be polite. (Mandarin, [https://tatoeba.org/eng/sentences/show/9400800 Tatoeba] [https://tatoeba.org/eng/user/profile/BobbyLee BobbyLee] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那個沒禮貌的人给我留下了很壞的印象。}} || na4/nei4 ge4 mei2/mo4 li3 mao4 de5 ren2 gei3 wo3 liu2 xia4 le5 hen3 huai4 de5 yin4 xiang4 。|| That rude man gave me a bad impression. (Mandarin, [https://tatoeba.org/eng/sentences/show/801935 Tatoeba] [https://tatoeba.org/eng/user/profile/egg0073 egg0073] [https://tatoeba.org/eng/user/profile/mailohilohi mailohilohi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |早睡早起对你的健康和容貌都很有好处。}} || zao3 shui4 zao3 qi3 dui4 ni3 de5 jian4 kang1 he2/he4/huo2 rong2 mao4 dou1/du1 hen3 you3 hao3 chu4 。|| Going to bed early and waking up early is very good both for your health and appearance. (Mandarin, [https://tatoeba.org/eng/sentences/show/5574638 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/WestofEden WestofEden])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用手指別人是不禮貌的。}} || yong4 shou3 zhi3 bie2 ren2 shi4 bu4 li3 mao4 de5 。|| Es ist nicht höflich, mit dem Finger auf andere zu zeigen. (Mandarin, [https://tatoeba.org/eng/sentences/show/894350 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |邊吃東西邊談話是非常沒有禮貌的。}} || bian1 chi1 dong1 xi1 bian1 tan2 hua4 shi4 fei1 chang2 mei2/mo4 you3 li3 mao4 de5 。|| It is rude to talk when your mouth is full. (Mandarin, [https://tatoeba.org/eng/sentences/show/363532 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |礼貌过度是烦人的。}} || li3 mao4 guo4 du4 shi4 fan2 ren2 de5 。|| Excess of politeness is annoying. (Mandarin, [https://tatoeba.org/eng/sentences/show/6089960 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |貌似没有人知道真相。}} || mao4 si4 mei2/mo4 you3 ren2 zhi1 dao4 zhen1 xiang1/xiang4 。|| Es scheint, dass niemand die Wahrheit kannte. (Mandarin, [https://tatoeba.org/eng/sentences/show/9007581 Tatoeba] [https://tatoeba.org/eng/user/profile/jacintoo jacintoo] [https://tatoeba.org/eng/user/profile/landano landano])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |指著別人是不禮貌的。}} || zhi3 zhao1/zhu4/zhuo2 bie2 ren2 shi4 bu4 li3 mao4 de5 。|| It is rude to point at others. (Mandarin, [https://tatoeba.org/eng/sentences/show/801345 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |难看的不是人的外貌,而是人的衣服。}} || nan2/nan4 kan4 de5 bu4 shi4 ren2 de5 wai4 mao4 , er2 shi4 ren2 de5 yi1 fu2 。|| Es ist nicht die Person, die hässlich ist, sondern die Kleidung. (Mandarin, [https://tatoeba.org/eng/sentences/show/891831 Tatoeba] [https://tatoeba.org/eng/user/profile/FeuDRenais FeuDRenais] [https://tatoeba.org/eng/user/profile/Zaghawa Zaghawa])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |马格达莱纳对我很有礼貌。}} || ma3 ge2 da2 lai2 na4 dui4 wo3 hen3 you3 li3 mao4 。|| Magdalena is very polite to me. (Mandarin, [https://tatoeba.org/eng/sentences/show/919652 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |说苗条比说瘦更有礼貌。}} || shuo1 miao2 tiao2 bi4 shuo1 shou4/sou4 geng4 you3 li3 mao4 。|| It's more polite to say thin than skinny. (Mandarin, [https://tatoeba.org/eng/sentences/show/812360 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/darinmex darinmex])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这个男孩不懂礼貌。}} || zhe4/zhei4 ge4 nan2 hai2 bu4 dong3 li3 mao4 。|| Dieser Junge kann sich nicht benehmen. (Mandarin, [https://tatoeba.org/eng/sentences/show/894962 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我觉得最好不要不礼貌。}} || wo3 jiao4/jue2 de2/de5/dei3 zui4 hao3 bu4 yao4 bu4 li3 mao4 。|| Ich denke, es ist am besten, nicht unhöflich zu sein. (Mandarin, [https://tatoeba.org/eng/sentences/show/501334 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |请礼貌些。}} || qing3 li3 mao4 xie1 。|| Bitte seien Sie höflich. (Mandarin, [https://tatoeba.org/eng/sentences/show/1328118 Tatoeba] [https://tatoeba.org/eng/user/profile/vicch vicch] [https://tatoeba.org/eng/user/profile/landano landano])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |美貌只是表面性的东西。}} || mei3 mao4 zhi3 shi4 biao3 mian4 xing4 de5 dong1 xi1 。|| Schönheit ist nur oberflächlich. (Mandarin, [https://tatoeba.org/eng/sentences/show/462034 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我建议,为了礼貌起见,我们尽可能少喝。}} || wo3 jian4 yi4 , wei2/wei4 le5 li3 mao4 qi3 jian4/xian4 , wo3 men5 jin4 ke3/ke4 neng2 shao3 he1 。|| Ich schlage vor, dass wir aus Höflichkeit so wenig wie möglich trinken. (Mandarin, [https://tatoeba.org/eng/sentences/show/4182631 Tatoeba] [https://tatoeba.org/eng/user/profile/ekgermana ekgermana] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用手指别人是不礼貌的。}} || yong4 shou3 zhi3 bie2 ren2 shi4 bu4 li3 mao4 de5 。|| Es ist nicht höflich, mit dem Finger auf andere zu zeigen. (Mandarin, [https://tatoeba.org/eng/sentences/show/894350 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|}
=== 拒 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了我的要求。}} || ta1 ju4 jue2 le5 wo3 de5 yao4 qiu2 。|| Sie lehnte meine Bitte ab. (Mandarin, [https://tatoeba.org/eng/sentences/show/683035 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝接受这笔钱。}} || ta1 ju4 jue2 jie1 shou4 zhe4/zhei4 bi3 qian2 。|| Sie lehnte das Geld ab. (Mandarin, [https://tatoeba.org/eng/sentences/show/851468 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他拒绝相信我们。}} || ta1 ju4 jue2 xiang1/xiang4 xin4 wo3 men5 。|| Er würde uns nicht glauben. (Mandarin, [https://tatoeba.org/eng/sentences/show/785851 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/BraveSentry BraveSentry])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你应该拒绝他的提议的。}} || ni3 ying1/ying4 gai1 ju4 jue2 ta1 de5 ti2 yi4 de5 。|| Du hättest seine Forderung ablehnen sollen. (Mandarin, [https://tatoeba.org/eng/sentences/show/871223 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了我的资助。}} || ta1 ju4 jue2 le5 wo3 de5 zi1 zhu4 。|| Sie lehnte meine finanzielle Unterstützung ab. (Mandarin, [https://tatoeba.org/eng/sentences/show/334379 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝让我帮助她。}} || ta1 ju4 jue2 rang4 wo3 bang1 zhu4 ta1 。|| She refused my offer to help her. (Mandarin, [https://tatoeba.org/eng/sentences/show/894031 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我以为汤姆会拒绝做。}} || wo3 yi3 wei2/wei4 tang1 mu3 hui4 ju4 jue2 zuo4 。|| I thought Tom would refuse to do that. I thought that Tom would refuse to do that. (Mandarin, [https://tatoeba.org/eng/sentences/show/9432363 Tatoeba] [https://tatoeba.org/eng/user/profile/BobbyLee BobbyLee] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |医生们拒绝做第二次手术。}} || yi1 sheng1 men5 ju4 jue2 zuo4 di4 er4 ci4 shou3 shu4 。|| Die Ärzte weigerten sich, eine zweite Operation durchzuführen. (Mandarin, [https://tatoeba.org/eng/sentences/show/1467060 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/Zaghawa Zaghawa])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的建议好像被拒绝了。}} || ta1 de5 jian4 yi4 hao3 xiang4 bei4 ju4 jue2 le5 。|| Her suggestion seems to have been turned down. (Mandarin, [https://tatoeba.org/eng/sentences/show/9962311 Tatoeba] [https://tatoeba.org/eng/user/profile/GlossaMatik GlossaMatik] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他拒绝了我加好友的请求。}} || ta1 ju4 jue2 le5 wo3 jia1 hao3 you3 de5 qing3 qiu2 。|| Er hat meine Freundschaftseinladung abgelehnt. (Mandarin, [https://tatoeba.org/eng/sentences/show/8463553 Tatoeba] [https://tatoeba.org/eng/user/profile/gumblex gumblex] [https://tatoeba.org/eng/user/profile/wolfgangth wolfgangth])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |总统拒绝回答哀个问题。}} || zong3 tong3 ju4 jue2 hui2 da2 ai1 ge4 wen4 ti2 。|| Der Präsident weigerte sich, auf die Frage zu antworten. (Shanghai, [https://tatoeba.org/eng/sentences/show/496427 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/raggione raggione])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你为什么拒绝做?}} || ni3 wei2/wei4 shi2 me5 ju4 jue2 zuo4 ?|| Warum weigerst du dich? (Mandarin, [https://tatoeba.org/eng/sentences/show/9423222 Tatoeba] [https://tatoeba.org/eng/user/profile/BobbyLee BobbyLee] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你拒绝去做,是不是?}} || ni3 ju4 jue2 qu4 zuo4 , shi4 bu4 shi4 ?|| You refused to do that, didn't you? (Mandarin, [https://tatoeba.org/eng/sentences/show/6624737 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你应该直接拒绝他的要求。}} || ni3 ying1/ying4 gai1 zhi2 jie1 ju4 jue2 ta1 de5 yao4 qiu2 。|| You should have refused his request flatly. (Mandarin, [https://tatoeba.org/eng/sentences/show/3068630 Tatoeba] [https://tatoeba.org/eng/user/profile/serendipity42 serendipity42])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他们拒绝了。}} || ta1 men5 ju4 jue2 le5 。|| Sie weigerten sich. (Mandarin, [https://tatoeba.org/eng/sentences/show/6073881 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了他的求婚。}} || ta1 ju4 jue2 le5 ta1 de5 qiu2 hun1 。|| Sie hat seinen Vorschlag abgelehnt. (Mandarin, [https://tatoeba.org/eng/sentences/show/373390 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公司为了削减成本,拒绝让员工自行加班。}} || gong1 si1 wei2/wei4 le5 xiao1/xue1 jian3 cheng2 ben3 , ju4 jue2 rang4 yuan2 gong1 zi4 hang2/xing2 jia1 ban1 。|| In order to cut down on costs, the company refuses to allow employees to work overtime. (Mandarin, [https://tatoeba.org/eng/sentences/show/2440614 Tatoeba] [https://tatoeba.org/eng/user/profile/fenfang557 fenfang557] [https://tatoeba.org/eng/user/profile/szilviez szilviez])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝做他们想要的事。}} || ta1 ju4 jue2 zuo4 ta1 men5 xiang3 yao4 de5 shi4 。|| Sie weigert sich, das zu tun, was sie wollten. (Mandarin, [https://tatoeba.org/eng/sentences/show/891744 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Vortarulo Vortarulo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的回答其实是拒绝。}} || ta1 de5 hui2 da2 qi2 shi2 shi4 ju4 jue2 。|| Seine Antwort war in Wirklichkeit eine Absage. (Mandarin, [https://tatoeba.org/eng/sentences/show/390482 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他没那个胆拒绝我的提议。}} || ta1 mei2/mo4 na4/nei4 ge4 胆 ju4 jue2 wo3 de5 ti2 yi4 。|| Er hat nicht den Mut, meinen Plan abzulehnen. (Mandarin, [https://tatoeba.org/eng/sentences/show/1250620 Tatoeba] [https://tatoeba.org/eng/user/profile/tsayng tsayng] [https://tatoeba.org/eng/user/profile/Haehnchenpaella Haehnchenpaella])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |圣女贞德拒绝放弃相信她听到的声音是来自上帝,而不是其他的。}} || sheng4 nü3/ru3 zhen1 de2 ju4 jue2 fang4 qi4 xiang1/xiang4 xin4 ta1 ting1 dao4 de5 sheng1 yin1 shi4 lai2 zi4 shang4 di4 , er2 bu4 shi4 qi2 ta1 de5 。|| Jeanne d'Arc weigerte sich, ihre Überzeugung zu leugnen, dass die Stimme, die sie hörte, von niemand anderem als Gott war. (Mandarin, [https://tatoeba.org/eng/sentences/show/502990 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/esocom esocom])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我不知道是否该同意或拒绝。}} || wo3 bu4 zhi1 dao4 shi4 pi3 gai1 tong2 yi4 huo4 ju4 jue2 。|| I do not know whether to accept or to refuse. (Mandarin, [https://tatoeba.org/eng/sentences/show/750435 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/pauldhunt pauldhunt])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了他的请求。}} || ta1 ju4 jue2 le5 ta1 de5 qing3 qiu2 。|| Sie wies seine Bitte ab. (Mandarin, [https://tatoeba.org/eng/sentences/show/8387374 Tatoeba] [https://tatoeba.org/eng/user/profile/wangchou wangchou] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你为什麼拒绝了他的提议?}} || ni3 wei2/wei4 shi2 me5 ju4 jue2 le5 ta1 de5 ti2 yi4 ?|| Warum hast du sein Angebot abgelehnt? (Mandarin, [https://tatoeba.org/eng/sentences/show/793199 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/virgil virgil])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我不知道应该接受还是拒绝。}} || wo3 bu4 zhi1 dao4 ying1/ying4 gai1 jie1 shou4 hai2/huan2 shi4 ju4 jue2 。|| Ich weiß nicht, ob ich annehmen oder ablehnen soll. (Mandarin, [https://tatoeba.org/eng/sentences/show/616299 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他拒绝了我的提议。}} || ta1 ju4 jue2 le5 wo3 de5 ti2 yi4 。|| Er lehnte mein Angebot ab. (Mandarin, [https://tatoeba.org/eng/sentences/show/833204 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/wolfgangth wolfgangth])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他向她求婚,但她却拒绝了。}} || ta1 xiang4 ta1 qiu2 hun1 , dan4 ta1 que4 ju4 jue2 le5 。|| Er machte ihr einen Heiratsantrag, sie aber lehnte ab. (Mandarin, [https://tatoeba.org/eng/sentences/show/380311 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Ole Ole])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |伊拒绝跟我采手。}} || yi1 ju4 jue2 gen1 wo3 cai3 shou3 。|| Er weigerte sich, mir die Hand zu geben. (Shanghai, [https://tatoeba.org/eng/sentences/show/1414650 Tatoeba] [https://tatoeba.org/eng/user/profile/U2FS U2FS] [https://tatoeba.org/eng/user/profile/pullnosemans pullnosemans])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了我。}} || ta1 ju4 jue2 le5 wo3 。|| She rejected me. (Mandarin, [https://tatoeba.org/eng/sentences/show/1072748 Tatoeba] [https://tatoeba.org/eng/user/profile/sysko sysko] [https://tatoeba.org/eng/user/profile/konkorde konkorde])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他断然地拒绝让我进去。}} || ta1 duan4 ran2 de4/di4 ju4 jue2 rang4 wo3 jin4 qu4 。|| Er weigert sich schlichtweg, mich hereinzulassen. (Mandarin, [https://tatoeba.org/eng/sentences/show/881554 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/tatomeimei tatomeimei])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你為什麼拒绝了他的提議?}} || ni3 wei2/wei4 shi2 me5 ju4 jue2 le5 ta1 de5 ti2 yi4 ?|| Warum hast du sein Angebot abgelehnt? (Mandarin, [https://tatoeba.org/eng/sentences/show/793199 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/virgil virgil])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你本该拒绝一个那么不公平的提议。}} || ni3 ben3 gai1 ju4 jue2 yi1 ge4 na4/nei4 me5 bu4 gong1 ping2 de5 ti2 yi4 。|| So einen ungerechten Vorschlag hättest du ablehnen sollen. (Mandarin, [https://tatoeba.org/eng/sentences/show/503226 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |尽管政府拒绝承认,它的经济政策还是失败了。}} || jin4 guan3/guan5 zheng4 fu3 ju4 jue2 承 ren4 , ta1/tuo2 de5 jing4 ji4 zheng4 策 hai2/huan2 shi4 shi1 bai4 le5 。|| Auch wenn sich die Regierung weigert, es zuzugeben, ist ihre Wirtschaftspolitik gescheitert. (Mandarin, [https://tatoeba.org/eng/sentences/show/5581646 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |总统拒绝回答那个问题。}} || zong3 tong3 ju4 jue2 hui2 da2 na4/nei4 ge4 wen4 ti2 。|| Der Präsident verweigerte auf diese Frage die Antwort. (Mandarin, [https://tatoeba.org/eng/sentences/show/333537 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Sudajaengi Sudajaengi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了每一项提议。}} || ta1 ju4 jue2 le5 mei3 yi1 xiang4 ti2 yi4 。|| Sie hat alle Vorschläge abgewiesen. (Mandarin, [https://tatoeba.org/eng/sentences/show/2017443 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我找商店经理谈了话,因为他拒绝为那不能用的电视退钱。}} || wo3 zhao3 shang1 dian4 jing4 li3 tan2 le5 hua4 , yin1 wei2/wei4 ta1 ju4 jue2 wei2/wei4 na4/nei4 bu4 neng2 yong4 de5 dian4 shi4 tui4 qian2 。|| I had words with the manager of that store, because he refused to refund my money for the TV set that wasn't operating properly. (Mandarin, [https://tatoeba.org/eng/sentences/show/736542 Tatoeba] [https://tatoeba.org/eng/user/profile/yujianing yujianing])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝回答你的问题。}} || wo3 ju4 jue2 hui2 da2 ni3 de5 wen4 ti2 。|| I refuse to answer your question. (Mandarin, [https://tatoeba.org/eng/sentences/show/1762969 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/szilviez szilviez])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝。}} || wo3 ju4 jue2 。|| Ich muss ablehnen. (Mandarin, [https://tatoeba.org/eng/sentences/show/3813012 Tatoeba] [https://tatoeba.org/eng/user/profile/hongsly hongsly] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |没有人知道他为何拒绝我帮忙。}} || mei2/mo4 you3 ren2 zhi1 dao4 ta1 wei2/wei4 he2 ju4 jue2 wo3 bang1 mang2 。|| Niemand weiß, warum er meine Hilfe ablehnt. (Mandarin, [https://tatoeba.org/eng/sentences/show/4071841 Tatoeba] [https://tatoeba.org/eng/user/profile/egg0073 egg0073] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆拒绝回答任何问题。}} || tang1 mu3 ju4 jue2 hui2 da2 ren4 he2 wen4 ti2 。|| Tom refused to answer any questions. (Mandarin, [https://tatoeba.org/eng/sentences/show/6057847 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |被拒绝是痛苦的。}} || bei4 ju4 jue2 shi4 tong4 ku3 de5 。|| Abgewiesen zu werden schmerzt. (Mandarin, [https://tatoeba.org/eng/sentences/show/6120796 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |此提议好得令人难以拒绝。}} || ci3 ti2 yi4 hao3 de2/de5/dei3 ling4 ren2 nan2/nan4 yi3 ju4 jue2 。|| Das Angebot ist zu gut, um es abzulehnen. (Mandarin, [https://tatoeba.org/eng/sentences/show/815037 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Tamy Tamy])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝被像一个孩子般对待。}} || wo3 ju4 jue2 bei4 xiang4 yi1 ge4 hai2 zi5 ban1 dui4 dai1 。|| Ich weigere mich, wie ein Kind behandelt zu werden. (Mandarin, [https://tatoeba.org/eng/sentences/show/427621 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝了报价。}} || wo3 ju4 jue2 le5 bao4 jia4/jie4 。|| Ich habe das Angebot abgelehnt. (Mandarin, [https://tatoeba.org/eng/sentences/show/804839 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝被你像奴隶一样对待。}} || wo3 ju4 jue2 bei4 ni3 xiang4 nu2 li4 yi1 yang4 dui4 dai1 。|| Ich lasse mich von dir nicht wie einen Sklaven behandeln. (Mandarin, [https://tatoeba.org/eng/sentences/show/796773 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/samueldora samueldora])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝了付款。}} || wo3 ju4 jue2 le5 fu4 kuan3 。|| Ich weigerte mich zu zahlen. (Mandarin, [https://tatoeba.org/eng/sentences/show/4444874 Tatoeba] [https://tatoeba.org/eng/user/profile/shanghainese shanghainese] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆甚至拒绝听我的建议。}} || tang1 mu3 shen4 zhi4 ju4 jue2 ting1 wo3 de5 jian4 yi4 。|| Tom refused to even listen to my suggestions. (Mandarin, [https://tatoeba.org/eng/sentences/show/5611615 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我必须拒绝。}} || wo3 bi4 xu1 ju4 jue2 。|| Ich muss nein sagen. (Mandarin, [https://tatoeba.org/eng/sentences/show/5091270 Tatoeba] [https://tatoeba.org/eng/user/profile/mirrorvan mirrorvan] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆拒绝付账。}} || tang1 mu3 ju4 jue2 fu4 账。|| Tom weigerte sich, die Rechnung zu bezahlen. (Mandarin, [https://tatoeba.org/eng/sentences/show/6103118 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|}
=== 犮 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|}
=== 髟 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|}
=== 髮 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |一個女人的頭髮很長,她的舌頭更長。}} || yi1 ge4 nü3/ru3 ren2 de5 tou2 髮 hen3 chang2/zhang3 , ta1 de5 she2 tou2 geng4 chang2/zhang3 。|| A woman's hair is long; her tongue is longer. (Mandarin, [https://tatoeba.org/eng/sentences/show/845981 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你用哪種洗髮水?}} || ni3 yong4 na3/na5/nei3 chong2/zhong3/zhong4 xi3/xian3 髮 shui3 ?|| Was für ein Shampoo benutzt du? (Mandarin, [https://tatoeba.org/eng/sentences/show/9049761 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在那個時代,男女髮式大體相似。}} || zai4 na4/nei4 ge4 shi2 dai4 , nan2 nü3/ru3 髮 shi4 da4 ti3 xiang1/xiang4 si4 。|| Zu jener Zeit hatten Männer und Frauen ähnliche Frisuren. (Mandarin, [https://tatoeba.org/eng/sentences/show/6475467 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公園裏有一個漂亮的黑髮姑娘。}} || gong1 yuan2 li3 you3 yi1 ge4 piao1/piao3 liang4 de5 hei1 髮 gu1 niang2 。|| Da war eine schöne Frau mit schwarzem Haar im Park. (Mandarin, [https://tatoeba.org/eng/sentences/show/676214 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的頭髮長而美麗。}} || ta1 de5 tou2 髮 chang2/zhang3 er2 mei3 li2/li4 。|| Ihre Haare sind lang und wunderschön. (Mandarin, [https://tatoeba.org/eng/sentences/show/846067 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你想怎麼剪你的頭髮?}} || ni3 xiang3 zen3 me5 jian3 ni3 de5 tou2 髮?|| How do you want your hair cut? (Mandarin, [https://tatoeba.org/eng/sentences/show/885533 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你最好立刻剪頭髮。}} || ni3 zui4 hao3 li4 ke4 jian3 tou2 髮。|| Du solltest dir besser umgehend die Haare schneiden lassen. (Mandarin, [https://tatoeba.org/eng/sentences/show/775818 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你最好立刻剪头髮。}} || ni3 zui4 hao3 li4 ke4 jian3 tou2 髮。|| Du solltest dir besser umgehend die Haare schneiden lassen. (Mandarin, [https://tatoeba.org/eng/sentences/show/775818 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你染过头髮吗?}} || ni3 ran3 guo4 tou2 髮 ma5 ?|| Hast du dir schon mal die Haare gefärbt? (Mandarin, [https://tatoeba.org/eng/sentences/show/6105124 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |即使我們都是金髮,我們的女兒卻頂著一頭紅髮。}} || ji2 shi3/shi4 wo3 men5 dou1/du1 shi4 jin1 髮, wo3 men5 de5 nü3/ru3 er2/er5 que4 頂 zhao1/zhu4/zhuo2 yi1 tou2 hong2 髮。|| Unsere Tochter ist rothaarig, obwohl wir beide weizenblond sind. (Mandarin, [https://tatoeba.org/eng/sentences/show/1261422 Tatoeba] [https://tatoeba.org/eng/user/profile/tsayng tsayng] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你想將頭髮剪成怎樣?}} || ni3 xiang3 jiang1/jiang4 tou2 髮 jian3 cheng2 zen3 yang4 ?|| How do you want your hair cut? (Mandarin, [https://tatoeba.org/eng/sentences/show/885535 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你的头髮太长了。}} || ni3 de5 tou2 髮 tai4 chang2/zhang3 le5 。|| Deine Haare sind zu lang. (Mandarin, [https://tatoeba.org/eng/sentences/show/425414 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |头髮想怎麼弄?}} || tou2 髮 xiang3 zen3 me5 long4 ?|| What kind of hair style would you like? How would you like your hair done? (Mandarin, [https://tatoeba.org/eng/sentences/show/1212085 Tatoeba] [https://tatoeba.org/eng/user/profile/liting liting] [https://tatoeba.org/eng/user/profile/denzel denzel] [https://tatoeba.org/eng/user/profile/richwarm richwarm])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在你出門之前,把你的頭髮梳一梳。}} || zai4 ni3 chu1 men2 zhi1 qian2 , ba3 ni3 de5 tou2 髮 shu1 yi1 shu1 。|| Kämme deine Haare bevor du ausgehst. (Mandarin, [https://tatoeba.org/eng/sentences/show/873286 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Dejo Dejo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你想将头髮剪成怎样?}} || ni3 xiang3 jiang1/jiang4 tou2 髮 jian3 cheng2 zen3 yang4 ?|| How do you want your hair cut? (Mandarin, [https://tatoeba.org/eng/sentences/show/885535 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的头髮长回来了。}} || ta1 de5 tou2 髮 chang2/zhang3 hui2 lai2 le5 。|| Her hair grew back. (Mandarin, [https://tatoeba.org/eng/sentences/show/6145382 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你的头髮很脏。}} || ni3 de5 tou2 髮 hen3 zang1 。|| Dein Haar ist fettig. (Mandarin, [https://tatoeba.org/eng/sentences/show/9510650 Tatoeba] [https://tatoeba.org/eng/user/profile/eltacodemex eltacodemex] [https://tatoeba.org/eng/user/profile/list list])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的頭髮中夾有白髮。}} || ta1 de5 tou2 髮 zhong1/zhong4 jia1/jia2 you3 bai2 髮。|| Her hair is streaked with gray. (Mandarin, [https://tatoeba.org/eng/sentences/show/846048 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |一个女人的头髮很长,她的舌头更长。}} || yi1 ge4 nü3/ru3 ren2 de5 tou2 髮 hen3 chang2/zhang3 , ta1 de5 she2 tou2 geng4 chang2/zhang3 。|| A woman's hair is long; her tongue is longer. (Mandarin, [https://tatoeba.org/eng/sentences/show/845981 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在那个时代,男女髮式大体相似。}} || zai4 na4/nei4 ge4 shi2 dai4 , nan2 nü3/ru3 髮 shi4 da4 ti3 xiang1/xiang4 si4 。|| Zu jener Zeit hatten Männer und Frauen ähnliche Frisuren. (Mandarin, [https://tatoeba.org/eng/sentences/show/6475467 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公園裏有一個漂亮的黑髮女孩。}} || gong1 yuan2 li3 you3 yi1 ge4 piao1/piao3 liang4 de5 hei1 髮 nü3/ru3 hai2 。|| Ein hübsches Mädchen mit schwarzen Haaren war im Park. (Mandarin, [https://tatoeba.org/eng/sentences/show/672310 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/a_coder a_coder])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你的頭髮太長了。}} || ni3 de5 tou2 髮 tai4 chang2/zhang3 le5 。|| Deine Haare sind zu lang. (Mandarin, [https://tatoeba.org/eng/sentences/show/425414 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在你出门之前,把你的头髮梳一梳。}} || zai4 ni3 chu1 men2 zhi1 qian2 , ba3 ni3 de5 tou2 髮 shu1 yi1 shu1 。|| Kämme deine Haare bevor du ausgehst. (Mandarin, [https://tatoeba.org/eng/sentences/show/873286 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Dejo Dejo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他有長頭髮。}} || ta1 you3 chang2/zhang3 tou2 髮。|| Er hat langes Haar. (Mandarin, [https://tatoeba.org/eng/sentences/show/770360 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你染過頭髮嗎?}} || ni3 ran3 guo4 tou2 髮 ma5 ?|| Hast du dir schon mal die Haare gefärbt? (Mandarin, [https://tatoeba.org/eng/sentences/show/6105124 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公园里有一个漂亮的黑髮姑娘。}} || gong1 yuan2 li3 you3 yi1 ge4 piao1/piao3 liang4 de5 hei1 髮 gu1 niang2 。|| Da war eine schöne Frau mit schwarzem Haar im Park. (Mandarin, [https://tatoeba.org/eng/sentences/show/676214 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你用哪种洗髮水?}} || ni3 yong4 na3/na5/nei3 chong2/zhong3/zhong4 xi3/xian3 髮 shui3 ?|| Was für ein Shampoo benutzt du? (Mandarin, [https://tatoeba.org/eng/sentences/show/9049761 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公园里有一个漂亮的黑髮女孩。}} || gong1 yuan2 li3 you3 yi1 ge4 piao1/piao3 liang4 de5 hei1 髮 nü3/ru3 hai2 。|| Ein hübsches Mädchen mit schwarzen Haaren war im Park. (Mandarin, [https://tatoeba.org/eng/sentences/show/672310 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/a_coder a_coder])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的头髮长而美丽。}} || ta1 de5 tou2 髮 chang2/zhang3 er2 mei3 li2/li4 。|| Ihre Haare sind lang und wunderschön. (Mandarin, [https://tatoeba.org/eng/sentences/show/846067 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他有长头髮。}} || ta1 you3 chang2/zhang3 tou2 髮。|| Er hat langes Haar. (Mandarin, [https://tatoeba.org/eng/sentences/show/770360 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你在哪裡剪头髮?}} || ni3 zai4 na3/na5/nei3 li3 jian3 tou2 髮?|| Wo hast du dir die Haare schneiden lassen? (Mandarin, [https://tatoeba.org/eng/sentences/show/894963 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我不明白为什麼他全秃还要去理髮店。}} || wo3 bu4 ming2 bai2 wei2/wei4 shi2 me5 ta1 quan2 tu1 hai2/huan2 yao4 qu4 li3 髮 dian4 。|| Ich verstehe nicht, wieso er trotz seiner Vollglatze noch zum Friseur geht. (Mandarin, [https://tatoeba.org/eng/sentences/show/5542964 Tatoeba] [https://tatoeba.org/eng/user/profile/egg0073 egg0073] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的头髮中夹有白髮。}} || ta1 de5 tou2 髮 zhong1/zhong4 jia1/jia2 you3 bai2 髮。|| Her hair is streaked with gray. (Mandarin, [https://tatoeba.org/eng/sentences/show/846048 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |保罗用手从头髮间梳过。}} || bao3 luo1 yong4 shou3 cong2 tou2 髮 jian1 shu1 guo4 。|| Paul ran his hand through his hair. (Mandarin, [https://tatoeba.org/eng/sentences/show/890599 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CN CN])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |保羅用手從頭髮間梳過。}} || bao3 luo2 yong4 shou3 cong2 tou2 髮 jian1 shu1 guo4 。|| Paul ran his hand through his hair. (Mandarin, [https://tatoeba.org/eng/sentences/show/890599 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CN CN])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |即使我们都是金髮,我们的女儿却顶著一头红髮。}} || ji2 shi3/shi4 wo3 men5 dou1/du1 shi4 jin1 髮, wo3 men5 de5 nü3/ru3 er2/er5 que4 ding3 zhao1/zhu4/zhuo2 yi1 tou2 hong2 髮。|| Unsere Tochter ist rothaarig, obwohl wir beide weizenblond sind. (Mandarin, [https://tatoeba.org/eng/sentences/show/1261422 Tatoeba] [https://tatoeba.org/eng/user/profile/tsayng tsayng] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的头髮很长。}} || ta1 de5 tou2 髮 hen3 chang2/zhang3 。|| Er hat langes Haar. Sein Haar ist lang. Er trägt sein Haar lang. (Mandarin, [https://tatoeba.org/eng/sentences/show/368143 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern] [https://tatoeba.org/eng/user/profile/Vortarulo Vortarulo] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你在哪裡剪頭髮?}} || ni3 zai4 na3/na5/nei3 li3 jian3 tou2 髮?|| Wo hast du dir die Haare schneiden lassen? (Mandarin, [https://tatoeba.org/eng/sentences/show/894963 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她的頭髮長回來了。}} || ta1 de5 tou2 髮 chang2/zhang3 hui2 lai2 le5 。|| Her hair grew back. (Mandarin, [https://tatoeba.org/eng/sentences/show/6145382 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的頭髮很長。}} || ta1 de5 tou2 髮 hen3 chang2/zhang3 。|| Er hat langes Haar. Sein Haar ist lang. Er trägt sein Haar lang. (Mandarin, [https://tatoeba.org/eng/sentences/show/368143 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern] [https://tatoeba.org/eng/user/profile/Vortarulo Vortarulo] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你想怎麼剪你的头髮?}} || ni3 xiang3 zen3 me5 jian3 ni3 de5 tou2 髮?|| How do you want your hair cut? (Mandarin, [https://tatoeba.org/eng/sentences/show/885533 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |金髮女郎跟她的心裡医师交谈。}} || jin1 髮 nü3/ru3 lang2/lang4 gen1 ta1 de5 xin1 li3 yi1 shi1 jiao1 tan2 。|| Eine Blondine spricht mit ihrem Psychiater. (Mandarin, [https://tatoeba.org/eng/sentences/show/884735 Tatoeba] [https://tatoeba.org/eng/user/profile/Tajfun Tajfun] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我把我的頭髮剪了。}} || wo3 ba3 wo3 de5 tou2 髮 jian3 le5 。|| Ich habe mir die Haare schneiden lassen. (Mandarin, [https://tatoeba.org/eng/sentences/show/6853182 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮师为他理了头髮。}} || li3 髮 shi1 wei2/wei4 ta1 li3 le5 tou2 髮。|| Der Frisör hat ihm einen Haarschnitt verliehen. (Mandarin, [https://tatoeba.org/eng/sentences/show/868434 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Espi Espi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的汤裡有一根头髮。}} || wo3 de5 tang1 li3 you3 yi1 gen5 tou2 髮。|| Da ist ein Haar in meiner Suppe. (Mandarin, [https://tatoeba.org/eng/sentences/show/801326 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我没剪过他们的头髮。}} || wo3 mei2/mo4 jian3 guo4 ta1 men5 de5 tou2 髮。|| I've never cut their hair. (Mandarin, [https://tatoeba.org/eng/sentences/show/2511515 Tatoeba] [https://tatoeba.org/eng/user/profile/tsayng tsayng] [https://tatoeba.org/eng/user/profile/teek teek])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我要去剪头髮了。}} || wo3 yao4 qu4 jian3 tou2 髮 le5 。|| I want to go and get a haircut. (Mandarin, [https://tatoeba.org/eng/sentences/show/6143659 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Kiwi Kiwi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆每天洗头髮。}} || tang1 mu3 mei3 tian1 xi3/xian3 tou2 髮。|| Tom wäscht sich jeden Tag die Haare. (Mandarin, [https://tatoeba.org/eng/sentences/show/9596139 Tatoeba] [https://tatoeba.org/eng/user/profile/eltacodemex eltacodemex] [https://tatoeba.org/eng/user/profile/raggione raggione])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的白髮越来越多。}} || wo3 de5 bai2 髮 yue4 lai2 yue4 duo1 。|| Ich bekomme immer mehr graue Haare. (Mandarin, [https://tatoeba.org/eng/sentences/show/801396 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那连衣裙很配她的红髮。}} || na4/nei4 lian2 yi1 qun2 hen3 pei4 ta1 de5 hong2 髮。|| Das Kleid passt gut zu ihren roten Haaren. (Mandarin, [https://tatoeba.org/eng/sentences/show/10301651 Tatoeba] [https://tatoeba.org/eng/user/profile/DaoSeng DaoSeng] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我覺得你還是頭髮直下來的時候好看。}} || wo3 jiao4/jue2 de2/de5/dei3 ni3 hai2/huan2 shi4 tou2 髮 zhi2 xia4 lai2 de5 shi2 hou4 hao3 kan4 。|| Ich finde, du hast mit glattem Haar besser ausgesehen. (Mandarin, [https://tatoeba.org/eng/sentences/show/7479898 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我去了理髮店理髮。}} || wo3 qu4 le5 li3 髮 dian4 li3 髮。|| I had my hair cut at a barber's shop. (Mandarin, [https://tatoeba.org/eng/sentences/show/458767 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我沒剪過他們的頭髮。}} || wo3 mei2/mo4 jian3 guo4 ta1 men5 de5 tou2 髮。|| I've never cut their hair. (Mandarin, [https://tatoeba.org/eng/sentences/show/2511515 Tatoeba] [https://tatoeba.org/eng/user/profile/tsayng tsayng] [https://tatoeba.org/eng/user/profile/teek teek])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我根本不喜欢我的头髮。}} || wo3 gen5 ben3 bu4 xi3 欢 wo3 de5 tou2 髮。|| I don't like my hair at all. (Mandarin, [https://tatoeba.org/eng/sentences/show/6059527 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/fanty fanty])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮店还没有开门。}} || li3 髮 dian4 hai2/huan2 mei2/mo4 you3 kai1 men2 。|| Der Friseur hat noch nicht geöffnet. (Mandarin, [https://tatoeba.org/eng/sentences/show/8767468 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那連衣裙很配她的紅髮。}} || na4/nei4 lian2 yi1 qun2 hen3 pei4 ta1 de5 hong2 髮。|| Das Kleid passt gut zu ihren roten Haaren. (Mandarin, [https://tatoeba.org/eng/sentences/show/10301651 Tatoeba] [https://tatoeba.org/eng/user/profile/DaoSeng DaoSeng] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我要去剪頭髮了。}} || wo3 yao4 qu4 jian3 tou2 髮 le5 。|| I want to go and get a haircut. (Mandarin, [https://tatoeba.org/eng/sentences/show/6143659 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Kiwi Kiwi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |長頭髮落伍了。}} || chang2/zhang3 tou2 髮 la4/lao4/luo4 wu3 le5 。|| Lange Haare sind unmodern. (Mandarin, [https://tatoeba.org/eng/sentences/show/686735 Tatoeba] [https://tatoeba.org/eng/user/profile/offdare offdare] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我昨天去了理髮店理髮。}} || wo3 zuo2 tian1 qu4 le5 li3 髮 dian4 li3 髮。|| Ich hab mir gestern beim Friseur die Haare schneiden lassen. (Mandarin, [https://tatoeba.org/eng/sentences/show/599676 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Vortarulo Vortarulo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的白髮越來越多。}} || wo3 de5 bai2 髮 yue4 lai2 yue4 duo1 。|| Ich bekomme immer mehr graue Haare. (Mandarin, [https://tatoeba.org/eng/sentences/show/801396 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我把我的头髮剪了。}} || wo3 ba3 wo3 de5 tou2 髮 jian3 le5 。|| Ich habe mir die Haare schneiden lassen. (Mandarin, [https://tatoeba.org/eng/sentences/show/6853182 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |金髮女郎跟她的心裡醫師交談。}} || jin1 髮 nü3/ru3 lang2/lang4 gen1 ta1 de5 xin1 li3 yi1 shi1 jiao1 tan2 。|| Eine Blondine spricht mit ihrem Psychiater. (Mandarin, [https://tatoeba.org/eng/sentences/show/884735 Tatoeba] [https://tatoeba.org/eng/user/profile/Tajfun Tajfun] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我觉得你还是头髮直下来的时候好看。}} || wo3 jiao4/jue2 de2/de5/dei3 ni3 hai2/huan2 shi4 tou2 髮 zhi2 xia4 lai2 de5 shi2 hou4 hao3 kan4 。|| Ich finde, du hast mit glattem Haar besser ausgesehen. (Mandarin, [https://tatoeba.org/eng/sentences/show/7479898 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆去年留了长髮。}} || tang1 mu3 qu4 nian2 liu2 le5 chang2/zhang3 髮。|| Letztes Jahr hatte Tom lange Haare. (Mandarin, [https://tatoeba.org/eng/sentences/show/10332934 Tatoeba] [https://tatoeba.org/eng/user/profile/DaoSeng DaoSeng] [https://tatoeba.org/eng/user/profile/wolfgangth wolfgangth])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我想在出發旅行前剪個頭髮。}} || wo3 xiang3 zai4 chu1 fa1 lü3 hang2/xing2 qian2 jian3 ge4 tou2 髮。|| I want to get a haircut before I go on the trip. (Mandarin, [https://tatoeba.org/eng/sentences/show/2638673 Tatoeba] [https://tatoeba.org/eng/user/profile/cienias cienias] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我妹妹每天早上洗頭髮。}} || wo3 mei4 mei4 mei3 tian1 zao3 shang4 xi3/xian3 tou2 髮。|| Meine Schwester wäscht sich jeden Morgen die Haare. (Mandarin, [https://tatoeba.org/eng/sentences/show/891128 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆喜欢黄头髮的女生。}} || tang1 mu3 xi3 欢 huang2 tou2 髮 de5 nü3/ru3 sheng1 。|| Tom mag Blondinen. (Mandarin, [https://tatoeba.org/eng/sentences/show/5984781 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我要去理髮了。}} || wo3 yao4 qu4 li3 髮 le5 。|| I want to go to the barber. (Mandarin, [https://tatoeba.org/eng/sentences/show/6143660 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Kiwi Kiwi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我想在出发旅行前剪个头髮。}} || wo3 xiang3 zai4 chu1 fa1 lü3 hang2/xing2 qian2 jian3 ge4 tou2 髮。|| I want to get a haircut before I go on the trip. (Mandarin, [https://tatoeba.org/eng/sentences/show/2638673 Tatoeba] [https://tatoeba.org/eng/user/profile/cienias cienias] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我打算去理髮店。}} || wo3 da3 suan4 qu4 li3 髮 dian4 。|| I intend to go to the barbershop. (Mandarin, [https://tatoeba.org/eng/sentences/show/885539 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮店還沒有開門。}} || li3 髮 dian4 hai2/huan2 mei2/mo4 you3 kai1 men2 。|| Der Friseur hat noch nicht geöffnet. (Mandarin, [https://tatoeba.org/eng/sentences/show/8767468 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我根本不喜歡我的頭髮。}} || wo3 gen5 ben3 bu4 xi3 歡 wo3 de5 tou2 髮。|| I don't like my hair at all. (Mandarin, [https://tatoeba.org/eng/sentences/show/6059527 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/fanty fanty])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆没有头髮。}} || tang1 mu3 mei2/mo4 you3 tou2 髮。|| Tom hat eine Glatze. (Mandarin, [https://tatoeba.org/eng/sentences/show/6107702 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的头髮已经很长了。}} || wo3 de5 tou2 髮 yi3 jing4 hen3 chang2/zhang3 le5 。|| Meine Haare sind schon sehr lang. (Mandarin, [https://tatoeba.org/eng/sentences/show/8767467 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那时正在下雨,而Joe回到家时长髮已湿透了。}} || na4/nei4 shi2 zheng4 zai4 xia4 yu3 , er2 Joe hui2 dao4 jia1 shi2 chang2/zhang3 髮 yi3 shi5 tou4 le5 。|| Es regnete gerade, und bis Joe zu Hause war, waren seine langen Haare triefnass. (Mandarin, [https://tatoeba.org/eng/sentences/show/348458 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/pne pne])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的頭髮已經很長了。}} || wo3 de5 tou2 髮 yi3 jing4 hen3 chang2/zhang3 le5 。|| Meine Haare sind schon sehr lang. (Mandarin, [https://tatoeba.org/eng/sentences/show/8767467 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆戴假髮。}} || tang1 mu3 dai4 jia3/jia4 髮。|| Tom trägt Perücke. (Mandarin, [https://tatoeba.org/eng/sentences/show/6936231 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/raggione raggione])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我妹妹每天早上洗头髮。}} || wo3 mei4 mei4 mei3 tian1 zao3 shang4 xi3/xian3 tou2 髮。|| Meine Schwester wäscht sich jeden Morgen die Haare. (Mandarin, [https://tatoeba.org/eng/sentences/show/891128 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |理髮師為他理了頭髮。}} || li3 髮 shi1 wei2/wei4 ta1 li3 le5 tou2 髮。|| Der Frisör hat ihm einen Haarschnitt verliehen. (Mandarin, [https://tatoeba.org/eng/sentences/show/868434 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Espi Espi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |长头髮落伍了。}} || chang2/zhang3 tou2 髮 la4/lao4/luo4 wu3 le5 。|| Lange Haare sind unmodern. (Mandarin, [https://tatoeba.org/eng/sentences/show/686735 Tatoeba] [https://tatoeba.org/eng/user/profile/offdare offdare] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |頭髮想怎麼弄?}} || tou2 髮 xiang3 zen3 me5 long4 ?|| What kind of hair style would you like? How would you like your hair done? (Mandarin, [https://tatoeba.org/eng/sentences/show/1212085 Tatoeba] [https://tatoeba.org/eng/user/profile/liting liting] [https://tatoeba.org/eng/user/profile/denzel denzel] [https://tatoeba.org/eng/user/profile/richwarm richwarm])
|}
=== einzusortieren ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |相貌堂堂}} ||xiàng mào táng táng ||Eine imposante Erscheinung ([[wikt:en:相貌堂堂 |Wiktionary en]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |十动然拒}} || shí dòng rán jù || zehnfach bewegt, aber zurückweisend; eine Frau ist durch den Liebesbeweise des Mannes sehr gerührt, weist ihn aber trotzdem zurück ([[wikt:en:十动然拒 |Wiktionary en]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |美名胜过美貌}} || měi míng shèng guò měimào || Ein guter Ruf ist besser als ein schönes Gesicht ([[q:Chinesische_Sprichw%C3%B6rter |Chinesische Sprichwörter]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人不可貌相,海水不可斗量。}} || rén bù kě mào xiàng, hǎi shuǐ bù kě dǒu liáng || Einen Menschen kann man nicht nach dem Aussehen beurteilen, Meerwasser kann man nicht mit einem Scheffel messen ([[q:Chinesische_Sprichw%C3%B6rter |Chinesische Sprichwörter]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |玄德见他形貌异常,问其姓名。 }} || xuan2 de2 jian4/xian4 ta1 xing2 mao4 yi4 chang2 , wen4 qi2 xing4 ming2 。 ||Xuande thought he looked strange, and asked his name. ([[s:en:Special:PermanentLink/5776532 |Wikisource: Romance of the Three Kingdoms]] [[s:zh:三國演義/第001回 | 三國演義/第001回]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |相貌堂堂 }} || xiang1/xiang4 mao4 tang2 tang2 ||He had a dignified air ([[s:en:Special:PermanentLink/5776532 |Wikisource: Romance of the Three Kingdoms]] [[s:zh:三國演義/第001回 | 三國演義/第001回]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |相拒于广宗}} || xiang1/xiang4 ju4 yu2 guang3 zong1 || They were battling it out in Guangzong ([[s:en:Special:PermanentLink/5776532 |Wikisource: Romance of the Three Kingdoms]] [[s:zh:三國演義/第001回 | 三國演義/第001回]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |与我军相拒}} || yu3 wo3 jun1 xiang1/xiang4 ju4 || he was locked in battle with our forces. ([[s:en:Special:PermanentLink/5495657 | Wikisource: Romance of the Three Kingdoms]] [[s:zh:三國演義/第002回 | 三國演義/第002回]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |张梁统其众,与我军相拒 }} || zhang1 liang2 tong3 qi2 zhong4 , yu3 wo3 jun1 xiang1/xiang4 ju4 ||Zhang Liang was now the leader, and was locked in battle with our forces. ([[s:en:Special:PermanentLink/5495657 | Wikisource: Romance of the Three Kingdoms]] [[s:zh:三國演義/第002回 | 三國演義/第002回]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch | 人所重、非貌高}} || ren2 suo3 chong2/zhong4 、 fei1 mao4 gao1 || Was für Menschen bedeutend ist, ist nicht hohes Aussehen. ([[Vokabeltexte_Chinesisch/_Vokabellektionen/_Lektion_636|Di Zi Gui Schülerregeln]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch | 何进之妹,始初我抬举他 }} || he2 jin4 zhi1 mei4 , shi3 chu1 wo3 tai2 ju3 ta1 ||At first, I helped to advance He Jin's younger sister ([[s:en:Special:PermanentLink/5495657 | Wikisource: Romance of the Three Kingdoms]] [[s:zh:三國演義/第002回 | 三國演義/第002回]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |否则,用左手传递食物会被认为是不礼貌的,因为左手是用来洗澡的。}} || pi3 ze2 , yong4 zuo3 shou3 chuan2/zhuan4 di4 shi2 wu4 hui4 bei4 ren4 wei2/wei4 shi4 bu4 li3 mao4 de5 , yin1 wei2/wei4 zuo3 shou3 shi4 yong4 lai2 xi3/xian3 zao3 de5 。||Otherwise, it is considered impolite to pass food with the left hand, because the left hand is used for bathing. ([https://tatoeba.org/eng/sentences/show/742974 Tatoeba] [https://tatoeba.org/eng/user/profile/eastasiastudent eastasiastudent])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我建议,为了礼貌起见,我们尽可能少喝。}} || wo3 jian4 yi4 , wei2/wei4 le5 li3 mao4 qi3 jian4/xian4 , wo3 men5 jin4 ke3/ke4 neng2 shao3 he1 。||I suggest that, out of politeness, we drink as little as possible. ([https://tatoeba.org/eng/sentences/show/4182631 Tatoeba] [https://tatoeba.org/eng/user/profile/ekgermana ekgermana] [https://tatoeba.org/eng/user/profile/garborg garborg])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她很有礼貌。}} || ta1 hen3 you3 li3 mao4 。||Sie hat sehr gute Manieren. ([https://tatoeba.org/eng/sentences/show/623186 Tatoeba] [https://tatoeba.org/eng/user/profile/xiuqin xiuqin] [https://tatoeba.org/eng/user/profile/meloncurtains meloncurtains])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我觉得最好不要不礼貌。}} || wo3 jiao4/jue2 de2/de5/dei3 zui4 hao3 bu4 yao4 bu4 li3 mao4 。||Ich denke, es ist am besten, nicht unhöflich zu sein. ([https://tatoeba.org/eng/sentences/show/501334 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |美貌只是表面性的东西。}} || mei3 mao4 zhi3 shi4 biao3 mian4 xing4 de5 dong1 xi1 。||Schönheit ist nur oberflächlich. ([https://tatoeba.org/eng/sentences/show/462034 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吃饭时发出声音是不礼貌的。}} || chi1 fan4 shi2 fa1 chu1 sheng1 yin1 shi4 bu4 li3 mao4 de5 。||It is bad manners to make a noise while you eat. ([https://tatoeba.org/eng/sentences/show/2075160 Tatoeba] [https://tatoeba.org/eng/user/profile/fercheung fercheung])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人不可貌相,海水不可斗量。}} || ren2 bu4 ke3/ke4 mao4 xiang1/xiang4 , hai3 shui3 bu4 ke3/ke4 dou4 liang2/liang4 。||You can't judge a person by appearance, just as you can't measure the sea with a pint pot. ([https://tatoeba.org/eng/sentences/show/3664074 Tatoeba] [https://tatoeba.org/eng/user/profile/gleki gleki])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |说苗条比说瘦更有礼貌。}} || shuo1 miao2 tiao2 bi4 shuo1 shou4/sou4 geng4 you3 li3 mao4 。||It's more polite to say thin than skinny. ([https://tatoeba.org/eng/sentences/show/812360 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/darinmex darinmex])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他把座位让给了一个老人,这显示出他很有礼貌。}} || ta1 ba3 zuo4 wei4 rang4 gei3 le5 yi1 ge4 lao3 ren2 , zhe4/zhei4 xian3 shi4 chu1 ta1 hen3 you3 li3 mao4 。||Er zeigte gute Umgangsformen, als er einem alten Menschen den Platz überließ. ([https://tatoeba.org/eng/sentences/show/847733 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在中国有一种说法:人不可貌相。}} || zai4 zhong1/zhong4 guo2 you3 yi1 chong2/zhong3/zhong4 shuo1 fa3 : ren2 bu4 ke3/ke4 mao4 xiang1/xiang4 。||In China sagt man, dass man einen Menschen nicht nach seinem Aussehen beurteilen darf. ([https://tatoeba.org/eng/sentences/show/449218 Tatoeba] [https://tatoeba.org/eng/user/profile/sysko sysko] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那个护士人很好,又有礼貌。}} || na4/nei4 ge4 hu4 shi4 ren2 hen3 hao3 , you4 you3 li3 mao4 。||Die Krankenschwester ist sehr nett und höflich. ([https://tatoeba.org/eng/sentences/show/463855 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不要以貌取人。}} || bu4 yao4 yi3 mao4 qu3 ren2 。||Bewerte Menschen nicht nach ihrem Äußeren. ([https://tatoeba.org/eng/sentences/show/345288 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |早睡早起对你的健康和容貌都很有好处。}} || zao3 shui4 zao3 qi3 dui4 ni3 de5 jian4 kang1 he2/he4/huo2 rong2 mao4 dou1/du1 hen3 you3 hao3 chu4 。||Going to bed early and waking up early is very good both for your health and appearance. ([https://tatoeba.org/eng/sentences/show/5574638 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/WestofEden WestofEden])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |开口要有礼貌,不讲下流话。}} || kai1 kou3 yao4 you3 li3 mao4 , bu4 jiang3/jiang5 xia4 liu2 hua4 。||One must be respectful when speaking, and not say obscene things. ([https://tatoeba.org/eng/sentences/show/421250 Tatoeba] [https://tatoeba.org/eng/user/profile/sysko sysko] [https://tatoeba.org/eng/user/profile/minshirui minshirui])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公主的美貌无法形容。}} || gong1 zhu3 de5 mei3 mao4 wu2 fa3 xing2 rong2 。||Die Prinzessin war von einer unbeschreiblichen Schönheit. ([https://tatoeba.org/eng/sentences/show/512493 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他今天非常礼貌。}} || ta1 jin1 tian1 fei1 chang2 li3 mao4 。||Er ist heute furchtbar höflich. ([https://tatoeba.org/eng/sentences/show/2394391 Tatoeba] [https://tatoeba.org/eng/user/profile/fenfang557 fenfang557] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |Tom没有礼貌。}} || Tom mei2/mo4 you3 li3 mao4 。||Tom hat keine Manieren. ([https://tatoeba.org/eng/sentences/show/346464 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MikeMolto MikeMolto])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用手指点别人不礼貌。}} || yong4 shou3 zhi3 dian3 bie2 ren2 bu4 li3 mao4 。||It's bad manners to point at people. ([https://tatoeba.org/eng/sentences/show/5091092 Tatoeba] [https://tatoeba.org/eng/user/profile/mirrorvan mirrorvan] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你出国的时候学一些当地的礼貌用语还是很有用的。}} || ni3 chu1 guo2 de5 shi2 hou4 xue2 yi1 xie1 dang1/dang4 de4/di4 de5 li3 mao4 yong4 yu3 hai2/huan2 shi4 hen3 you3 yong4 de5 。||When you go abroad, it is useful to learn at least some polite phrases in the local language. ([https://tatoeba.org/eng/sentences/show/1517484 Tatoeba] [https://tatoeba.org/eng/user/profile/gonnastop gonnastop] [https://tatoeba.org/eng/user/profile/iris iris])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他们认为,去反驳一个不认识的人有些不礼貌。}} || ta1 men5 ren4 wei2/wei4 , qu4 fan3 驳 yi1 ge4 bu4 ren4 zhi4 de5 ren2 you3 xie1 bu4 li3 mao4 。||Sie finden es unhöflich, jemandem zu widersprechen, den sie nicht gut kennen. ([https://tatoeba.org/eng/sentences/show/2052135 Tatoeba] [https://tatoeba.org/eng/user/profile/Gustav249 Gustav249] [https://tatoeba.org/eng/user/profile/Fingerhut Fingerhut])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你至少可以试着多一点礼貌,即使那不是你的本质。}} || ni3 zhi4 shao3 ke3/ke4 yi3 shi4 zhao2/zhe2 duo1 yi1 dian3 li3 mao4 , ji2 shi3/shi4 na4/nei4 bu4 shi4 ni3 de5 ben3 zhi4 。||Du könntest zumindest versuchen, ein bisschen höflicher zu sein, auch wenn das nicht in deiner Natur liegt. ([https://tatoeba.org/eng/sentences/show/334701 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不要被外貌蒙蔽了。}} || bu4 yao4 bei4 wai4 mao4 meng2 蔽 le5 。||Don't let appearances deceive you. ([https://tatoeba.org/eng/sentences/show/4517819 Tatoeba] [https://tatoeba.org/eng/user/profile/yuiyu yuiyu] [https://tatoeba.org/eng/user/profile/paper1n0 paper1n0])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人们都以为日本人是讲究礼貌的。}} || ren2 men5 dou1/du1 yi3 wei2/wei4 ri4 ben3 ren2 shi4 jiang3/jiang5 jiu1 li3 mao4 de5 。||Das japanische Volk wird als höflich betrachtet. ([https://tatoeba.org/eng/sentences/show/1946779 Tatoeba] [https://tatoeba.org/eng/user/profile/bigfatpanda bigfatpanda] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |难看的不是人的外貌,而是人的衣服。}} || nan2/nan4 kan4 de5 bu4 shi4 ren2 de5 wai4 mao4 , er2 shi4 ren2 de5 yi1 fu2 。||Es ist nicht die Person, die hässlich ist, sondern die Kleidung. ([https://tatoeba.org/eng/sentences/show/891831 Tatoeba] [https://tatoeba.org/eng/user/profile/FeuDRenais FeuDRenais] [https://tatoeba.org/eng/user/profile/Zaghawa Zaghawa])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的容貌改变了许多。}} || ta1 de5 rong2 mao4 gai3 bian4 le5 xu3 duo1 。||Sein Aussehen hat sich sehr verändert. ([https://tatoeba.org/eng/sentences/show/334283 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/tatomeimei tatomeimei])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我找商店经理谈了话,因为他拒绝为那不能用的电视退钱。}} || wo3 zhao3 shang1 dian4 jing4 li3 tan2 le5 hua4 , yin1 wei2/wei4 ta1 ju4 jue2 wei2/wei4 na4/nei4 bu4 neng2 yong4 de5 dian4 shi4 tui4 qian2 。||I had words with the manager of that store, because he refused to refund my money for the TV set that wasn't operating properly. ([https://tatoeba.org/eng/sentences/show/736542 Tatoeba] [https://tatoeba.org/eng/user/profile/yujianing yujianing])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了我。}} || ta1 ju4 jue2 le5 wo3 。||She rejected me. ([https://tatoeba.org/eng/sentences/show/1072748 Tatoeba] [https://tatoeba.org/eng/user/profile/sysko sysko] [https://tatoeba.org/eng/user/profile/konkorde konkorde])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝被你像奴隶一样对待。}} || wo3 ju4 jue2 bei4 ni3 xiang4 nu2 li4 yi1 yang4 dui4 dai1 。||Ich lasse mich von dir nicht wie einen Sklaven behandeln. ([https://tatoeba.org/eng/sentences/show/796773 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/samueldora samueldora])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝了报价。}} || wo3 ju4 jue2 le5 bao4 jia4/jie4 。||Ich habe das Angebot abgelehnt. ([https://tatoeba.org/eng/sentences/show/804839 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你本该拒绝一个那么不公平的提议。}} || ni3 ben3 gai1 ju4 jue2 yi1 ge4 na4/nei4 me5 bu4 gong1 ping2 de5 ti2 yi4 。||So einen ungerechten Vorschlag hättest du ablehnen sollen. ([https://tatoeba.org/eng/sentences/show/503226 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆甚至拒绝听我的建议。}} || tang1 mu3 shen4 zhi4 ju4 jue2 ting1 wo3 de5 jian4 yi4 。||Tom refused to even listen to my suggestions. ([https://tatoeba.org/eng/sentences/show/5611615 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |医生们拒绝做第二次手术。}} || yi1 sheng1 men5 ju4 jue2 zuo4 di4 er4 ci4 shou3 shu4 。||Die Ärzte weigerten sich, eine zweite Operation durchzuführen. ([https://tatoeba.org/eng/sentences/show/1467060 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/Zaghawa Zaghawa])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |总统拒绝回答那个问题。}} || zong3 tong3 ju4 jue2 hui2 da2 na4/nei4 ge4 wen4 ti2 。||Der Präsident weigerte sich, auf diese Frage zu antworten. ([https://tatoeba.org/eng/sentences/show/333537 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/tatomeimei tatomeimei])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他拒绝相信我们。}} || ta1 ju4 jue2 xiang1/xiang4 xin4 wo3 men5 。||He refuses to believe us. ([https://tatoeba.org/eng/sentences/show/785851 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/tinytina tinytina])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我必须拒绝。}} || wo3 bi4 xu1 ju4 jue2 。||I have to say no. ([https://tatoeba.org/eng/sentences/show/5091270 Tatoeba] [https://tatoeba.org/eng/user/profile/mirrorvan mirrorvan] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |圣女贞德拒绝放弃相信她听到的声音是来自上帝,而不是其他的。}} || sheng4 nü3/ru3 zhen1 de2 ju4 jue2 fang4 qi4 xiang1/xiang4 xin4 ta1 ting1 dao4 de5 sheng1 yin1 shi4 lai2 zi4 shang4 di4 , er2 bu4 shi4 qi2 ta1 de5 。||Jeanne d'Arc weigerte sich, ihre Überzeugung zu leugnen, dass die Stimme, die sie hörte, von niemand anderem als Gott war. ([https://tatoeba.org/eng/sentences/show/502990 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/esocom esocom])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |尽管我提出了热切的要求,他们拒绝跟我说话。}} || jin4 guan3/guan5 wo3 ti2 chu1 le5 re4 qie1 de5 yao4 qiu2 , ta1 men5 ju4 jue2 gen1 wo3 shuo1 hua4 。||They refused to talk to me in spite of my earnest request. ([https://tatoeba.org/eng/sentences/show/1565720 Tatoeba] [https://tatoeba.org/eng/user/profile/eastasiastudent eastasiastudent])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝。}} || wo3 ju4 jue2 。||I must decline. ([https://tatoeba.org/eng/sentences/show/3813012 Tatoeba] [https://tatoeba.org/eng/user/profile/hongsly hongsly] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了每一项提议。}} || ta1 ju4 jue2 le5 mei3 yi1 xiang4 ti2 yi4 。||She turned down every proposal. ([https://tatoeba.org/eng/sentences/show/2017443 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝回答你的问题。}} || wo3 ju4 jue2 hui2 da2 ni3 de5 wen4 ti2 。||I refuse to answer your question. ([https://tatoeba.org/eng/sentences/show/1762969 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/szilviez szilviez])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我拒绝被像一个孩子般对待。}} || wo3 ju4 jue2 bei4 xiang4 yi1 ge4 hai2 zi5 ban1 dui4 dai1 。||Ich weigere mich, wie ein Kind behandelt zu werden. ([https://tatoeba.org/eng/sentences/show/427621 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的回答其实是拒绝。}} || ta1 de5 hui2 da2 qi2 shi2 shi4 ju4 jue2 。||Seine Antwort war in Wirklichkeit eine Absage. ([https://tatoeba.org/eng/sentences/show/390482 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |尽管政府拒绝承认,它的经济政策还是失败了。}} || jin4 guan3/guan5 zheng4 fu3 ju4 jue2 承 ren4 , ta1/tuo2 de5 jing4 ji4 zheng4 策 hai2/huan2 shi4 shi1 bai4 le5 。||Although the government refuses to admit it, its economic policy is in ruins. ([https://tatoeba.org/eng/sentences/show/5581646 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |公司为了削减成本,拒绝让员工自行加班。}} || gong1 si1 wei2/wei4 le5 xiao1/xue1 jian3 cheng2 ben3 , ju4 jue2 rang4 yuan2 gong1 zi4 hang2/xing2 jia1 ban1 。||In order to cut down on costs, the company refuses to allow employees to work overtime. ([https://tatoeba.org/eng/sentences/show/2440614 Tatoeba] [https://tatoeba.org/eng/user/profile/fenfang557 fenfang557] [https://tatoeba.org/eng/user/profile/szilviez szilviez])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你应该直接拒绝他的要求。}} || ni3 ying1/ying4 gai1 zhi2 jie1 ju4 jue2 ta1 de5 yao4 qiu2 。||You should have refused his request flatly. ([https://tatoeba.org/eng/sentences/show/3068630 Tatoeba] [https://tatoeba.org/eng/user/profile/serendipity42 serendipity42])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她拒绝了我的资助。}} || ta1 ju4 jue2 le5 wo3 de5 zi1 zhu4 。||She turned down the subsidy that I offered. ([https://tatoeba.org/eng/sentences/show/334379 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/aliene aliene])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你要干洗还是湿洗?}} || ni3 yao4 gan1/qian2 xi3/xian3 hai2/huan2 shi4 shi5 xi3/xian3 ?||Do you want dry cleaning or regular wash? ([https://tatoeba.org/eng/sentences/show/420222 Tatoeba] [https://tatoeba.org/eng/user/profile/sysko sysko] [https://tatoeba.org/eng/user/profile/tigro1973 tigro1973])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |猫讨厌被弄湿。}} || mao1 tao3 yan4 bei4 long4 shi5 。||Katzen verabscheuen es nass zu werden. ([https://tatoeba.org/eng/sentences/show/815302 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Dejo Dejo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他从头到脚都湿了。}} || ta1 cong2 tou2 dao4 jiao3 dou1/du1 shi5 le5 。||Er war von Kopf bis Fuß durchnässt. ([https://tatoeba.org/eng/sentences/show/389434 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我浑身都被雨水给淋湿了。你现在能不能开车来接我?}} || wo3 浑 shen1 dou1/du1 bei4 yu3 shui3 gei3 lin2 shi5 le5 。 ni3 xian4 zai4 neng2 bu4 neng2 kai1 che1 lai2 jie1 wo3 ?||Wegen des starken Regens bin ich nass bis auf die Haut. Kannst du mich gleich mit dem Auto abholen? ([https://tatoeba.org/eng/sentences/show/2394828 Tatoeba] [https://tatoeba.org/eng/user/profile/fenfang557 fenfang557] [https://tatoeba.org/eng/user/profile/chiyochan chiyochan])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |天气又冷又湿。}} || tian1 qi4 you4 leng3 you4 shi5 。||Das Wetter war nicht nur kalt, sondern auch feucht. ([https://tatoeba.org/eng/sentences/show/333431 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |因为气候又暖和又湿润,所以广州一年到头都有花。}} || yin1 wei2/wei4 qi4 hou4 you4 nuan3 he2/he4/huo2 you4 shi5 run4 , suo3 yi3 guang3 zhou1 yi1 nian2 dao4 tou2 dou1/du1 you3 hua1 。||With a warm and wet climate, Guangzhou has fresh flowers all year round. ([https://tatoeba.org/eng/sentences/show/766041 Tatoeba] [https://tatoeba.org/eng/user/profile/eastasiastudent eastasiastudent])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |帮我抬起这包裹。}} || bang1 wo3 tai2 qi3 zhe4/zhei4 bao1 guo3 。||Help me lift the package. ([https://tatoeba.org/eng/sentences/show/5856739 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |把你的腿抬起來}} || ba3 ni3 de5 tui3 tai2 qi3 lai2 ||Raise your leg. ([https://tatoeba.org/eng/sentences/show/6049580 Tatoeba] [https://tatoeba.org/eng/user/profile/magicalrpetz47 magicalrpetz47] [https://tatoeba.org/eng/user/profile/mailohilohi mailohilohi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他抬頭望著天空。}} || ta1 tai2 tou2 wang4 zhao1/zhu4/zhuo2 tian1 kong1/kong4 。||He was looking upward to the sky. ([https://tatoeba.org/eng/sentences/show/546569 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她抬頭看著他。}} || ta1 tai2 tou2 kan4 zhao1/zhu4/zhuo2 ta1 。||Sie hob den Kopf und sah ihn an. ([https://tatoeba.org/eng/sentences/show/616108 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/samueldora samueldora])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这张桌子太重,没抬动。}} || zhe4/zhei4 zhang1 桌 zi5 tai4 chong2/zhong4 , mei2/mo4 tai2 dong4 。||Dieser Schreibtisch ist zu schwer zum Anheben. ([https://tatoeba.org/eng/sentences/show/348025 Tatoeba] [https://tatoeba.org/eng/user/profile/zhouj1955 zhouj1955] [https://tatoeba.org/eng/user/profile/lilygilder lilygilder])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她抬頭望向天空。}} || ta1 tai2 tou2 wang4 xiang4 tian1 kong1/kong4 。||Sie sah zum Himmel hinauf. ([https://tatoeba.org/eng/sentences/show/350705 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Fingerhut Fingerhut])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这张桌子太重,抬不动。}} || zhe4/zhei4 zhang1 桌 zi5 tai4 chong2/zhong4 , tai2 bu4 dong4 。||Dieser Schreibtisch ist zu schwer zum Anheben. ([https://tatoeba.org/eng/sentences/show/348026 Tatoeba] [https://tatoeba.org/eng/user/profile/zhouj1955 zhouj1955] [https://tatoeba.org/eng/user/profile/lilygilder lilygilder])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那位技师技术很好。}} || na4/nei4 wei4 ji4 shi1 ji4 shu4 hen3 hao3 。||That technician is highly skilled. ([https://tatoeba.org/eng/sentences/show/6452006 Tatoeba] [https://tatoeba.org/eng/user/profile/Lemmih Lemmih])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我们公司的技术已经达到了发达国家九十年代的水平。}} || wo3 men5 gong1 si1 de5 ji4 shu4 yi3 jing4 da2 dao4 le5 fa1 da2 guo2 jia1 jiu3 shi2 nian2 dai4 de5 shui3 ping2 。||Our company's technology has already reached the level of a developed country in the 1990s. ([https://tatoeba.org/eng/sentences/show/717378 Tatoeba] [https://tatoeba.org/eng/user/profile/Yashanti Yashanti] [https://tatoeba.org/eng/user/profile/eastasiastudent eastasiastudent])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |空间技术还在幼儿期。}} || kong1/kong4 jian1 ji4 shu4 hai2/huan2 zai4 you4 er2/er5 ji1/qi1 。||Die Weltraumforschung steckt noch in den Kinderschuhen. ([https://tatoeba.org/eng/sentences/show/5581593 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/samueldora samueldora])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |日本是世界高科技产业的领头人。}} || ri4 ben3 shi4 shi4 jie4 gao1 ke1 ji4 chan3 ye4 de5 ling3 tou2 ren2 。||Japan is the leader of the world's high-tech industry. ([https://tatoeba.org/eng/sentences/show/335266 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/koineko koineko])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |听说大数据技术现在很热门。}} || ting1 shuo1 da4 shu3/shuo4 ju4 ji4 shu4 xian4 zai4 hen3 re4 men2 。||I hear about that the network is very popular now. ([https://tatoeba.org/eng/sentences/show/4813375 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/pig8322 pig8322])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |在科技准备好之前需要五到十年。}} || zai4 ke1 ji4 zhun3 bei4 hao3 zhi1 qian2 xu1 yao4 wu3 dao4 shi2 nian2 。||Es wird fünf bis zehn Jahre dauern, bis die Technologie bereit ist. ([https://tatoeba.org/eng/sentences/show/501708 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |除了语言,我也对技术感兴趣。}} || chu2 le5 yu3 yan2 , wo3 ye3 dui4 ji4 shu4 gan3 xing1/xing4 qu4 。||Apart from languages, I'm also interested in technology. ([https://tatoeba.org/eng/sentences/show/899118 Tatoeba] [https://tatoeba.org/eng/user/profile/eastasiastudent eastasiastudent])
|}
== Lückentexte ==
=== [http://magazine.marcopoloproject.org/%e5%b0%b1%e4%ba%8b%e8%ae%ba%e4%ba%8b-judging-merits/ the marco polo project: 就事论事] ===
小时候很喜欢看 Lu Xun 的文章,后来有一段时间,看了一些关于他为人的文章,很是反感,于是顺带也不喜欢他的文字了。不过后来,人再长大一些,觉得自己很是好笑,对我而言他只是一个作家,用他的文字来表达他的观点,我需要认同和不认同的,只不过是他的文字而已,为何要和他的为人联系在一起?再说了,他是一个怎样的人,我同样也是从别人的文字里面了解。
从小的教育,让我曾经有个习惯,把所有的事情和一个人的道德好坏联系在一起,或者第一时间先去 herauszufinden 动机。后来一个比我年长一点的朋友讲起这样一件事情:文化大革命的时候,实在找不出一个人的罪证,于是会质问对方,为何要在这个时间出门?为何要在这个时间去买菜?一定带有不可告人的目的。这个时候,被质问的人,真的无从解释,其实对方也根本不想听解释,因为他们认为自己已经找到了证据。我听完哈哈大笑,但是仔细一想,这不也是我有意无意会 begangen 的错误。
我也经常看到这样的 Frage:因为你存在道德问题,因为你的身份问题,因为你的为人关系,所以你没有资格发表看法,所以你说的话就是错的,在这种情况之下,是不可能进行讨论的,因为对方已经从道德高度,否定了你,拒绝接受你。
如何学习就事论事,如何学习抛弃诛心的思维,改变总是站在道德高度 und zu kritisieren 别人的习惯,我还在努力中,不知道你呢?
[http://magazine.marcopoloproject.org/authors/Luqiu%20Luwei%20-%20%E9%97%BE%E4%B8%98%E9%9C%B2%E8%96%87/ Luqiu Luwei]
[http://magazine.marcopoloproject.org/%e5%b0%b1%e4%ba%8b%e8%ae%ba%e4%ba%8b-judging-things-on-their-own-merits-english/ Übersetzung]
Judging things on their own merits
When I was little, I really liked Lu Xun’s writing, but later, at some stage, I read a few pieces about him as a person, and really disliked him, so after that, I no longer liked what he wrote. Then later still, I grew up again, and found myself quite ridiculous: for me, he was just a writer, and expressed his way of seeing the world with his writing, so what I needed to agree and disagree with was only what he wrote, why should it also be connected to him as a person? Beside, it’s from other people writing about him that I could understand what kind of a man he was.
In my childhood education, I developed a habit: connect everything to a person’s good or bad morals, or from the start, try to guess what their motivation is. Later, a friend slightly older than myself told me the following thing: during the Cultural Revolution, they couldn’t find any incriminating evidence against a certain person, so they started interrogating: Why did you go out at that particular time? Why did you go shopping at that particular time? You must have had some ulterior motive. The person interrogated really had no explanation for that, but the interrogator didn’t actually want any explanation at all, because they thought they already had all the evidence. I laughed when I heard this, but thinking about it retrospectively, I have to say this is a mistake I might have committed myself, intentionally or not.
I often come across this question: because of issues with your ethical position, because of issues with your identty, because of your relationships or character 因为你的为人关系, you’re not eligible to express your views, or what you’re saying is necessarily wrong. In such circumstances, discussion is impossible, because your counterpart has already taken the moral high ground, they have denied you access, they have refused to accept you.
How can we learn to judge things on their own merit, how can we learn to give up our tendency to condemn, and stop always taking a moral high-ground to criticise other people’s habits: I’m still working on it – I’m not sure about you.
[http://magazine.marcopoloproject.org/author/julienleyre/ Julien Leyre] [http://julienleyre.wordpress.com website]
=== [https://newchristianbiblestudy.org/de/bible/compare/chinese-union-s/german-elberfelder-1905/matthew/22/ Bibel: Matthäusevangelium Kapitel 22] ===
{| class="wikitable"
! Chinese Union Version !! Übersetzung Rudolf Brockhaus (1856-1932)
|-
| 22.1 Jesus 又用比喻对他们说: || 22.1 Und Jesus antwortete und redete wiederum in Gleichnissen zu ihnen und sprach:
|-
| 22.2 天国好比一个王为他儿子摆设娶亲的 Bankett, || 22.2 Das Reich der Himmel ist einem Könige gleich geworden, der seinem Sohne Hochzeit machte.
|-
| 22.3 就打发 Knechte 去,请那些被召的人来赴席,他们却不肯来。 || 22.3 Und er sandte seine Knechte aus, um die Geladenen zur Hochzeit zu rufen; und sie wollten nicht kommen.
|-
| 22.4 王又打发别的 Knechte,说:你们告诉那被召的人,我的 Mahl 已经预备好了,牛和肥畜已经宰了,各样都齐备,请你们来赴席。 || 22.4 Wiederum sandte er andere Knechte aus und sprach: Saget den Geladenen: Siehe, mein Mahl habe ich bereitet, meine Ochsen und mein Mastvieh sind geschlachtet, und alles ist bereit; kommt zur Hochzeit.
|-
| 22.5 那些人不理就走了;一个到自己田里去;一个作买卖去; || 22.5 Sie aber achteten es nicht und gingen hin, der eine auf seinen Acker, der andere an seinen Handel.
|-
| 22.6 其馀的拿住 Knechte,mißhandelten 他们,把他们杀了。 || 22.6 Die übrigen aber ergriffen seine Knechte, mißhandelten und töteten sie.
|-
| 22.7 王就大怒,发兵除灭那些凶手,und steckte 他们的城 in Brand。 || 22.7 Der König aber ward zornig und sandte seine Heere aus, brachte jene Mörder um und steckte ihre Stadt in Brand.
|-
| 22.8 於是对 Knechten 说:die Hochzeit 已经齐备,只是所召的人不配。 || 22.8 Dann sagt er zu seinen Knechten: die Hochzeit ist zwar bereit, aber die Geladenen waren nicht würdig;
|-
| 22.9 所以你们要往 Kreuzwege der Landstraßen 上去,凡遇见的,都召来赴席。 || 22.9 so gehet nun hin auf die Kreuzwege der Landstraßen, und so viele immer ihr finden werdet, ladet zur Hochzeit.
|-
| 22.10 那些 Knechte 就出去,到大路上,凡遇见的,不论善恶都召聚了来,Hochzeit 上就坐满了客。 || 22.10 Und jene Knechte gingen aus auf die Landstraßen und brachten alle zusammen, so viele sie fanden, sowohl Böse als Gute. Und die Hochzeit wurde voll von Gästen.
|-
| 22.11 王进来观看宾客,见那里有一个没有穿礼服的, || 22.11 Als aber der König hereinkam, die Gäste zu besehen, sah er daselbst einen Menschen, der nicht mit einem Hochzeitskleide bekleidet war.
|-
| 22.12 就对他说:朋友,你到这里来怎么不穿礼服呢?那人无言可答。 || 22.12 Und er spricht zu ihm: Freund, wie bist du hier hereingekommen, da du kein Hochzeitskleid anhast? Er aber verstummte.
|-
| 22.13 於是王对 Diener 说:bindet 起他的手脚来,把他丢在外边的黑暗里;在那里必要哀哭切齿了。 || 22.13 Da sprach der König zu den Dienern: Bindet ihm Füße und Hände, nehmet ihn und werfet ihn hinaus in die äußere Finsternis: da wird sein das Weinen und das Zähneknirschen.
|-
| 22.14 因为被召的人多,选上的人少。 || 22.14 Denn viele sind Berufene, wenige aber Auserwählte.
|-
| 22.15 当时,法利赛人出去商议,怎样就着 Jesus 的话 nutzen, um ihn in eine Falle zu locken, || 22.15 Dann gingen die Pharisäer hin und hielten Rat, wie sie ihn in der Rede in eine Falle lockten.
|-
| 22.16 就打发他们的门徒同 Herodes 的人去见 Jesus,说:夫子,我们知道你是诚实人,并且诚诚实实传神的道,什么人你都不 kümmern,因为你不看人的外貌。 || 22.16 Und sie senden ihre Jünger mit den Herodianern zu ihm und sagen: Lehrer, wir wissen, daß du wahrhaftig bist und den Weg Gottes in Wahrheit lehrst und dich um niemand kümmerst, denn du siehst nicht auf die Person der Menschen; sage uns nun, was denkst du:
|-
| 22.17 请告诉我们,你的意见如何?纳税给该撒可以不可以? || 22.17 Ist es erlaubt, dem Kaiser Steuer zu geben, oder nicht?
|-
| 22.18 Jesus 看出他们的恶意,就说:假冒为善的人哪,为什么 versuchet ihr 我? || 22.18 Da aber Jesus ihre Bosheit erkannte, sprach er: Was versuchet ihr mich, Heuchler?
|-
| 22.19 拿一个上税的钱给我看!他们就拿一个银钱来给他。 || 22.19 Zeiget mir die Steuermünze. Sie aber überreichten ihm einen Denar.
|-
| 22.20 Jesus 说:这像和这号是谁的? || 22.20 Und er spricht zu ihnen: Wessen ist dieses Bild und die Überschrift?
|-
| 22.21 他们说:是该撒的。Jesus 说:这样,该撒的物当归给该撒;神的物当归给神。 || 22.21 Sie sagen zu ihm: Des Kaisers. Da spricht er zu ihnen: Gebet denn dem Kaiser, was des Kaisers ist, und Gott, was Gottes ist.
|-
| 22.22 他们听见就希奇,离开他走了。 || 22.22 Und als sie das hörten, verwunderten sie sich und ließen ihn und gingen hinweg.
|-
| 22.23 撒都该人常说没有复活的事。那天,他们来问 Jesus 说: || 22.23 An jenem Tage kamen Sadducäer zu ihm, die da sagen, es gebe keine Auferstehung;
|-
| 22.24 夫子,Moses 说:人若死了,没有孩子,他兄弟当娶他的妻,为哥哥生子立後。 || 22.24 und sie fragten ihn und sprachen: Lehrer, Moses hat gesagt: Wenn jemand stirbt und keine Kinder hat, so soll sein Bruder sein Weib heiraten und soll seinem Bruder Samen erwecken.
|-
| 22.25 从前,在我们这里有弟兄七人,第一个娶了妻,死了,没有孩子,hinterließ er 妻子给兄弟。 || 22.25 Es waren aber bei uns sieben Brüder. Und der erste verheiratete sich und starb; und weil er keinen Samen hatte, hinterließ er sein Weib seinem Bruder.
|-
| 22.26 第二、第三、直到第七个,都是如此。 || 22.26 Gleicherweise auch der zweite und der dritte, bis auf den siebten.
|-
| 22.27 末後,妇人也死了。 || 22.27 Zuletzt aber von allen starb auch das Weib.
|-
| 22.28 这样,当复活的时候,他是七个人中那一个的妻子呢?因为他们都娶过他。 || 22.28 In der Auferstehung nun, wessen Weib von den sieben wird sie sein? Denn alle hatten sie.
|-
| 22.29 Jesus 回答说:你们错了;因为不明白圣经,也不 kennt 神的大能。 || 22.29 Jesus aber antwortete und sprach zu ihnen: Ihr irret, indem ihr die Schriften nicht kennet, noch die Kraft Gottes;
|-
| 22.30 当复活的时候,人也不娶也不 heiraten Frauen einen Mann,乃像天上的使者一样。 || 22.30 denn in der Auferstehung heiraten sie nicht, noch werden sie verheiratet, sondern sie sind wie Engel Gottes im Himmel.
|-
| 22.31 论到死人复活,神在经上向你们所说的,你们没有念过么? || 22.31 Was aber die Auferstehung der Toten betrifft, habt ihr nicht gelesen, was zu euch geredet ist von Gott, der da spricht:
|-
| 22.32 他说:我是 Abraham 的神,以撒的神,雅各的神。神不是死人的神,乃是活人的神。 || 22.32 "Ich bin der Gott Abrahams und der Gott Isaaks und der Gott Jakobs"? Gott ist nicht ein Gott der Toten, sondern der Lebendigen.
|-
| 22.33 众人听见这话,就希奇他的教训。 || 22.33 Und als die Volksmengen es hörten, erstaunten sie über seine Lehre.
|-
| 22.34 法利赛人听见 Jesus 堵住了撒都该人的口,他们就聚集。 || 22.34 Als aber die Pharisäer hörten, daß er die Sadducäer zum Schweigen gebracht hatte, versammelten sie sich miteinander.
|-
| 22.35 内中有一个人是律法师,und versuchte Jesus,就问他说: || 22.35 Und es fragte einer aus ihnen, ein Gesetzgelehrter, und versuchte ihn und sprach:
|-
| 22.36 夫子,律法上的 Gebot,那一条是最大的呢? || 22.36 Lehrer, welches ist das große Gebot in dem Gesetz?
|-
| 22.37 Jesus 对他说:你要尽心、尽性、尽意爱主─你的神。 || 22.37 Er aber sprach zu ihm: "Du sollst den Herrn, deinen Gott, lieben mit deinem ganzen Herzen und mit deiner ganzen Seele und mit deinem ganzen Verstande".
|-
| 22.38 这是 Gebote 中的第一,且是最大的。 || 22.38 Dieses ist das große und erste Gebot.
|-
| 22.39 其次也 gleiche,就是要爱人如己。 || 22.39 Das zweite aber, ihm gleiche, ist: "Du sollst deinen Nächsten lieben wie dich selbst".
|-
| 22.40 这两条 Gebote 是律法和先知一切道理的总纲。 || 22.40 An diesen zwei Geboten hängt das ganze Gesetz und die Propheten.
|-
| 22.41 法利赛人聚集的时候,Jesus 问他们说: || 22.41 Als aber die Pharisäer versammelt waren, fragte sie Jesus und sagte:
|-
| 22.42 论到 Christus,你们的意见如何?他是谁的子孙呢?他们回答说:是大卫的子孙。 || 22.42 Was dünkt euch von dem Christus? Wessen Sohn ist er? Sie sagen zu ihm: Davids.
|-
| 22.43 Jesus 说:这样,大卫被圣灵感动,怎么还称他为主,说: || 22.43 Er spricht zu ihnen: Wie nennt David ihn denn im Geiste Herr, indem er sagt:
|-
| 22.44 主对我主说:你坐在我的右边,等我把你 Feinde 放在你的脚下。 || 22.44 "Der Herr sprach zu meinem Herrn: Setze dich zu meiner Rechten, bis ich deine Feinde lege unter deine Füße"?
|-
| 22.45 大卫既称他为主,他怎么又是大卫的子孙呢? || 22.45 Wenn nun David ihn Herr nennt, wie ist er sein Sohn?
|-
| 22.46 他们没有一个人能回答一言。从那日以後,也没有人敢再问他什么。 || 22.46 Und niemand konnte ihm ein Wort antworten, noch wagte jemand von dem Tage an, ihn ferner zu befragen.
|}
=== Haenisch: Lehrgang der klassischen chinesischen Schriftsprache ===
====第一百零八課====
第一百零八课
dì yī bǎi líng bā kè
Hundertachte Lektion
Der Text dieser Lektion findet sich im [[s:zh:%E9%9A%8B%E6%9B%B8/%E5%8D%B777|Sui Shu, der Geschichte der Sui-Dynastie]].
---------------------------------
李士 Qian 出 Getreide 數千石以_鄉人
李士 Qian 出 Getreide 数千石以贷乡人
lǐ shì qiān chū sù shù qiān dàn yǐ dài xiāng rén
Li Shiqian gab Getreide im Gewicht von 1000 Dan heraus, und verlieh es an die Dorfbewohner.
---------------------------------
值年谷不登,
zhí nián gǔ bù dēng,
In dem Jahr passierte, dass das Getreide (die Ernte) nicht eingebracht werden konnte
---------------------------------
und die Schuldner 無以_,
und die Schuldner 无以偿,
zhài jiā wú yǐ cháng,
und die Schuldner nichts zum Zurückzahlen hatten.
---------------------------------
皆來致謝。
皆来致谢。
jiē lái zhì xiè.
Alle kamen, um Entschuldigungen abzugeben.
---------------------------------
士 Qian 曰
shì qiān yuē
Shiqian sagte:
---------------------------------
吾家餘 Getreide,
吾家余 Getreide,
wú jiā yú sù,
Das überschüssige Getreide meiner Familie
---------------------------------
本圖 Mildtätigkeiten und Unterstützungen,
本图 Mildtätigkeiten und Unterstützungen,
běn tú zhèn shàn,
war ursprünlich für Mildtätigkeiten und Unterstützungen geplant.
---------------------------------
豈求利哉
岂求利哉
qǐ qiú lì zāi
Wie könnte ich Gewinn daraus ziehen!
---------------------------------
於是 召 alle Schuldner
于是 召 alle Schuldner
yú shì xī zhào zhài jiā
Daraufhin bestellte er alle Schuldner ein
---------------------------------
為_酒食
为设酒食
wèi shè jiǔ shí
und bereitete Getränke und Essen für sie vor.
---------------------------------
對之 verbrennen 契曰
对之 verbrennen 契曰
duì zhī fán qì yuē
Vor ihnen verbrannte er die Schuldscheine und sagte:
---------------------------------
契了矣,
契了矣,
qì le yǐ,
Die Schuldscheine haben sich erledigt.
---------------------------------
幸勿為念也。
幸勿为念也。
xìng wù wèi niàn yě.
Es wäre nett, wenn sie nicht weiter darüber sprechen würden.
---------------------------------
明年大熟,
明年大熟,
míng nián dà shú,
Das folgende Jahr war sehr warm (und es gab eine gute Ernte).
---------------------------------
Die Schuldner 爭來_ Qian,
Die Schuldner 争来偿 Qian,
zhài jiā zhēng lái cháng qiān,
Die Schuldner wollten kommen und alles Qian zurückzahlen.
---------------------------------
Qian 拒之,
qiān jù zhī,
Qian widersprach.
---------------------------------
一無所受。
一无所受。
yī wú suǒ shòu.
Es gab nicht ein Stück, das er annahm.
---------------------------------
====第一百一十七課====
第一百一十七课
dì yī bǎi yī shí qī kè
Hundertsiebzehnte Lektion
------------------------------
田单
tián dān
Tian Dan ([[w:en:Tian_Dan|Wikipedia]])
------------------------------
燕 angreifen 齊
燕 angreifen 齐
yàn gōng qí
Yan griff Qi an.
------------------------------
下七十餘城
下七十余城
xià qī shí yú chéng
Es unterwarf mehr als 70 Städte.
------------------------------
田_守即墨以拒燕軍
田单守即墨以拒燕军
tián dān shǒu jí mò yǐ jù yàn jūn
Tian Dan verteidigte Jimo durch seinen Widerstand gegen die Armee von Yan.
------------------------------
收城中得千餘牛
收城中得千余牛
shōu chéng zhōng dé qiān yú niú
Er sammelte in der Stadt mehr als 1000 Rinder ein,
------------------------------
為 tiefrote Seide 衣
为 tiefrote Seide 衣
wèi jiàng zēng yī
stattete sie mit Kleidung aus tiefroter Seide aus,
------------------------------
畫以五__文
画以五彩龙文
huà yǐ wǔ cǎi lóng wén
die fünffarbig mit Drachenzeichen bemalt wurde.
------------------------------
束兵刃於其角
束兵刃于其角
shù bīng rèn yú qí jiǎo
Er band Waffenklingen an ihre Hörner.
------------------------------
Begossen mit Fett 束 Schilf 於尾
Begossen mit Fett 束 Schilf 于尾
guàn zhī shù wěi yú wěi
Er band fettgetränktes Schilf an ihre Schwänze,
------------------------------
燒其 Ende
烧其 Ende
shāo qí duān
die an ihrem Ende angezündet wurden.
------------------------------
_城數十穴
凿城数十穴
záo chéng shù shí xué
Er durchbrach die Stadtmauer an 10 Stellen (Löchern).
------------------------------
夜 loslassen 牛
yè zòng niú
Nachts ließ er die Rinder los;
------------------------------
Starke 士五千人隨其後。
Starke 士五千人随其后。
zhuàng shì wǔ qiān rén suí qí hòu.
5000 starke Kämpfer folgten hinter ihnen.
------------------------------
牛尾熱,
牛尾热,
niú wěi rè,
Die Rinderschwänze waren heiß.
------------------------------
怒而奔燕軍,
怒而奔燕军,
nù ér bēn yàn jūn,
Sie wurden wütend und rannten gegen die Armee von Yan.
------------------------------
燕軍大 erschrecken
燕军大 erschrecken
yàn jūn dà hài
Die Armee von Yan erschrak sehr .
------------------------------
败走
bài zǒu
Sie erlitten eine Niederlage und flohen.
------------------------------
七十餘城皆_為齊有
七十余城皆复为齐有
qī shí yú chéng jiē fù wèi qí yǒu
Alle diese mehr als 70 Städte fielen wieder in den Besitz von Qi.
------------------------------
== Texte ==
=== [https://archive.org/details/chinesemanualcom00dougiala A Chinese Manual: Dialog IV Teil 1 Seite 173 ] ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |
<br/>这衣裳齐整容貌标致.
<br/>你买不买.
<br/>价钱贱我也要买.
<br/>加减要紧.
}}
||
<br/> zhe4/zhei4 yi1 裳 qi2 zheng3 rong2 mao4 标 zhi4 .
<br/> ni3 mai3 bu4 mai3 .
<br/> jia4/jie4 qian2 jian4 wo3 ye3 yao4 mai3 .
<br/> jia1 jian3 yao4 jin3 .
||
<br/>These clothes are in good order, and the appearance is very graceful;
<br/>will you buy them or not?
<br/>If the price is cheap, then I should indeed wish to buy them.
<br/>The proportion of the ingredients is important.
|}
=== [https://archive.org/details/yyentzuerhchip02wadeuoft Colloquial Chinese 2: Excercise X-284 (traditionell)] ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |
<br/>臉盆是洗臉用的.
<br/>洗手用胰子就洗得乾淨了.
<br/>前兒個最熱我洗了六回臉.
<br/>給我一把木梳梳梳頭髮.
<br/>早起洗澡最好.
<br/>刷子.
}}
||
<br/> lian3 pen2 shi4 xi3/xian3 lian3 yong4 de5 .
<br/> xi3/xian3 shou3 yong4 yi2 zi5 jiu4 xi3/xian3 de2/de5/dei3 gan1/qian2 jing4 le5 .
<br/> qian2 er2/er5 ge4 zui4 re4 wo3 xi3/xian3 le5 liu4 hui2 lian3 .
<br/> gei3 wo3 yi1 ba3 mu4 shu1 shu1 shu1 tou2 髮.
<br/> zao3 qi3 xi3/xian3 zao3 zui4 hao3 .
<br/> shua1/shua4 zi5 .
||
<br/>A basin is used for washing the face.
<br/>In washing the hands, if you use soap you can wash them clean.
<br/>The day before yesterday was the hottest [we have had]; I washed my face six times.
<br/>Bring me a comb to comb my hair.
<br/>It is best to bathe early.
<br/>A brush.
|}
=== [https://ctext.org/analects/ens Analekte des Konfuzius] ===
{{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch | 子夏之门人问交于子张。子张曰:“子夏云何?”对曰:“子夏曰:‘可者与之,其不可者拒之。’”子张曰:“异乎吾所闻:君子尊贤而容众,嘉善而矜不能。我之大贤与,于人何所不容?我之不贤与,人将拒我,如之何其拒人也?” }}
Übersetzung James Legge
The disciples of Zi Xia asked Zi Zhang about the principles that should characterize mutual intercourse. Zi Zhang asked, "What does Zi Xia say on the subject?" They replied, "Zi Xia says: 'Associate with those who can advantage you. Put away from you those who cannot do so.'" Zi Zhang observed, "This is different from what I have learned. The superior man honors the talented and virtuous, and bears with all. He praises the good, and pities the incompetent. Am I possessed of great talents and virtue? - who is there among men whom I will not bear with? Am I devoid of talents and virtue? - men will put me away from them. What have we to do with the putting away of others?"
=== [https://ctext.org/yangzi-fayan/juan-yi/ens Yangzi Fayan -> Learning and Practice]===
{{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |
学者,所以修性也。视、听、言、貌、思,性所有也。学则正,否则邪。
}}
Englische Übersetzung siehe ctext.org
=== [https://ctext.org/yangzi-fayan/juan-yi Yangzi Fayan -> Learning and Practice (traditionell)]===
{{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |
學者,所以修性也。視、聽、言、貌、思,性所有也。學則正,否則邪。
}}
=== [http://museum.marcopoloproject.org/2013/04/09/%e5%81%9a%e4%b8%80%e4%b8%aa%e6%b2%a1%e6%9c%89%e8%81%8c%e4%b8%9a%e8%89%ba%e6%9c%af%e5%ae%b6%e7%9a%84%e7%99%bd%e6%97%a5%e6%a2%a6-the-daydream-of-a-non-professional-artist/ the marco polo project: 做一个没有职业艺术家的白日梦 – The daydream of a non-professional artist (Auszug)] ===
{{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |如果我们拒绝“职业艺术家”这种存在,那是不是很多问题就可以解决了呢?艺术商品化、体制化、艺术家生存问题、艺术形成其自身的封闭的意识形态等等⋯⋯<br/><br/>缘由是来自我两个MFA快毕业的艺术家室友,她们需要时间和空间去创作,所以她们不会接受一份全职工作,哪怕是与艺术相关。
}}
[http://museum.marcopoloproject.org/author/lucia/ Lucia] [http://www.douban.com/note/261418963/ Douban]
If we reject the idea that there is such a thing as a “professional artists”, can’t we start solving many questions? The commercialisation of art, the institutionalisation of art, the survival of artists, the closure of the art world around its own ideology, etc etc.
This reasoning comes from two of my room-mates at MFA, when they were about to complete their studies in fine arts: they need time and space to create, and therefore wouldn’t accept a full-time job, even if it was associated with the arts.
...
== [[s:en:Translation:Tao_Te_Ching | Tao Te Ching]] Kapitel 48 第四十八章 ==
{{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |
为学日益,
为道日损;
损之又损,
以至於无为;
无为而无不为矣。
故取天下者,
常以无事;
及其有事,
不足以取天下。
}}
=== Übersetzung Richard Wilhelm ===
Wer das Lernen übt, vermehrt täglich.
Wer den SINN übt, vermindert täglich.
Er vermindert und vermindert,
bis er schließlich ankommt beim Nichtsmachen.
Beim Nichtsmachen bleibt nichts ungemacht.
Das Reich erlangen kann man nur,
wenn man immer frei bleibt von Geschäftigkeit.
Die Vielbeschäftigten sind nicht geschickt,
das Reich zu erlangen.
=== Übersetzung [[s:en:Translation:Tao_Te_Ching | wikisource]] ===
Practicing scholarships, everyday there is something to gain,
Practicing the Dao, everyday there is something to lose;
When you lose all that can be lost,
You may be without action.
Act not and leave none to be acted upon!
Therefore those who can master the universe,
Often remain unoccupied;
Those who are preoccupied,
Cannot master the universe.
== Wiederholung Zeichen Tao Te Ching ==
keine neuen Zeichen
<noinclude>
{{Navigation zurückhochvor|
zurücktext=Lektion 557|
zurücklink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 557|
hochtext=Buch Vokabellektionen|
hochlink=Vokabeltexte_Chinesisch/_Vokabellektionen|
vortext=Lektion 559|
vorlink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 559}}
</noinclude>
5szamcrte1am7464tyyimuku79z10w8
Vokabeltexte Chinesisch/ Vokabellektionen/ Lektion 559
0
100975
1090851
1016437
2026-09-15T11:11:05Z
Christian-bauer
6469
kleinere Ergänzungen und Korrekturen
1090851
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor|
zurücktext=Lektion 558|
zurücklink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 558|
hochtext=Buch Vokabellektionen|
hochlink=Vokabeltexte_Chinesisch/_Vokabellektionen|
vortext=Lektion 560|
vorlink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 560}}
</noinclude>
== Zeichen ==
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung !! Lernhilfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |惵}} || die2 || Furcht, Spionage || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=惵}}
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒}} || du2 || Droge, Giftstoff, Gift, giftig, vergiften, toxisch, Narkotikum, grausam || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=毒}} (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽}} || shou4 || brutaler Mensch, roher Mensch, Barbar, barbarisch, Tier, tierisch, Biest, bestialisch || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=兽}}
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |勳}} || xun1 || (Variante von 勛/勋), Medaille, Orden, Verdienst, verdienstvolles Werk, Großtat, Merite || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=勳}}
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击}} || ji1 || angreifen, prügeln, schlagen, Schlag, Stoss || {{:Vokabeltexte_Chinesisch/ Vorlage:Texte_Zeichen_Externe_Links|Zeichen=击}}
|}
== Zusammengesetzte Wörter ==
=== 毒 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung !! Lernhilfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒饵}} || du2 er3 || Giftköder
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |犯毒}} || fan4 du2 || Betäubungsmittel, narkotisch
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒素}} || du2 su4 || Toxin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒蛇}} || du2 she2 || Giftschlange
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |流毒}} || liu2 du2 || schädlicher Einfluß, einen vergiftenden Einfluß haben, sich wie eine Seuche ausbreiten
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |去毒}} || qu4 du2 || Entgiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒虫}} || du2 chong2 || Giftinsekt
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |剧毒}} || ju4 du2 || hochgiftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品}} || du2 pin3 || Rauschmittel || (HSK 3.0 Band 6)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |狠毒}} || hen3 du2 || Boshaftigkeit, Herbheit, boshaft, heimtückisch, giftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |刻毒}} || ke4 du2 || Bitterkeit, Grausamkeit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒牙}} || du2 ya2 || Giftzahn
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |蛇毒}} || she2 du2 || Schlangengift
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冰毒}} || bing1 du2 || Ice, Methylamphetamin Hydrochlorid
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有毒}} || you3 du2 || giftig, toxisch || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |染毒}} || ran3 du2 || Kontamination, Vergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |无毒}} || wu2 du2 || ungiftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |無毒}} || wu2 du2 || (traditionelle Schreibweise von 无毒), ungiftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |戒毒}} || jie4 du2 || Drogenentzug
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吸毒}} || xi1 du2 || drogenabhängig || (HSK 3.0 Band 6)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒犯}} || du2 fan4 || Drogendealer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |解毒}} || jie3 du2 || entgiften
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |杀毒}} || sha1 du2 || Antivirus || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |殺毒}} || sha1 du2 || (traditionelle Schreibweise von 杀毒), Antivirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |身毒}} || yuan2 du2 || Indien (hist.)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |禁毒}} || jin4 du2 || Drogenverbot
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |梅毒}} || mei2 du2 || Syphilis
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒堇}} || du2 jin3 || Schierling
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒菇}} || du2 jun1 || (traditionelle Schreibweise von 毒菌), Giftpilz
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |消毒}} || xiao1 du2 || Desinfektion, Reinigung, Reinigungsmaterial, keimfrei machen, sterilisieren, steril, sterilisiert || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |阴毒}} || yin1 du2 || hinterhältig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |陰毒}} || yin1 du2 || (traditionelle Schreibweise von 阴毒), hinterhältig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒力}} || du2 li4 || Toxizität, Giftigkeit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒}} || bing4 du2 || Virus || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒性}} || du2 xing4 || Giftigkeit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |中毒}} || zhong4 du2 || Vergiftung || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |恶毒}} || e4 du2 || boshaft, heimtückisch, böswillig, giftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |惡毒}} || e4 du2 || (traditionelle Schreibweise von 恶毒), boshaft, heimtückisch, böswillig, giftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |水中毒}} || shui3 zhong1 du2 || Hyperhydration
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒性}} || bing4 du2 xing4 || viral
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |无毒的}} || wu2 du2 de5 || ungiftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |無毒的}} || wu2 du2 de5 || (traditionelle Schreibweise von 无毒的), ungiftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |内毒素}} || nei4 du2 su4 || Endotoxin, Endotoxine
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |內毒素}} || nei4 du2 su4 || (traditionelle Schreibweise von 内毒素), Endotoxin, Endotoxine
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒舌派}} || du2 she2 pai4 || scharfzüngig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒蛇似}} || du2 she2 si4 || giftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |解毒药}} || jie3 du2 yao4 || Antidot, Antidota, Gegengift
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |解毒藥}} || jie3 du2 yao4 || (traditionelle Schreibweise von 解毒药), Antidot, Antidota, Gegengift
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |解毒剂}} || jie3 du2 ji4 || Gegengift
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒物学}} || du2 wu4 xue2 || Toxikologie
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒物學}} || du2 wu4 xue2 || (traditionelle Schreibweise von 毒物学), Toxikologie
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒理学}} || du2 li3 xue2 || Toxikologie
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒理學}} || du2 li3 xue2 || (traditionelle Schreibweise von 毒理学), Toxikologie
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |反病毒}} || fan3 bing4 du2 || Antivirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒草名}} || du2 cao3 ming2 || Schierling, Schierling
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有毒的}} || you3 du2 de5 || giftig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |铅中毒}} || qian1 zhong4 du2 || Bleivergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |鉛中毒}} || qian1 zhong4 du2 || (traditionelle Schreibweise von 铅中毒), Bleivergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |消毒水}} || xiao1 du2 shui3 || keimtötendes Mittel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |鱼中毒}} || yu2 zhong4 du2 || Fischvergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |魚中毒}} || yu2 zhong4 du2 || (traditionelle Schreibweise von 鱼中毒), Fischvergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒气室}} || du2 qi4 shi4 || Gaskammer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒氣室}} || du2 qi4 shi4 || (traditionelle Schreibweise von 毒气室), Gaskammer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |肉中毒}} || rou4 zhong1 du2 || Botulismus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |类病毒}} || lei4 bing4 du2 || Viroid
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |消毒剂}} || xiao1 du2 ji4 || Desinfektionsmittel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吸毒者}} || xi1 du2 zhe3 || Drogensüchtiger, Junkie
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汉他病毒}} || han4 ta1 bing4 du2 || Hanta-Virus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |漢他病毒}} || han4 ta1 bing4 du2 || (traditionelle Schreibweise von 汉他病毒), Hanta-Virus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品依赖}} || du2 pin3 yi1 lai4 || drogensüchtig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |虫媒病毒}} || chong2 mei2 bing4 du2 || Arbovirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |酒精中毒}} || jiu3 jing1 zhong4 du2 || Alkoholismus, Alkoholvergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |神经毒气}} || shen2 jing1 du2 qi4 || Nervengas
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |神經毒氣}} || shen2 jing1 du2 qi4 || (traditionelle Schreibweise von 神经毒气), Nervengas
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |农药中毒}} || nong2 yao4 zhong4 du2 || Pestizidvergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |農藥中毒}} || nong2 yao4 zhong4 du2 || (traditionelle Schreibweise von 农药中毒), Pestizidvergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒气暗杀}} || du2 qi4 an4 sha1 || Giftgasanschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒氣暗殺}} || du2 qi4 an4 sha1 || (traditionelle Schreibweise von 毒气暗杀), Giftgasanschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |神经毒素}} || shen2 jing1 du2 su4 || Nervengift
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |神經毒素}} || shen2 jing1 du2 su4 || (traditionelle Schreibweise von 神经毒素), Nervengift
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |水银中毒}} || shui3 yin2 zhong4 du2 || Quecksilbervergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |水銀中毒}} || shui3 yin2 zhong4 du2 || (traditionelle Schreibweise von 水银中毒), Quecksilbervergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |慢病毒属}} || man4 bing4 du2 shu3 || Lentiviren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |慢病毒屬}} || man4 bing4 du2 shu3 || (traditionelle Schreibweise von 慢病毒属), Lentiviren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有毒货物}} || you3 du2 huo4 wu4 || giftige Ladung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有毒貨物}} || you3 du2 huo4 wu4 || (traditionelle Schreibweise von 有毒货物), giftige Ladung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吸毒过量}} || xi1 du2 guo4 liang4 || Drogenüberdosis, Drogenexzess
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吸毒過量}} || xi1 du2 guo4 liang4 || (traditionelle Schreibweise von 吸毒过量), Drogenüberdosis, Drogenexzess
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有毒资产}} || you3 du2 zi1 chan3 || toxische Bankpapiere
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品过量}} || du2 pin3 guo4 liang4 || Drogenexzess
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品過量}} || du2 pin3 guo4 liang4 || (traditionelle Schreibweise von 毒品过量), Drogenexzess
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |无毒油墨}} || wu2 du2 you2 mo4 || lebensmittelechte Farbe
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |無毒油墨}} || wu2 du2 you2 mo4 || (traditionelle Schreibweise von 无毒油墨), lebensmittelechte Farbe
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |黄曲毒素}} || huang2 qu3 du2 su4 || Aflatoxin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |黃曲毒素}} || huang2 qu3 du2 su4 || (traditionelle Schreibweise von 黄曲毒素), Aflatoxin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒程序}} || bing4 du2 cheng2 xu4 || Virenprogramm
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒定义}} || bing4 du2 ding4 yi4 || Virusdefinition
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒定義}} || bing4 du2 ding4 yi4 || (traditionelle Schreibweise von 病毒定义), Virusdefinition
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吸毒人员}} || xi1 du2 ren2 yuan2 || Drogenabhängige
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |消毒药剂}} || xiao1 du2 yao4 ji4 || Desinfektionsmittel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |地面消毒}} || di4 mian4 xiao1 du2 || Bodensanierung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |有毒物质}} || you3 du2 wu4 zhi4 || Giftstoffe, Toxine
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒物公告}} || du2 wu4 gong1 gao4 || Giftanschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒警报}} || bing4 du2 jing3 bao4 || Viruswarnung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒警報}} || bing4 du2 jing3 bao4 || (traditionelle Schreibweise von 病毒警报), Viruswarnung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |轮状病毒}} || lun2 zhuang4 bing4 du2 || Rotaviren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |电脑病毒}} || dian4 nao3 bing4 du2 || Computervirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |電腦病毒}} || dian4 nao3 bing4 du2 || (traditionelle Schreibweise von 电脑病毒), Computervirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品交易}} || du2 pin3 jiao1 yi4 || Drogenhandel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |富马毒素}} || fu4 ma3 du2 su4 || Fumonisin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |富馬毒素}} || fu4 ma3 du2 su4 || (traditionelle Schreibweise von 富马毒素), Fumonisin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |食物中毒}} || shi2 wu4 zhong4 du2 || Lebensmittelvergiftung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |走私毒品}} || zou3 si1 du2 pin3 || Rauschgiftschmuggel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |黄病毒科}} || huang2 bing4 du2 ke1 || Flaviviridae
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |黃病毒科}} || huang2 bing4 du2 ke1 || (traditionelle Schreibweise von 黄病毒科), Flaviviridae
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒粒子}} || bing4 du2 li4 zi3 || Viruspartikel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒预警}} || bing4 du2 yu4 jing3 || Virenwarnung, Viruswarnung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒預警}} || bing4 du2 yu4 jing3 || (traditionelle Schreibweise von 病毒预警), Virenwarnung, Viruswarnung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒警告}} || bing4 du2 jing3 gao4 || Virenwarnung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |天花病毒}} || tian1 hua1 bing4 du2 || Pockenvirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒微粒}} || bing4 du2 wei1 li4 || Viruspartikel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |神女病毒}} || shen2 nü3 bing4 du2 || Norovirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |东邪西毒}} || dong1 xie2 xi1 du2 || Ashes of Time
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |東邪西毒}} || dong1 xie2 xi1 du2 || (traditionelle Schreibweise von 东邪西毒), Ashes of Time
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |消除毒剂}} || xiao1 chu2 du2 ji4 || Dekontamination, Dekontaminierung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品犯罪}} || du2 pin3 fan4 zui4 || Drogenkriminalität
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |恶毒行为}} || e4 du2 xing2 wei2 || übel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |惡毒行為}} || e4 du2 xing2 wei2 || (traditionelle Schreibweise von 恶毒行为), übel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |神经性毒剂}} || shen2 jing1 xing4 du2 ji4 || Nervengas
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |埃博拉病毒}} || ai1 bo2 la1 bing4 du2 || Ebola
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |圆环病毒科}} || yuan2 huan2 bing4 du2 ke1 || Circoviridae
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |国际禁毒日}} || guo2 ji4 jin4 du2 ri4 || Weltdrogentag(Rechtsw)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品注射器}} || du2 pin3 zhu4 she4 qi4 || Giftspritze
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |阿片类毒品}} || a1 pian4 lei4 du2 pin3 || Opiumdrogen, Drogen auf Opiumbasis
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |路易斯毒气}} || lu4 yi4 si1 du2 qi4 || Lewisit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |路易斯毒氣}} || lu4 yi4 si1 du2 qi4 || (traditionelle Schreibweise von 路易斯毒气), Lewisit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |玻那病毒科}} || bo1 na3 bing4 du2 ke1 || Bornavirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒性流感}} || bing4 du2 xing4 liu2 gan3 || Virusgrippe, Influenza
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |本雅病毒科}} || ben3 ya3 bing4 du2 ke1 || Bunyaviridae (eine Virus-Familie)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |病毒定义库}} || bing4 du2 ding4 yi4 ku4 || Virusdefinition
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |计算机病毒}} || ji4 suan4 ji1 bing4 du2 || Computervirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒树果实理论}} || du2 shu4 guo3 shi2 li3 lun4 || Früchte des vergifteten Baumes(Rechtsw), Zufallsfund(Rechtsw)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒樹果實理論}} || du2 shu4 guo3 shi2 li3 lun4 || (traditionelle Schreibweise von 毒树果实理论), Früchte des vergifteten Baumes(Rechtsw), Zufallsfund(Rechtsw)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |巴斯德消毒法}} || ba1 si1 de2 xiao1 du2 fa3 || Pasteurisierung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |阴险恶毒的人}} || yin1 xian3 e4 du2 de5 ren2 || Viper
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |陰險惡毒的人}} || yin1 xian3 e4 du2 de5 ren2 || (traditionelle Schreibweise von 阴险恶毒的人), Viper
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |西尼罗河病毒}} || xi1 ni2 luo2 he2 bing4 du2 || West-Nil-Virus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |西尼羅河病毒}} || xi1 ni2 luo2 he2 bing4 du2 || (traditionelle Schreibweise von 西尼罗河病毒), West-Nil-Virus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |节肢介体病毒}} || jie2 zhi1 jie4 ti3 bing4 du2 || Arbovirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |節肢介體病毒}} || jie2 zhi1 jie4 ti3 bing4 du2 || (traditionelle Schreibweise von 节肢介体病毒), Arbovirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |单股反链病毒目}} || dan1 gu3 fan3 lian4 bing4 du2 mu4 || Mononegavirales
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |后来被视为病毒}} || hou4 lai2 bei4 shi4 wei2 bing4 du2 || Trojanische Pferd
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |後來被視為病毒}} || hou4 lai2 bei4 shi4 wei2 bing4 du2 || (traditionelle Schreibweise von 后来被视为病毒), Trojanische Pferd
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |流行性感冒病毒}} || liu2 xing2 xing4 gan3 mao4 bing4 du2 || Influenzavirus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人类呼吸道融合病毒}} || ren2 lei4 hu1 xi1 dao4 rong2 he2 bing4 du2 || Respiratory-Syncytial-Virus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |无毒的印刷用化学药剂}} || wu2 du2 de5 yin4 shua4 yong4 hua4 xue2 yao4 ji4 || ungiftige Druckchemikalien
|}
=== 兽 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung !! Lernhilfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽类}} || shou4 lei4 || animalisch, tierisch
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |午兽}} || wu3 shou4 || Tier aus dem QQ-Game
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |野兽}} || ye3 shou4 || wildes Tier || (HSK 3.0 Band 7-9)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽药}} || shou4 yao4 || Medizin für Tiere (Medikamente), Tiermedizin (Heilmittel)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |幼兽}} || you4 shou4 || Wölfling, Flegel
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽医}} || shou4 yi1 || Tierarzt
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |林兽}} || lin2 shou4 || Waldtiere
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽性}} || shou4 xing4 || Bestialität, rabiat, bestialisch, barbarisch
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |走兽}} || zou3 shou4 || Vierfüßer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |魔兽}} || mo2 shou4 || Warcraft
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽皮}} || shou4 pi2 || Fell
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽人}} || shou4 ren2 || Therianthropie (Verwandlung eines Menschen in ein Tier)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽迷}} || shou4 mi2 || Furry
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |袋兽}} || dai4 shou4 || Beuteltier
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽欲}} || shou4 yu4 || Bestialität
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽耳}} || shou4 er3 || Kemonomimi, Gehör
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽骨}} || shou4 gu3 || tierische Knochen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽行}} || shou4 xing4 || Bestialität
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽王}} || shou4 wang2 || König der wilden Tiere
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |怪兽}} || guai4 shou4 || Monster, Monstrum, seltsames Biest, Ungetüm, Ungeheuer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |独角兽}} || du2 jiao3 shou4 || Einhorn
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |虎狮兽}} || hu3 shi1 shou4 || Tiger-Löwe-Kreuzung, "Tigon"
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |野兽派}} || ye3 shou4 pai4 || Fauvismus
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽力车}} || shou4 li4 che1 || Streitwagen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |肉食兽}} || rou4 shi2 shou4 || Raubtier
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽王星}} || shou4 wang2 xing1 || Jyu Oh Sei
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |寄生兽}} || ji4 sheng1 shou4 || Kiseiju
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |水龙兽}} || shui3 long2 shou4 || Lystrosaurus ("Schaufel-Echse", ein Dinosaurier)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |中兽医}} || zhong1 shou4 yi1 || traditioneller chinesischer Tierarzt, traditioneller chinesischer Tiermediziner, traditioneller chinesischer Veterinär
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |鸭嘴兽}} || ya1 zui3 shou4 || Schnabeltier
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽医学}} || shou4 yi1 xue2 || Tiermedizin, Veterinärmedizin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |半兽人}} || ban4 shou4 ren2 || Ork
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |野兽般}} || ye3 shou4 ban1 || bestialisch
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |斗兽场}} || dou4 shou4 chang3 || Amphitheater, Colosseum, Kolosseum, Tierkampfarena
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |斗兽士}} || dou4 shou4 shi4 || Gladiator
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |狮虎兽}} || shi1 hu3 shou4 || Liger (Kreuzung aus männlichem Löwen und weiblichem Tiger)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人面兽心}} || ren2 mian4 shou4 xin1 || Bestie in Menschengestalt
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |魔兽世界}} || mo2 shou4 shi4 jie4 || World of Warcraft
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |滴水嘴兽}} || di1 shui3 zui3 shou4 || Wasserspeier
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |困兽犹斗}} || kun4 shou4 you2 dou4 || sich in einer aussichtslosen Lage verzweifelt wehren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽名数目}} || shou4 ming2 shu4 mu4 || Sechshundertsechsundsechzig
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |真兽下纲}} || zhen1 shou4 xia4 gang1 || Höhere Säugetiere, Plazentatiere (lat: Eutheria, eine Unterklasse der Säugetiere)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |兽性的人}} || shou4 xing4 de5 ren2 || Biest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |中兽医学}} || zhong1 shou4 yi1 xue2 || Traditionelle Chinesische Tiermedizin, Traditionelle Chinesische Veterinärmedizin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |魔兽争霸}} || mo2 shou4 zheng1 ba4 || WarCraft
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |罗马斗兽场}} || luo2 ma3 dou4 shou4 chang3 || Kolosseum
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |怪兽电力公司}} || guai4 shou4 dian4 li4 gong1 si1 || Die Monster AG [ Pixar Studios ]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |人面兽心之人}} || ren2 mian4 shou4 xin1 zhi1 ren2 || Saukerl
|}
=== 勳 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |元勳}} || yuan2 xun1 || (traditionelle Schreibweise von 元勋), ein Mann von großem Verdienst, Gründer, Leute der ersten Stunde; Bsp.: (開國元勛) 开国元勋 -- ein Mann der ersten Stunde (bei der Gründung eines Landes)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |王勳}} || wang2 xun1 || (traditionelle Schreibweise von 王勋), Sunjong of Goryeo
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |勳爵}} || xun1 jue2 || (traditionelle Schreibweise von 勋爵), Lord
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |張勳}} || Zhang1 Xun1 || (traditionelle Schreibweise von 张勋), Zhang Xun (1854-1923), Qing loyalist general who attempted to restore the abdicated emperor Puyi 溥儀|溥仪[Pu3 yi2] to the throne in the Manchu Restoration of 1917 張勳復辟|张勋复辟[Zhang1 Xun1 Fu4 bi4]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |勳章}} || xun1 zhang1 || (traditionelle Schreibweise von 勋章), Auszeichnung, Medaille
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |高田勳}} || gao1 tian2 xun1 || (traditionelle Schreibweise von 高田勋), Isao Takahata
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |開國元勳}} || kai1 guo2 yuan2 xun1 || (traditionelle Schreibweise von 开国元勋), founding figure (of a country or dynasty), founding father, fig. also used of company or school etc
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |勝利勳章}} || sheng4 li4 xun1 zhang1 || (traditionelle Schreibweise von 胜利勋章), Sowjetischer Siegesorden
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |鐵十字勳章}} || tie3 shi2 zi4 xun1 zhang1 || (traditionelle Schreibweise von 铁十字勋章), Eisernes Kreuz
|}
=== 击 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung !! Lernhilfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击穿}} || ji1 chuan1 || Durchschlag (Elektrotechnik)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击回}} || ji1 hui2 || Rücklauf, zurückprallen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |鸟击}} || niao3 ji1 || Vogelschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |直击}} || zhi2 ji1 || Volltreffer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拍击}} || pai1 ji1 || Anschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |连击}} || lian2 ji2 || schlagen, abstoßen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拳击}} || quan2 ji2 || Faustkampf, Faustschlag, boxen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |轻击}} || qing1 ji1 || tippen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |双击}} || shuang1 ji1 || Doppelklick, doppelklicken
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |雷击}} || lei2 ji2 || Blitzschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |袭击}} || xi2 ji1 || jemanden überfallen, heimsuchen; Anschlag, Attacke, Angriff || (HSK 3.0 Band 7-9)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击下}} || ji1 xia4 || abschießen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |一击}} || yi1 ji1 || gelungener Streich
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |目击}} || mu4 ji2 || mit eigenen Augen sehen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击球}} || ji1 qiu2 || mit dem Schlagholz schlagen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击杀}} || ji1 sha1 || erschlagen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |游击}} || you2 ji2 || einen Partisanenkampf führen, Partisanen-
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击鼓}} || ji2 gu3 || trommeln
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |反击}} || fan3 ji1 || zurückschlagen || (HSK 3.0 Band 7-9)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |枪击}} || qiang1 ji1 || schießen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |点击}} || dian3 ji1 || drücken, drängen, drücken, treffen, klicken, anklicken, schlagen, erreichen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |电击}} || dian4 ji1 || Stromschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |痛击}} || tong4 ji2 || einen schweren Schlag versetzen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |回击}} || hui2 ji1 || Konter, Gegenangriff;parieren, entgegentreten
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |突击}} || tu2 ji2 || Ansturm || (HSK 3.0 Band 7-9)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击}} || chong1 ji2 || Schock || (HSK 3.0 Band 6)
|-
| rowspan='2'| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击}} || she4 ji1 || Schießsport, Dreharbeiten || rowspan='2'| (HSK 3.0 Band 5)
|-
| she4 ji2 || [entlassen, anfeuern, Dreharbeiten, filmen, Jagdpacht]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |叩击}} || kou4 ji1 || Anschlag, Perkussion, klopfen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击剑}} || ji2 jian4 || Fechten
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |敲击}} || qiao1 ji2 || pochen, schlagen, klopfen, trommeln
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |单击}} || dan1 ji1 || klicken, anklicken, mit einem Klick öffnen, einfaches Klicken, Einzelklick
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |还击}} || huan2 ji1 || Gegenangriff, zurückschlagen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击节}} || ji1 jie2 || sich mitreißen lassem
|-
| rowspan='2'| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击败}} || ji1 bai4 || Vereitelung
|-
| ji2 bai4 || [Schlag, Schlagbolzen, überwinden, schlagen]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击退}} || ji2 tui4 || schlagen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击落}} || ji2 luo4 || abschießen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |掌击}} || zhang3 ji2 || schlagen, Klaps
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |伏击}} || fu2 ji1 || Hinterhalt
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |打击}} || da3 ji1 || schlagen; angreifen, bekämpfen, brechen || (HSK 3.0 Band 5)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |误击}} || wu4 ji1 || Friendly Fire
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |重击}} || zhong4 ji2 || knuffen, knallen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |出击}} || chu1 ji1 || angreifen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击碎}} || ji1 sui4 || zerschmettern
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击倒}} || ji2 dao3 || überfahren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |技击}} || ji4 ji1 || Angriffs- und Verteidigungskunst der Kampfkünste
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |电击器}} || dian4 ji1 qi4 || Elektroschlagstock, Elektroschocker
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拳击场}} || quan2 ji1 chang3 || Reif
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |被袭击}} || bei4 xi2 ji1 || angegriffen, angreifen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |强击机}} || qiang2 ji1 ji1 || Stürmerin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击座}} || chong1 ji2 zuo4 || Stoßrosette
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |点击数}} || dian3 ji1 shu4 || Treffer, Clicks
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |打击地}} || fang4 dan3 de5 || (traditionelle Schreibweise von 放胆地), frei heraus, ohne Furcht
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |受打击}} || shou4 da3 ji1 || unterliegen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拳击手}} || quan2 ji1 shou3 || Boxer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |被击败}} || bei4 ji1 bai4 || bezwingen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |袭击者}} || xi2 ji1 zhe3 || Angreiferin
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |可击败}} || ke3 ji1 bai4 || überwindbar
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |突击队}} || tu1 ji1 dui4 || Kommando, Kommandotruppe, Kommandoeinheit, Sondereinsatztruppe
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |游击手}} || you2 ji2 shou3 || Shortstop
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拳击家}} || quan2 ji1 jia1 || Boxer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |枪击案}} || qiang1 ji1 an4 || Amoklauf
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |大打击}} || dai4 da3 ji1 || Grand Slam
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |四百击}} || si4 bai3 ji1 || Sie küssten und sie schlugen ihn
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击式}} || chong1 ji2 shi4 || ballistisch
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |目击者}} || mu4 ji1 zhe3 || Augenzeuge
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击层}} || chong1 ji1 ceng2 || Anschwemmung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |游击战}} || you2 ji1 zhan4 || Guerillakrieg
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |第一击}} || di4 yi1 ji1 || Erstschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击场}} || she4 ji1 chang3 || Schießplatz
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击力}} || chong1 ji1 li4 || Stoßkraft
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |突击队员}} || tu1 ji1 dui4 yuan2 || Angehöriger einer Kommandotruppe, Mitglied einer Kommandoeinheit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |目击作证}} || mu4 ji1 zuo4 zheng4 || Aussage, aussagen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |反手击球}} || fan3 shou3 ji1 qiu2 || Rücklauf
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |意外袭击}} || yi4 wai4 xi2 ji1 || überraschen, überraschend
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |警告射击}} || jing3 gao4 she4 ji1 || Warnschuss
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |袭击银行}} || xi2 ji2 yin2 xing2 || Banküberfall
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |击倒对手}} || ji2 dao3 dui4 shou3 || Knock-out
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |反戈一击}} || fang3 e1 yi1 ji1 || zur (moralisch überlegenen) Gegenseite wechseln
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |迎头痛击}} || ying2 tou2 tong4 ji2 || The Great American Bash
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击作用}} || chong1 ji2 zuo4 yong4 || Stoßkraft
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |加以打击}} || jia1 yi3 da3 ji1 || auferlegen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |给以打击}} || gei3 yi3 da3 ji1 || Abruf
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |突击步枪}} || tu1 ji1 bu4 qiang1 || Sturmgewehr
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |军事打击}} || jun1 shi4 da3 ji2 || Militäroffensive, Militärschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |法国拳击}} || fa3 guo2 quan2 ji1 || Savate
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |突然袭击}} || tu2 ran2 xi2 ji2 || überfallen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击命令}} || she4 ji2 ming4 ling4 || Schießbefehl
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |打击力度}} || da3 ji2 li4 du4 || Schlagkraft
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |枪击现场}} || qiang1 ji2 xian4 chang3 || Tatort
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击时间}} || chong1 ji2 shi2 jian1 || Einschwingzeit
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |声东击西}} || sheng1 dong1 ji1 xi1 || Ablenkungsmanöver, Finten im Osten, Angriff im Westen, im Osten Scheinmanöver veranstalten, im Westen angreifen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用拳一击}} || yong4 quan2 yi1 ji1 || Boxer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |突击虎式}} || tu1 ji1 hu3 shi4 || Sturmpanzer VI
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击武器}} || she4 ji1 wu3 qi4 || Schusswaffe
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击试验}} || chong1 ji1 shi4 yan4 || Kerbschlagprüfung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击位置}} || she4 ji1 wei4 zhi5 || Anschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |被枪击中}} || bei4 qiang1 ji1 zhong1 || durch Schüsse getroffen werden
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |打击乐器}} || da3 ji2 yue4 qi4 || Schlaginstrument
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不堪一击}} || bu4 kan1 yi1 ji2 || keinen Stoß vertragen können, keinerlei Kritik vertragen, schon beim ersten Schlag zusammenbrechen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |二次打击}} || er4 ci4 da3 ji2 || Zweitschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |鼓击乐团}} || gu3 ji1 yue4 tuan2 || The Strokes
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |文化冲击}} || wen2 hua4 chong1 ji1 || Kulturschock
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |敲击金属}} || qiao1 ji1 jin1 shu3 || Thrash Metal
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |指定打击}} || zhi3 ding4 da3 ji2 || Designated Hitter (Schlagmann im Baseball oder Softball, der für den Werfer einspringt)
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |游击队员}} || you2 ji1 dui4 yuan2 || Widerstandskämpfer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |严厉打击}} || yan2 li4 da3 ji1 || das Handwerk legen, energisch gegen… vorgehen, Kampf führen gegen
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拳击比赛}} || quan2 ji1 bi3 sai4 || Boxkampf
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |职业拳击手}} || zhi2 ye4 quan2 ji1 shou3 || Berufsboxer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击断续器}} || she4 ji1 duan4 xu4 qi4 || Unterbrechergetriebe
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |每点击成本}} || mei3 dian3 ji1 cheng2 ben3 || Pay per Click
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |校园枪击案}} || xiao4 yuan2 qiang1 ji2 an4 || Amoklauf in der Schule, Schulmassaker
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用鱼雷袭击}} || yong4 yu2 lei2 xi2 ji1 || torpedieren
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |自杀性袭击}} || zi4 sha1 xing4 xi2 ji1 || Selbstmordanschlag, Selbstmordattentat
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |报复性打击}} || bao4 fu4 xing4 da3 ji1 || Vergeltungsschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |从海底出击}} || cong2 hai3 di3 chu1 ji2 || Das Boot
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击类游戏}} || she4 ji1 lei4 you2 xi4 || Ballerspiel [Computer]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |命运的打击}} || ming4 yun4 de5 da3 ji1 || Schicksalsschlag
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |拳击运动员}} || quan2 ji1 yun4 dong4 yuan2 || Boxer
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |打击停经机}} || da3 ji2 ting2 jing1 ji1 || Abschlagplatine
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |射击运动员}} || she4 ji2 yun4 dong4 yuan2 || Schütze, Schießsportler
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |伊拉克游击战}} || yi1 la1 ke4 you2 ji1 zhan4 || Irakischer Widerstand
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |单击开始按钮}} || dan1 ji1 kai1 shi3 an4 niu3 || Schaltfläche "Start" anklicken
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |自杀性袭击者}} || zi4 sha1 xing4 xi2 ji1 zhe3 || Selbstmordattentäter
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |重量级拳击手}} || zhong4 liang4 ji2 quan2 ji1 shou3 || Schwergewicht
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |被雷电击中的}} || bei4 lei2 dian4 ji1 zhong1 de5 || vom Blitz getroffen werden
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |世界拳击协会}} || shi4 jie4 quan2 ji1 xie2 hui4 || World Boxing Association
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击式磨碎机}} || chong1 ji2 shi4 mo4 sui4 ji1 || Schlagwerkmühle
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |打击军事力量}} || da3 ji1 jun1 shi4 li4 liang5 || Gegenkraft
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |民间的射击比赛}} || min2 jian1 de5 she4 ji1 bi3 sai4 || Schützenfest
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |点击小图看大图}} || dian3 ji1 xiao3 tu2 kan4 da4 tu2 || Anklicken zum Vergrößern des Bildes, zum Betrachten des großen Bildes dieses kleine Bild anklicken
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |成功的突然袭击}} || cheng2 gong1 de5 tu1 ran2 xi2 ji1 || Coup
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |九一一袭击事件}} || jiu3 yi1 yi1 xi2 ji1 shi4 jian4 || Terroranschläge am 11. September 2001 in den USA
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |证人席目击者席}} || zheng4 ren5 xi2 mu4 ji1 zhe3 xi2 || Zeugenstand
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |冲击式冲击试验机}} || chong1 ji2 shi4 chong1 ji1 shi4 yan4 ji1 || Pendelschlagwerk
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |无冲击的机器起动}} || wu2 chong1 ji1 de5 ji1 qi4 qi3 dong4 || ruckfreier Maschinenanlauf
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |第一人称射击游戏}} || di4 yi1 ren2 cheng1 she4 ji1 you2 xi4 || Ego-Shooter
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |坚决打击流产女婴}} || jian1 jue2 da3 ji1 liu2 chan3 nü3 ying1 || ???
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用鼠标右键点击文件}} || yong4 shu3 biao1 you4 jian4 dian3 ji1 wen2 jian4 || mit der rechten Maustaste auf eine Datei klicken
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |用鼠标右键点击文件夹}} || yong4 shu3 biao1 you4 jian4 dian3 ji1 wen2 jian4 jia1 || mit der rechten Maustaste auf einen Ordner klicken
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |北京点击科技有限公司}} || bei3 jing1 dian3 ji1 ke1 ji4 you3 xian4 gong1 si1 || Dianji Ltd.
|}
== Sätze ==
=== 惵 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|}
=== 毒 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |您曾经食物中毒过吗?}} || nin2 ceng2 jing4 shi2 wu4 zhong1/zhong4 du2 guo4 ma5 ?|| Hatten Sie schon mal eine Lebensmittelvergiftung? (Mandarin, [https://tatoeba.org/eng/sentences/show/838537 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他服毒自杀了。}} || ta1 fu2 du2 zi4 sha1 le5 。|| Er brachte sich mit Gift um. Er hat sich mit Gift umgebracht. (Mandarin, [https://tatoeba.org/eng/sentences/show/762134 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Alois Alois] [https://tatoeba.org/eng/user/profile/wolfgangth wolfgangth])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |它有毒吗?}} || ta1/tuo2 you3 du2 ma5 ?|| Ist es giftig? (Mandarin, [https://tatoeba.org/eng/sentences/show/8215687 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她服毒自杀了。}} || ta1 fu2 du2 zi4 sha1 le5 。|| Sie hat sich mit Gift umgebracht. (Mandarin, [https://tatoeba.org/eng/sentences/show/426414 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |對毒品說不。}} || dui4 du2 pin3 shuo1 bu4 。|| Sage Nein zu Drogen. (Mandarin, [https://tatoeba.org/eng/sentences/show/827526 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |它有毒嗎?}} || ta1/tuo2 you3 du2 ma5 ?|| Ist es giftig? (Mandarin, [https://tatoeba.org/eng/sentences/show/8215687 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的实验室裡有所有最致命的毒。}} || ta1 de5 shi2 yan4 shi4 li3 you3 suo3 you3 zui4 zhi4 ming4 de5 du2 。|| In seinem Labor sind alle tödlichsten Gifte zu finden. (Mandarin, [https://tatoeba.org/eng/sentences/show/3706781 Tatoeba] [https://tatoeba.org/eng/user/profile/egg0073 egg0073] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |对毒品说不。}} || dui4 du2 pin3 shuo1 bu4 。|| Sage Nein zu Drogen. (Mandarin, [https://tatoeba.org/eng/sentences/show/827526 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他是个吸毒男。}} || ta1 shi4 ge4 xi1 du2 nan2 。|| He's a meth addict. (Mandarin, [https://tatoeba.org/eng/sentences/show/2513911 Tatoeba] [https://tatoeba.org/eng/user/profile/fenfang557 fenfang557] [https://tatoeba.org/eng/user/profile/Spamster Spamster])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我不吸毒。}} || wo3 bu4 xi1 du2 。|| Ich nehme keine Drogen. (Mandarin, [https://tatoeba.org/eng/sentences/show/6475443 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/mrtaistoi mrtaistoi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你怎么能如此狼毒?}} || ni3 zen3 me5 neng2 ru2 ci3 lang2 du2 ?|| Wie kannst du so grausam sein? (Mandarin, [https://tatoeba.org/eng/sentences/show/4144653 Tatoeba] [https://tatoeba.org/eng/user/profile/shanghainese shanghainese] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我们猜这是一种被蛇咬伤的毒。}} || wo3 men5 cai1 zhe4/zhei4 shi4 yi1 chong2/zhong3/zhong4 bei4 she2 yao3 shang1 de5 du2 。|| Wir vermuten, dass es sich um eine Vergiftung durch Schlangenbiss handelt. (Mandarin, [https://tatoeba.org/eng/sentences/show/811099 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |埃博拉是人类已知的最致命的病毒之一。}} || ai1 bo2 la1 shi4 ren2 lei4 yi3 zhi1 de5 zui4 zhi4 ming4 de5 bing4 du2 zhi1 yi1 。|| Ebola ist eines der tödlichsten Viren, die der Menschheit bekannt sind. (Mandarin, [https://tatoeba.org/eng/sentences/show/8563313 Tatoeba] [https://tatoeba.org/eng/user/profile/slo_oth slo_oth] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他误服了毒药。}} || ta1 wu4 fu2 le5 du2 yao4 。|| Er hat irrtümlich Gift genommen. (Mandarin, [https://tatoeba.org/eng/sentences/show/335226 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |口中有蜜,心中有毒。}} || kou3 zhong1/zhong4 you3 mi4 , xin1 zhong1/zhong4 you3 du2 。|| Honey in the mouth and poison in the heart. (Mandarin, [https://tatoeba.org/eng/sentences/show/2879789 Tatoeba] [https://tatoeba.org/eng/user/profile/Popolon Popolon] [https://tatoeba.org/eng/user/profile/Swift Swift])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他服毒自殺了。}} || ta1 fu2 du2 zi4 sha1 le5 。|| Er brachte sich mit Gift um. Er hat sich mit Gift umgebracht. (Mandarin, [https://tatoeba.org/eng/sentences/show/762134 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Alois Alois] [https://tatoeba.org/eng/user/profile/wolfgangth wolfgangth])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |一个差劲的厨师和下毒者唯一的不同在於他们的意图。}} || yi1 ge4 cha4/chai1 jing4 de5 厨 shi1 he2/he4/huo2 xia4 du2 zhe3 wei2/wei3 yi1 de5 bu4 tong2 zai4 yu2 ta1 men5 de5 yi4 tu2 。|| Der einzige Unterschied zwischen einem schlechten Koch und einem Giftmischer ist die Absicht. (Mandarin, [https://tatoeba.org/eng/sentences/show/727906 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/lilygilder lilygilder])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |您曾經食物中毒過嗎?}} || nin2 ceng2 jing4 shi2 wu4 zhong1/zhong4 du2 guo4 ma5 ?|| Hatten Sie schon mal eine Lebensmittelvergiftung? (Mandarin, [https://tatoeba.org/eng/sentences/show/838537 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |国家将对毒品政策进行改革。}} || guo2 jia1 jiang1/jiang4 dui4 du2 pin3 zheng4 策 jin4 hang2/xing2 gai3 ge2 。|| Der Staat wird seine Drogenpolitik reformieren. (Mandarin, [https://tatoeba.org/eng/sentences/show/5384772 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |國家將對毒品政策進行改革。}} || guo2 jia1 jiang1/jiang4 dui4 du2 pin3 zheng4 策 jin4 hang2/xing2 gai3 ge2 。|| Der Staat wird seine Drogenpolitik reformieren. (Mandarin, [https://tatoeba.org/eng/sentences/show/5384772 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这些点都是病毒集中的地方。}} || zhe4/zhei4 xie1 dian3 dou1/du1 shi4 bing4 du2 ji2 zhong1/zhong4 de5 de4/di4 fang1 。|| All those dots are viral focuses. (Mandarin, [https://tatoeba.org/eng/sentences/show/1397100 Tatoeba] [https://tatoeba.org/eng/user/profile/mtdot mtdot] [https://tatoeba.org/eng/user/profile/marcelostockle marcelostockle])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的電腦已經中了BraveSentry病毒。}} || wo3 de5 dian4 nao3 yi3 jing4 zhong1/zhong4 le5 BraveSentry bing4 du2 。|| My computer has been infected with BraveSentry. My computer has already been infected with the BraveSentry virus. (Mandarin, [https://tatoeba.org/eng/sentences/show/816682 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/BraveSentry BraveSentry] [https://tatoeba.org/eng/user/profile/tsp_2 tsp_2])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我知道您接下来会问:“您毒杀了多少人?”}} || wo3 zhi1 dao4 nin2 jie1 xia4 lai2 hui4 wen4 :“ nin2 du2 sha1 le5 duo1 shao3 ren2 ?”|| Und ich weiß, dass Sie als nächstes fragen werden: „Wie viele Menschen haben Sie vergiftet?“ (Mandarin, [https://tatoeba.org/eng/sentences/show/10002083 Tatoeba] [https://tatoeba.org/eng/user/profile/GlossaMatik GlossaMatik] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这条鱼没有毒。}} || zhe4/zhei4 tiao2 yu2 mei2/mo4 you3 du2 。|| Dieser Fisch ist nicht giftig. (Mandarin, [https://tatoeba.org/eng/sentences/show/336955 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品是国际性的问题。}} || du2 pin3 shi4 guo2 ji4 xing4 de5 wen4 ti2 。|| Das Drogenproblem ist international. (Mandarin, [https://tatoeba.org/eng/sentences/show/819828 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的电脑已经中了BraveSentry病毒。}} || wo3 de5 dian4 nao3 yi3 jing4 zhong1/zhong4 le5 BraveSentry bing4 du2 。|| My computer has been infected with BraveSentry. My computer has already been infected with the BraveSentry virus. (Mandarin, [https://tatoeba.org/eng/sentences/show/816682 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/BraveSentry BraveSentry] [https://tatoeba.org/eng/user/profile/tsp_2 tsp_2])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |许多国家对毒品具有严格的法律。}} || xu3 duo1 guo2 jia1 dui4 du2 pin3 ju4 you3 yan2 ge2 de5 fa3 lü4 。|| Zahlreiche Länder haben strenge Gesetze gegen Drogen. (Mandarin, [https://tatoeba.org/eng/sentences/show/1876947 Tatoeba] [https://tatoeba.org/eng/user/profile/street street] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品问题是国际性的。}} || du2 pin3 wen4 ti2 shi4 guo2 ji4 xing4 de5 。|| Das Drogenproblem ist international. (Mandarin, [https://tatoeba.org/eng/sentences/show/6774603 Tatoeba] [https://tatoeba.org/eng/user/profile/basilhan basilhan] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|}
=== 兽 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |Tom有兽医背景。}} || Tom you3 shou4 yi1 bei1/bei4 jing3 。|| Tom has a veterinary background. (Mandarin, [https://tatoeba.org/eng/sentences/show/4504477 Tatoeba] [https://tatoeba.org/eng/user/profile/egg0073 egg0073] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |如果狮子是百兽之王的话,鹰就是百鸟之王了。}} || ru2 guo3 shi1 zi5 shi4 bai3 shou4 zhi1 wang2 de5 hua4 , ying1 jiu4 shi4 bai3 niao3 zhi1 wang2 le5 。|| So, wie der Löwe König der Tiere ist, so ist der Adler der König der Vögel. (Mandarin, [https://tatoeba.org/eng/sentences/show/458836 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她长大后成为了一名兽医。}} || ta1 chang2/zhang3 da4 hou4 cheng2 wei2/wei4 le5 yi1 ming2 shou4 yi1 。|| Sie wurde Tierärztin. (Mandarin, [https://tatoeba.org/eng/sentences/show/802070 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |吾知其兽之名。}} || wu2 zhi1 qi2 shou4 zhi1 ming2 。|| Ich kenne den Namen dieses Tiers. (klassisch, [https://tatoeba.org/eng/sentences/show/1112051 Tatoeba] [https://tatoeba.org/eng/user/profile/shanghainese shanghainese] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |狮子是兽类之王的话,鹰就是鸟类之王。}} || shi1 zi5 shi4 shou4 lei4 zhi1 wang2 de5 hua4 , ying1 jiu4 shi4 niao3 lei4 zhi1 wang2 。|| Wenn der Löwe König der Landtiere ist, dann ist der Adler König der Vögel. (Mandarin, [https://tatoeba.org/eng/sentences/show/4613919 Tatoeba] [https://tatoeba.org/eng/user/profile/cranewang cranewang] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我的床下有怪兽。}} || wo3 de5 chuang2 xia4 you3 guai4 shou4 。|| Unter meinem Bett ist ein Monster. (Mandarin, [https://tatoeba.org/eng/sentences/show/9467048 Tatoeba] [https://tatoeba.org/eng/user/profile/BobbyLee BobbyLee] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆的小儿子要当兽医。}} || tang1 mu3 de5 xiao3 er2/er5 zi5 yao4 dang1/dang4 shou4 yi1 。|| Tom's youngest son wants to be a veterinarian. (Mandarin, [https://tatoeba.org/eng/sentences/show/9415203 Tatoeba] [https://tatoeba.org/eng/user/profile/BobbyLee BobbyLee] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |那时汤姆相当一个兽医。}} || na4/nei4 shi2 tang1 mu3 xiang1/xiang4 dang1/dang4 yi1 ge4 shou4 yi1 。|| Tom wanted to become a veterinarian. (Mandarin, [https://tatoeba.org/eng/sentences/show/6822762 Tatoeba] [https://tatoeba.org/eng/user/profile/basilhan basilhan] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |独角兽是一种美丽的怪物。}} || du2 jue2 shou4 shi4 yi1 chong2/zhong3/zhong4 mei3 li2/li4 de5 guai4 wu4 。|| Das Einhorn ist ein Fabelwesen. (Mandarin, [https://tatoeba.org/eng/sentences/show/1227141 Tatoeba] [https://tatoeba.org/eng/user/profile/tsayng tsayng] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |是我内在的兽性想要它。}} || shi4 wo3 nei4 zai4 de5 shou4 xing4 xiang3 yao4 ta1/tuo2 。|| Es ist das Tier in mir, das danach schreit. (Mandarin, [https://tatoeba.org/eng/sentences/show/803799 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Wolf Wolf])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我怕野兽。}} || wo3 pa4 野 shou4 。|| I'm scared of wild animals. (Mandarin, [https://tatoeba.org/eng/sentences/show/4265179 Tatoeba] [https://tatoeba.org/eng/user/profile/notabene notabene] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |狮子是万兽之王。}} || shi1 zi5 shi4 wan4 shou4 zhi1 wang2 。|| Der Löwe ist der König der Tiere. (Mandarin, [https://tatoeba.org/eng/sentences/show/784072 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |鸟兽好悲声,耳与人耳同也。}} || niao3 shou4 hao3 bei1 sheng1 , er3 yu3 ren2 er3 tong2 ye3 。|| Birds and beasts like tragic sounds, their ears are identical with the human ones. (klassisch, [https://tatoeba.org/eng/sentences/show/1063682 Tatoeba] [https://tatoeba.org/eng/user/profile/shanghainese shanghainese])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |狮子是百兽之王。}} || shi1 zi5 shi4 bai3 shou4 zhi1 wang2 。|| Der Löwe ist der König der Tiere. (Mandarin, [https://tatoeba.org/eng/sentences/show/710752 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo])
|}
=== 勳 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|}
=== 击 ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他把对手击倒了。}} || ta1 ba3 dui4 shou3 ji1 dao3 le5 。|| He knocked his opponent out. (Mandarin, [https://tatoeba.org/eng/sentences/show/363994 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/U2FS U2FS])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你听到了点击声吗?}} || ni3 ting1 dao4 le5 dian3 ji1 sheng1 ma5 ?|| Haben Sie das Klicken gehört? (Mandarin, [https://tatoeba.org/eng/sentences/show/818091 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |台风袭击了关东地区。}} || tai2 feng1 xi2 ji1 le5 guan1 dong1 de4/di4 qu1 。|| Der Taifun traf den Bezirk Kanto. (Mandarin, [https://tatoeba.org/eng/sentences/show/1776532 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的去世让他的太太大受打击。}} || ta1 de5 qu4 shi4 rang4 ta1 de5 tai4 tai4 da4 shou4 da3 ji1 。|| His death was great shock to his wife. (Mandarin, [https://tatoeba.org/eng/sentences/show/604452 Tatoeba] [https://tatoeba.org/eng/user/profile/xiuqin xiuqin] [https://tatoeba.org/eng/user/profile/CM CM])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他们报告目击了事故。}} || ta1 men5 bao4 gao4 mu4 ji1 le5 shi4 gu4 。|| They reported seeing the incident. (Mandarin, [https://tatoeba.org/eng/sentences/show/5574372 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |仔细检查后发现,该头骨被重击碎裂。}} || zi1 xi4 jian3 cha2 hou4 fa1 xian4 , gai1 tou2 gu3 bei4 chong2/zhong4 ji1 sui4 lie4 。|| After careful examination, it can be seen that the skull was smashed to pieces. (Mandarin, [https://tatoeba.org/eng/sentences/show/765686 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/sharris123 sharris123])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我们被两面夹击了。}} || wo3 men5 bei4 liang3 mian4 jia1/jia2 ji1 le5 。|| We were attacked from both sides. (Mandarin, [https://tatoeba.org/eng/sentences/show/5951355 Tatoeba] [https://tatoeba.org/eng/user/profile/xjjAstrus xjjAstrus] [https://tatoeba.org/eng/user/profile/sharris123 sharris123])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |一窝黄蜂袭击了孩子们。}} || yi1 wo1 huang2 feng1 xi2 ji1 le5 hai2 zi5 men5 。|| Ein Schwarm Hornissen hat die Kinder angegriffen. (Mandarin, [https://tatoeba.org/eng/sentences/show/872149 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Esperantostern Esperantostern])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |世上最好的小提琴是用雷击木造成的。}} || shi4 shang4 zui4 hao3 de5 xiao3 ti2 qin2 shi4 yong4 lei2 ji1 mu4 zao4 cheng2 de5 。|| The best violins are made with wood from trees that have been struck by lightning. (Mandarin, [https://tatoeba.org/eng/sentences/show/899403 Tatoeba] [https://tatoeba.org/eng/user/profile/U2FS U2FS] [https://tatoeba.org/eng/user/profile/krrk krrk])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |想成为一个好的击球手的话,你要在球场上时刻保持镇定,还要学会相信自己的直觉。}} || xiang3 cheng2 wei2/wei4 yi1 ge4 hao3 de5 ji1 qiu2 shou3 de5 hua4 , ni3 yao4 zai4 qiu2 chang3 shang4 shi2 ke4 bao3 chi2 zhen4 ding4 , hai2/huan2 yao4 xue2 hui4 xiang1/xiang4 xin4 zi4 ji3 de5 zhi2 jiao4/jue2 。|| To be a good batter, you've got to hang loose and follow your instincts. (Mandarin, [https://tatoeba.org/eng/sentences/show/372364 Tatoeba] [https://tatoeba.org/eng/user/profile/nickyeow nickyeow] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |奶奶去世让全家都受了打击。}} || nai3 nai3 qu4 shi4 rang4 quan2 jia1 dou1/du1 shou4 le5 da3 ji1 。|| Grandmother's passing away came as a great blow to the entire family. (Mandarin, [https://tatoeba.org/eng/sentences/show/2442220 Tatoeba] [https://tatoeba.org/eng/user/profile/ydcok ydcok] [https://tatoeba.org/eng/user/profile/FeuDRenais2 FeuDRenais2])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |开始下载时,请点击“保存”按钮。}} || kai1 shi3 xia4 zai3/zai4 shi2 , qing3 dian3 ji1 “ bao3 cun2 ” an4 niu3 。|| Auf „Speichern“ klicken, um mit dem Herunterladen zu beginnen. (Mandarin, [https://tatoeba.org/eng/sentences/show/3805027 Tatoeba] [https://tatoeba.org/eng/user/profile/rickjiang rickjiang] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我们这队5-4击败对手。}} || wo3 men5 zhe4/zhei4 dui4 5-4 ji1 bai4 dui4 shou3 。|| Unsere Mannschaft hat unseren Gegner 5 zu 4 geschlagen. (Mandarin, [https://tatoeba.org/eng/sentences/show/785291 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |停止射击。}} || ting2 zhi3 she4 ji1 。|| Hör auf zu schießen. (Mandarin, [https://tatoeba.org/eng/sentences/show/5092701 Tatoeba] [https://tatoeba.org/eng/user/profile/mirrorvan mirrorvan] [https://tatoeba.org/eng/user/profile/Hans_Adler Hans_Adler])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他目击了那件意外。}} || ta1 mu4 ji1 le5 na4/nei4 jian4 yi4 wai4 。|| Er war Zeuge des Unfalls. (Mandarin, [https://tatoeba.org/eng/sentences/show/805718 Tatoeba] [https://tatoeba.org/eng/user/profile/cherylting cherylting] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他用他的球拍击球。}} || ta1 yong4 ta1 de5 qiu2 pai1 ji1 qiu2 。|| Er schlug den Ball mit seinem Schläger. (Mandarin, [https://tatoeba.org/eng/sentences/show/876740 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他的评论简洁且击中要害。}} || ta1 de5 ping2 lun4 jian3 jie2 qie3 ji1 zhong1/zhong4 yao4 hai4 。|| Sein Kommentar war prägnant und sachdienlich. (Mandarin, [https://tatoeba.org/eng/sentences/show/1783896 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen] [https://tatoeba.org/eng/user/profile/Aldain Aldain])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他枪击了我。}} || ta1 qiang1 ji1 le5 wo3 。|| Er hat auf mich geschossen. (Mandarin, [https://tatoeba.org/eng/sentences/show/793302 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/al_ex_an_der al_ex_an_der])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |乔治击中了他的腹部。}} || qiao2 zhi4 ji1 zhong1/zhong4 le5 ta1 de5 fu4 bu4 。|| Schorsch boxte ihm in den Bauch. (Mandarin, [https://tatoeba.org/eng/sentences/show/840797 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |点击图片进入下一页!}} || dian3 ji1 tu2 pian4 jin4 ru4 xia4 yi1 ye4 !|| Klicken Sie auf das Bild, um zur nächsten Seite zu gelangen! (Mandarin, [https://tatoeba.org/eng/sentences/show/787562 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Sudajaengi Sudajaengi])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |枪击是在中午十二时左右开始的。}} || qiang1 ji1 shi4 zai4 zhong1/zhong4 wu3 shi2 er4 shi2 zuo3 you4 kai1 shi3 de5 。|| Die Schießerei begann etwa um zwölf Uhr mittags. (Mandarin, [https://tatoeba.org/eng/sentences/show/836339 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha] [https://tatoeba.org/eng/user/profile/Tickler Tickler])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |金融危机打击了所有经济行业。}} || jin1 rong2 wei1 ji1 da3 ji1 le5 suo3 you3 jing4 ji4 hang2/xing2 ye4 。|| Die Finanzkrise hat alle Bereiche der Wirtschaft in Mitleidenschaft gezogen. (Mandarin, [https://tatoeba.org/eng/sentences/show/805170 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Yorwba Yorwba])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |经理斥责了那个正重击桌子的男子。}} || jing4 li3 chi4 ze2 le5 na4/nei4 ge4 zheng4 chong2/zhong4 ji1 桌 zi5 de5 nan2 zi5 。|| The manager reprimanded the man who was pounding on the table. (Mandarin, [https://tatoeba.org/eng/sentences/show/824422 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这会打击我们的生意。}} || zhe4/zhei4 hui4 da3 ji1 wo3 men5 de5 sheng1 yi4 。|| This could hurt our business. (Mandarin, [https://tatoeba.org/eng/sentences/show/5613631 Tatoeba] [https://tatoeba.org/eng/user/profile/verdastelo9604 verdastelo9604] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆的头部受了重重的一击。}} || tang1 mu3 de5 tou2 bu4 shou4 le5 chong2/zhong4 chong2/zhong4 de5 yi1 ji1 。|| Tom received a heavy blow on the head. (Mandarin, [https://tatoeba.org/eng/sentences/show/2024197 Tatoeba] [https://tatoeba.org/eng/user/profile/fercheung fercheung] [https://tatoeba.org/eng/user/profile/CK CK])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |经理以重击桌子来斥责那名男子。}} || jing4 li3 yi3 chong2/zhong4 ji1 桌 zi5 lai2 chi4 ze2 na4/nei4 ming2 nan2 zi5 。|| The manager reprimanded the man by pounding on the table. (Mandarin, [https://tatoeba.org/eng/sentences/show/824428 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |汤姆想学拳击,但他妈妈觉得这太危险了。}} || tang1 mu3 xiang3 xue2 quan2 ji1 , dan4 ta1 ma1 ma1 jiao4/jue2 de2/de5/dei3 zhe4/zhei4 tai4 wei1 xian3 le5 。|| Tom will Boxen lernen, aber seine Mutter meint, dass es zu gefährlich ist. (Mandarin, [https://tatoeba.org/eng/sentences/show/7772622 Tatoeba] [https://tatoeba.org/eng/user/profile/jiangche jiangche] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |要说,就要说得有力量,使对方失去反击的能力。}} || yao4 shuo1 , jiu4 yao4 shuo1 de2/de5/dei3 you3 li4 liang2/liang4 , shi3/shi4 dui4 fang1 shi1 qu4 fan3 ji1 de5 neng2 li4 。|| If you're going to say it, you have to say it with force, and take away your opponent's ability to retaliate. (Mandarin, [https://tatoeba.org/eng/sentences/show/2367535 Tatoeba] [https://tatoeba.org/eng/user/profile/eastasiastudent eastasiastudent])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |"我是警察。你可以到警察局来吗?""为-为什麼?""你不能认为在市中心开枪射击不是犯罪行为?!"}} || " wo3 shi4 jing3 察。 ni3 ke3/ke4 yi3 dao4 jing3 察 ju2 lai2 ma5 ?"" wei2/wei4 - wei2/wei4 shi2 me5 ?"" ni3 bu4 neng2 ren4 wei2/wei4 zai4 shi4 zhong1/zhong4 xin1 kai1 qiang1 she4 ji1 bu4 shi4 犯 zui4 hang2/xing2 wei2/wei4 ?!"|| "This is the police. Would you mind coming down to the station?" "W-why?" "You can't think it's not a crime to go shooting guns off in the middle of town?!" (Mandarin, [https://tatoeba.org/eng/sentences/show/780349 Tatoeba] [https://tatoeba.org/eng/user/profile/Martha Martha])
|}
=== einzusortieren ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |不自由毋宁死}} || bù zì yóu wú nìng sǐ || Ohne Freiheit ist es besser zu sterben; ([[wikt:en:不自由毋宁死 |Wiktionary en]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |亚洲的安纳托利亚人开始穿着用兽皮制作的衣服帽子}} || ya4 zhou1 de5 an1 na4 tuo1 li4 ya4 ren2 kai1 shi3 chuan1 zhao2/zhe2 yong4 shou4 pi5 zhi4 zuo4 de5 yi1 fu2 mao4 zi5 || Asien: Die Menschen in Anatolien begannen aus Tierhäuten gemachte Kleider und Mützen zu tragen. ([[Vokabeltexte_Chinesisch/_Geschichtsdetails/ 8._Jahrtausend_v._Chr. |Geschichtsdetails]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |12.34毒蛇的种类!你们既是恶人,怎能说出好话来呢?因为心里所充满的,口里就说出来。}} || 12.34 du2 she2 de5 chong2/zhong3/zhong4 lei4 ! ni3 men5 ji4 shi4 e4/wu4 ren2 , zen3 neng2 shuo1 chu1 hao3 hua4 lai2 ne5 ? yin1 wei2/wei4 xin1 li3 suo3 chong1 man3 de5 , kou3 li3 jiu4 shuo1 chu1 lai2 。|| 12.34 Otternbrut! Wie könnt ihr Gutes reden, da ihr böse seid? Denn aus der Fülle des Herzens redet der Mund. ([[Diskussion:Vokabeltexte_Chinesisch/_Vokabellektionen#Das_Neue_Testament|Die Bibel - Matthäusevangelium]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |21.41他们说:要下毒手除灭那些恶人,将葡萄园另租给那按着时候交果子的园户。}} || 21.41 ta1 men5 shuo1 : yao4 xia4 du2 shou3 chu2 mie4 na4/nei4 xie1 e4/wu4 ren2 , jiang1/jiang4 pu2 tao2 yuan2 ling4 zu1 gei3 na4/nei4 an4 zhao2/zhe2 shi2 hou4 jiao1 guo3 zi5 de5 yuan2 yong4 。|| 21.41 Sie sagen zu ihm: Er wird jene Übeltäter übel umbringen, und den Weinberg wird er an andere Weingärtner verdingen, die ihm die Früchte abgeben werden zu ihrer Zeit. ([[Diskussion:Vokabeltexte_Chinesisch/_Vokabellektionen#Das_Neue_Testament|Die Bibel - Matthäusevangelium]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |集于走兽与为流行}} || ji2 yu2 zou3 shou4 yu3 wei2/wei4 liu2 hang2/xing2 ||sammelt sie (Kraft) sich in den vierfüßigen Tieren, so ermöglicht sie ihnen das Laufen und Rennen ([http://ctext.org/lv-shi-chun-qiu/zhs Lü Bu We] [http://www.zeno.org/pnd/119012251 Richard Wilhelm])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |喂兽之药,无出九门}} || wei4 shou4 zhi1 yao4 , wu2 chu1 jiu3 men2 ||Gifte um Säugetiere zu vergiften, dürfen nicht die neun Tore verlassen. ([http://ctext.org/lv-shi-chun-qiu/zhs Lü Bu We] [http://www.zeno.org/pnd/119012251 Richard Wilhelm])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |刃未接而欲已得矣}} || ren4 wei4 jie1 er2 yu4 yi3 de2/de5/dei3 yi3 ||Noch ehe die Klingen sich kreuzen, ist die Absicht erreicht. ([http://ctext.org/lv-shi-chun-qiu/zhs Lü Bu We] [http://www.zeno.org/pnd/119012251 Richard Wilhelm])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毋罪毋罪。}} || wu2 zui4 wu2 zui4 。||Do not punish those without crime. [https://tatoeba.org/eng/sentences/show/1108117 Tatoeba] [https://tatoeba.org/eng/user/profile/shanghainese shanghainese]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这些点都是病毒集中的地方。}} || zhe4/zhei4 xie1 dian3 dou1/du1 shi4 bing4 du2 ji2 zhong1/zhong4 de5 de4/di4 fang1 。||All those dots are viral focuses. [https://tatoeba.org/eng/sentences/show/1397100 Tatoeba] [https://tatoeba.org/eng/user/profile/mtdot mtdot] [https://tatoeba.org/eng/user/profile/marcelostockle marcelostockle]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |毒品是国际性的问题。}} || du2 pin3 shi4 guo2 ji4 xing4 de5 wen4 ti2 。||Das Drogenproblem ist international. [https://tatoeba.org/eng/sentences/show/819828 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我们猜这是一种被蛇咬伤的毒。}} || wo3 men5 cai1 zhe4/zhei4 shi4 yi1 chong2/zhong3/zhong4 bei4 she2 yao3 shang1 de5 du2 。||Wir vermuten, dass es sich um eine Vergiftung durch Schlangenbiss handelt. [https://tatoeba.org/eng/sentences/show/811099 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |这条鱼没有毒。}} || zhe4/zhei4 tiao2 yu2 mei2/mo4 you3 du2 。||Dieser Fisch ist nicht giftig. [https://tatoeba.org/eng/sentences/show/336955 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/xtofu80 xtofu80]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他是个吸毒男。}} || ta1 shi4 ge4 xi1 du2 nan2 。||He's a meth addict. [https://tatoeba.org/eng/sentences/show/2513911 Tatoeba] [https://tatoeba.org/eng/user/profile/fenfang557 fenfang557] [https://tatoeba.org/eng/user/profile/Spamster Spamster]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |口中有蜜,心中有毒。}} || kou3 zhong1/zhong4 you3 mi4 , xin1 zhong1/zhong4 you3 du2 。||Honey in the mouth and poison in the heart. [https://tatoeba.org/eng/sentences/show/2879789 Tatoeba] [https://tatoeba.org/eng/user/profile/Popolon Popolon] [https://tatoeba.org/eng/user/profile/Swift Swift]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |他误服了毒药。}} || ta1 wu4 fu2 le5 du2 yao4 。||Er hat irrtümlich Gift genommen. [https://tatoeba.org/eng/sentences/show/335226 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |你怎么能如此狼毒?}} || ni3 zen3 me5 neng2 ru2 ci3 lang2 du2 ?||Wie kannst du so grausam sein? [https://tatoeba.org/eng/sentences/show/4144653 Tatoeba] [https://tatoeba.org/eng/user/profile/shanghainese shanghainese] [https://tatoeba.org/eng/user/profile/Pfirsichbaeumchen Pfirsichbaeumchen]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |土人看见那毒蛇悬在他手上,就彼此说:这人必是个凶手,虽然从海里救上来,天理还不容他活着。}} || tu3 ren2 kan4 jian4/xian4 na4/nei4 du2 she2 xuan2 zai4 ta1 shou3 shang4 , jiu4 bi3 ci3 shuo1 : zhe4/zhei4 ren2 bi4 shi4 ge4 xiong1 shou3 , sui1 ran2 cong2 hai3 li3 jiu4 shang4 lai2 , tian1 li3 hai2/huan2 bu4 rong2 ta1 huo2 zhao2/zhe2 。||4 Als aber die Eingeborenen das Tier an seiner Hand hängen sahen, sagten sie zueinander: Jedenfalls ist dieser Mensch ein Mörder, welchen Dike, obschon er aus dem Meere gerettet ist, nicht leben läßt. ([[Diskussion:Vokabeltexte_Chinesisch/_Vokabellektionen#Das_Neue_Testament|Die Bibel - Apostelgeschichte]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |许多国家对毒品具有严格的法律。}} || xu3 duo1 guo2 jia1 dui4 du2 pin3 ju4 you3 yan2 ge2 de5 fa3 lü4 。||Zahlreiche Länder haben strenge Gesetze gegen Drogen. [https://tatoeba.org/eng/sentences/show/1876947 Tatoeba] [https://tatoeba.org/eng/user/profile/street street] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |她服毒自杀了。}} || ta1 fu2 du2 zi4 sha1 le5 。||Sie hat sich mit Gift umgebracht. [https://tatoeba.org/eng/sentences/show/426414 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/MUIRIEL MUIRIEL]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |里面有地上各样四足的走兽和昆虫,并天上的飞鸟;}} || li3 mian4 you3 de4/di4 shang4 ge4 yang4 si4 zu3 de5 zou3 shou4 he2/he4/huo2 kun1 chong2 , bing4 tian1 shang4 de5 fei1 niao3 ;||12 in welchem allerlei vierfüßige und kriechende Tiere der Erde waren und das Gevögel des Himmels. ([[Diskussion:Vokabeltexte_Chinesisch/_Vokabellektionen#Das_Neue_Testament|Die Bibel - Apostelgeschichte]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |我怕野兽。}} || wo3 pa4 野 shou4 。||I'm scared of wild animals. [https://tatoeba.org/eng/sentences/show/4265179 Tatoeba] [https://tatoeba.org/eng/user/profile/notabene notabene] [https://tatoeba.org/eng/user/profile/CK CK]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |野兽都聚在了一起。}} || 野 shou4 dou1/du1 ju4 zai4 le5 yi1 qi3 。||The wild beasts all gather. [https://tatoeba.org/eng/sentences/show/1360020 Tatoeba] [https://tatoeba.org/eng/user/profile/sadhen sadhen]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |狮子是万兽之王。}} || shi1 zi5 shi4 wan4 shou4 zhi1 wang2 。||Der Löwe ist der König der Tiere. [https://tatoeba.org/eng/sentences/show/784072 Tatoeba] [https://tatoeba.org/eng/user/profile/fucongcong fucongcong] [https://tatoeba.org/eng/user/profile/Manfredo Manfredo]
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |好鋼用在刀刃上}} || hao3 gang1 yong4 zai4 dao1 ren4 shang4 ||([[wikt:en:好鋼用在刀刃上|Wiktionary en]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |好钢用在刀刃上}} || hao3 gang1 yong4 zai4 dao1 ren4 shang4 ||([[wikt:en:好钢用在刀刃上|Wiktionary en]])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |则孤将弃国家,释群臣,服剑臂刃,变容貌,易名姓}} || ze2 gu1 jiang1/jiang4 qi4 guo2 jia1 , shi4 qun2 chen2 , fu2 jian4 bi4 ren4 , bian4 rong2 mao4 , yi4 ming2 xing4 ||So will ich allein mein Reich verlassen, all meine Diener ihrer Pflicht entbinden, ein Schwert umgürten und einen Dolch in die Hand nehmen, mich verkleiden und meinen Namen ändern. ([http://ctext.org/lv-shi-chun-qiu/zhs Lü Bu We] [http://www.zeno.org/pnd/119012251 Richard Wilhelm])
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |游刃有余}} || you2 ren4 you3 yu2 ||([[wikt:en:游刃有余|Wiktionary en]])
|}
== Lückentexte ==
=== [https://newchristianbiblestudy.org/de/bible/compare/chinese-union-s/german-elberfelder-1905/acts-of-the-apostles/28/ Bibel: Apostelgeschichte Kapitel 28] ===
{| class="wikitable"
! Chinese Union Version !! Übersetzung Rudolf Brockhaus (1856-1932)
|-
| 我们既已得救,才知道那岛名叫米利大。||1 Und als wir gerettet waren, da erfuhren wir, daß die Insel Melite heiße.
|-
| 土人看待我们,有非常的情分;因为当时下雨,天气又冷,就生火接待我们众人。||2 Die Eingeborenen aber erzeigten uns eine nicht gewöhnliche Freundlichkeit, denn sie zündeten ein Feuer an und nahmen uns alle zu sich wegen des eingetretenen Regens und wegen der Kälte.
|-
| 那时,保罗拾起一 gewisse Menge Reiser,放在火上,有一条毒蛇,因为热了出来,咬住他的手。||3 Als aber Paulus eine gewisse Menge Reiser zusammenraffte und auf das Feuer legte, kam infolge der Hitze eine Natter heraus und hängte sich an seine Hand.
|-
| 土人看见那毒蛇悬在他手上,就彼此说:这人必是个凶手,虽然从海里救上来,天理还不容他活着。||4 Als aber die Eingeborenen das Tier an seiner Hand hängen sahen, sagten sie zueinander: Jedenfalls ist dieser Mensch ein Mörder, welchen Dike, obschon er aus dem Meere gerettet ist, nicht leben läßt.
|-
| 保罗 nun 把那毒蛇, schüttelte es 在火里,并没有受伤。||5 Er nun schüttelte das Tier in das Feuer ab und erlitt nichts Schlimmes.
|-
| 土人想他必要 aufschwellen,或是忽然 hinfallen und 死了;看了多时,见他无害,就转念,说:他是个神。||6 Sie aber erwarteten, daß er aufschwellen oder plötzlich tot hinfallen würde. Als sie aber lange warteten und sahen, daß ihm nichts Ungewöhnliches geschah, änderten sie ihre Meinung und sagten, er sei ein Gott.
|-
| 离那地方不远,有田产是岛长部百流的;他接纳我们,尽情款待三日。||7 In der Umgebung jenes Ortes aber besaß der Erste der Insel, mit Namen Publius, Ländereien; der nahm uns auf und beherbergte uns drei Tage freundlich.
|-
| 当时,部百流的父亲患热病和 Ruhr befallen daniederlag。保罗进去,为他 beten,按手在他身上,治好了他。||8 Es geschah aber, daß der Vater des Publius, von Fieber und Ruhr befallen, daniederlag. Zu dem ging Paulus hinein, und als er gebetet hatte, legte er ihm die Hände auf und heilte ihn.
|-
| 从此,岛上其馀的病人也来,得了医治。||9 Als dies aber geschehen war, kamen auch die übrigen auf der Insel, welche Krankheiten hatten, herzu und wurden geheilt;
|-
| 他们又多方的尊敬我们;到了开船的时候,也把我们所需用的送到船上。||10 diese ehrten uns auch mit vielen Ehren, und als wir abfuhren, luden sie uns auf, was uns nötig war.
|-
| 过了三个月,我们上了亚力山大的船往前行;这船以丢斯双子为记,是在那海岛过了冬的。||11 Nach drei Monaten aber fuhren wir ab in einem alexandrinischen Schiffe, das auf der Insel überwintert hatte, mit dem Zeichen der Dioskuren.
|-
| 到了 Syrakus,我们停泊三日;||12 Und als wir in Syrakus gelandet waren, blieben wir drei Tage.
|-
| 又从那里绕行,来到 Rhegium。过了一天,起了南风,第二天就来到部丢利。||13 Von dort fuhren wir herum und kamen nach Rhegium; und da nach einem Tage sich ein Südwind erhob, kamen wir den zweiten Tag nach Puteoli,
|-
| 在那里遇见弟兄们,请我们与他们同住了七天。这样,我们来到罗马。||14 wo wir Brüder fanden und gebeten wurden, sieben Tage bei ihnen zu bleiben; und so kamen wir nach Rom.
|-
| 那里的弟兄们一听见我们的信息就出来,到 Appii-Forum 和三馆地方迎接我们。保罗见了他们,就感谢神,放心 und fasste Mut。||15 Und von dort kamen die Brüder, als sie von uns gehört hatten, uns bis Appii-Forum und Tres-Tabernä entgegen; und als Paulus sie sah, dankte er Gott und faßte Mut.
|-
| 进了罗马城,(有古卷在此有:百夫长把众 Gefangene 交给御营的统领,惟有)保罗蒙准和一个看守他的兵另住在一处。||16 Als wir aber nach Rom kamen, überlieferte der Hauptmann die Gefangenen dem Oberbefehlshaber; aber dem Paulus wurde erlaubt, mit dem Kriegsknechte, der ihn bewachte, für sich zu bleiben.
|-
| 过了三天,保罗请犹太人的首领来。他们来了,就对他们说:弟兄们,我虽没有做什么事干 wider 本国的百姓和我们祖宗的规条,却被 gefangen genommen,从 Jerusalem 解在罗马人的手里。||17 Es geschah aber nach drei Tagen, daß er die, welche die Ersten der Juden waren, zusammenberief. Als sie aber zusammengekommen waren, sprach er zu ihnen: Brüder! Ich, der ich nichts wider das Volk oder die väterlichen Gebräuche getan habe, bin gefangen aus Jerusalem in die Hände der Römer überliefert worden,
|-
| 他们 verhörten 我,就愿意释放我;因为在我身上,并没有该死的罪。罪。||18 welche, nachdem sie mich verhört hatten, mich loslassen wollten, weil keine Ursache des Todes an mir war.
|-
| 无奈犹太人不服,我不得已,只好上告於该撒,并非有什么事要 klagen wider 我本国的百姓。||19 Als aber die Juden widersprachen, war ich gezwungen, mich auf den Kaiser zu berufen, nicht als hätte ich wider meine Nation etwas zu klagen.
|-
| 因此,我请你们来见面说话,我原为以色列人所指望的,被这炼子 umgeben。||20 Um dieser Ursache willen nun habe ich euch herbeigerufen, euch zu sehen und zu euch zu reden; denn wegen der Hoffnung Israels bin ich mit dieser Kette umgeben.
|-
| 他们说:我们并没有接着从犹太来论你的信,也没有弟兄到这里来报给我们说你有什么不好处。||21 Sie aber sprachen zu ihm: Wir haben über dich weder Briefe von Judäa empfangen, noch ist jemand von den Brüdern hergekommen und hat uns über dich etwas Böses berichtet oder gesagt.
|-
| 但我们愿意听你的意见如何;因为这教门,我们 ist bekannt, daß 到处被 widersprochen 的。||22 Aber wir begehren von dir zu hören, welche Gesinnung du hast; denn von dieser Sekte ist uns bekannt, daß ihr allenthalben widersprochen wird.
|-
| 他们和保罗约定了日子,就有许多人到他的寓处来。保罗从早到晚,对他们讲论这事,证明神国的道,引 Moses 的律法和先知的书,以 Jesu 的事劝勉他们。||23 Als sie ihm aber einen Tag bestimmt hatten, kamen mehrere zu ihm in die Herberge, welchen er die Wahrheit auslegte, indem er das Reich Gottes bezeugte und sie zu überzeugen suchte von Jesu, sowohl aus dem Gesetz Moses' als auch den Propheten, von frühmorgens bis zum Abend.
|-
| 他所说的话,有信的,有不信的。||24 Und etliche wurden überzeugt von dem, was gesagt wurde, andere aber glaubten nicht.
|-
| 他们彼此不合,就散了;未散以先,保罗说了一句话,说: Trefflich hat 圣灵 zu 先知以赛亚向你们祖宗所说的话是不错的。||25 Als sie aber unter sich uneins waren, gingen sie weg, als Paulus ein Wort sprach: Trefflich hat der Heilige Geist durch Jesaias, den Propheten, zu unseren Vätern geredet und gesagt:
|-
| 他说:你去告诉这百姓说:你们听是要听见,却不明白;看是要看见,却不 wahrnehmen;||26 "Gehe hin zu diesem Volke und sprich: Hörend werdet ihr hören und nicht verstehen, und sehend werdet ihr sehen und nicht wahrnehmen.
|-
| 因为这百姓油蒙了心,耳朵 haben schwer gehört,眼睛闭着;恐怕眼睛看见,耳朵听见,心里明白,回转过来,我就医治他们。||27 Denn das Herz dieses Volkes ist dick geworden, und mit den Ohren haben sie schwer gehört, und ihre Augen haben sie geschlossen, damit sie nicht etwa mit den Augen sehen und mit den Ohren hören und mit dem Herzen verstehen und sich bekehren und ich sie heile."
|-
| 所以你们当知道,神这救恩,如今传给外邦人,他们也必听受。(有古卷在此有:||28 So sei euch nun kund, daß dieses Heil Gottes den Nationen gesandt ist; sie werden auch hören.
|-
| 保罗说了这话,犹太人议论纷纷的就走了。)||29 Und als er dies gesagt hatte, gingen die Juden weg und hatten viel Wortwechsel unter sich.
|-
| 保罗在自己所租的房子里住了足足两年。凡来见他的人,他全都接待,||30 Er aber blieb zwei ganze Jahre in seinem eigenen gemieteten Hause und nahm alle auf, die zu ihm kamen,
|-
| freimütig 传讲神国的道,将主 Jesus Christus 的事教导人,并没有人禁止。||31 indem er das Reich Gottes predigte und die Dinge, welche den Herrn Jesus Christus betreffen, mit aller Freimütigkeit ungehindert lehrte.
|}
=== Haenisch: Lehrgang der klassischen chinesischen Schriftsprache ===
==== 第四十課 ====
第四十课
dì sì shí kè
Vierzigste Lektion
Es ist auch die 41. Lektion im 国文二百课.
Das Thema ist eine Geschichte aus der Kindheit [[w:Sima_Guang|司馬光/司马光/Sima Guangs]](1019-1086).
-----------------------------------
司馬光七歲時.
司马光七岁时.
Sīmǎ guāng qī suì shí.
Sima guang, im Alter von sieben Jahren,
-----------------------------------
與群兒_庭前.
与群儿戏庭前.
Yǔ qún érxì tíng qián.
spielte mit einer Gruppe Jungen vor der Halle.
-----------------------------------
一兒失足.
一儿失足.
Yī ér shīzú.
Ein Junge stolperte.
-----------------------------------
Er fiel 入 tönernen Wassertrog 中. 衆_走.
Er fiel 入 tönernen Wassertrog 中. 众惊走.
Diē rù wèng zhōng. Zhòng jīng zǒu.
Er fiel in einen tönernen Wassertrog. Alle rannten erschrocken davon.
-----------------------------------
光取石击 Trog. Der Trog 破.
Guāng qǔshí jī wèng. Wèng pò.
Guang nahm einen Stein und hämmerte gegen den Trog. Der Trog brach.
-----------------------------------
水_流出. 兒得不死.
水尽流出. 儿得不死.
Shuǐ jìn liúchū. Er dé bùsǐ.
Das Wasser floss vollständig heraus, der Junge musste nicht sterben.
-----------------------------------
==== 第四十一課 ====
第四十一课
dì sì shí yī kè
Einundvierzigste Lektion
Sie kommt auch im [https://ctext.org/wiki.pl?if=en&chapter=225270 Qūhǎi zǒngmù tíyào, Rolle 35] vor.
Das Thema ist eine Geschichte aus der Kindheit [[w:en:Wen_Yanbo_(Song_dynasty)|文彥博/文彦博/Wen Yanbos]](1019-1086).
-----------------------------------
文彥博幼時與群兒__.
文彦博幼时与群儿击球.
Wén yànbó yòu shí yǔ qún er jī qiú.
In Wen Yanbos Kindheit spielte er mit einer Gruppe Jungen Ball.
-----------------------------------
Variante:
按文彥博幼時。與群兒 herumtollen。
按文彦博幼时。与群儿 herumtollen。
Àn wén yànbó yòu shí. Yǔ qún er xī.
In Wen Yanbos Kindheit tollte er mit einer Gruppe Jungen herum.
-----------------------------------
_落柱穴中.
球落柱穴中.
Qiú luò zhù xué zhōng.
Der Ball fiel in ein Pfostenloch.
-----------------------------------
Varianten:
球入穴中。
球入穴中。
Qiú rù xué zhōng.
Der Ball fiel in ein Loch.
-----------------------------------
Der gekickte Ball _入穴中。
Der gekickte Ball 滚入穴中。
Cù jū gǔn rù xué zhōng.
Der gekickte Ball rollte in ein Loch.
-----------------------------------
穴深.
穴深.
Xué shēn.
Das Loch war tief.
-----------------------------------
Mit der Hand fassen 之不得出.
Mit der Hand fassen 之不得出.
Tàn zhī bùdé chū.
Mit der Hand konnte man den Ball nicht herausholen.
-----------------------------------
群兒無_.
群儿无计.
Qún er wú jì.
Die Gruppe Jungen hatte keinen Plan.
-----------------------------------
彥博以水 begießen 之.
彦博以水 begießen 之.
Yàn bó yǐ shuǐ guàn zhī.
Yanbo begoss das Loch mit Wasser.
-----------------------------------
球遂 treibend 出.
Qiú suì fú chū.
Der Ball kam daraufhin auf dem Wasser schwimmend heraus.
-----------------------------------
Varianten:
用水 treiben 之而出。
Yòngshuǐ fú zhī ér chū.
Man nutzte Wasser, er trieb nach oben und kam heraus.
-----------------------------------
彥博用水 treiben 出。
彦博用水 treiben 出。
Yàn bó yòngshuǐ fú chū.
Yangbo nutzte Wasser, um in darauf treibend herauszuholen.
-----------------------------------
Nachwort:
與司馬光_ Trog 破水。以救小兒。
与司马光击 Trog 破水。以救小儿。
Yǔ sīmǎ guāng jī wèng pòshuǐ. Yǐ jiù xiǎo'ér.
Er ist wie Sima Guang, der gegen den Trog hämmerte, dass er brach und das Wasser auslief, damit er einen Jungen retten konnte.
-----------------------------------
皆稱幼慧
皆称幼慧
Jiē chēng yòu huì
Beide werden als intelligente Kinder gepriesen.
-----------------------------------
====第一百零七課====
第一百零七课
dì yī bǎi líng qī kè
Hundertsiebte Lektion
Diese Geschichte findet sich im [https://ctext.org/chun-qiu-zuo-zhuan/xi-gong-san-shi-san-nian/zh Chunqiu Zuozhuan, Überlieferung des Zuo zur Zeit der Frühling-und-Herbstperiode].
---------------------------------
[[w:zh:%E5%B7%A6%E4%BC%A0| Wikipedia zum Chunqiu Zuozhuan]]
《左传》,全称《春秋左氏传》,原名《左氏春秋》,汉朝时又名《春秋左氏》 , 《春秋内传》,《左氏》等,是一部编年体史书,记录古中国春秋时期中原各国的历史
“zuǒ zhuàn”, quán chēng “chūn qiū zuǒ shì zhuàn”, yuán míng “zuǒ shì chūn qiū”, hàn cháo shí yòu míng “chūn qiū zuǒ shì”, “chūn qiū nèi zhuàn”,“zuǒ shì” děng, shì yī bù biān nián tǐ shǐ shū, jì lù gǔ zhōng guó
Die "Überlieferung des Zuo", (vollständiger Name: "Überlieferung aus der Frühling-und-Herbstperiode von Herrn Zuo", ursprünglicher Name: "Herr Zuo: Frühling-und-Herbstperiode", in der Han-Zeit auch "Frühling-und-Herbstperiode von Herrn Zuo", "Zeitgenössische Überlieferung der Frühling-und-Herbstperiode" oder nur kurz "Herr Zuo" genannt) ist ein chronologisches Geschichtsbuch, in dem Geschichte aller Staaten der zentralchinesischen Ebene zur Zeit der Frühling-und-Herbstperiode des alten China niedergeschrieben ist.
-----------------------------------
Xian 高
xián gāo
Xian Gao
------------------------------------
[[w:zh:%E5%BC%A6%E9%AB%98| Wikipedia]]
Xian 高,春秋时期郑国商人
xián gāo, chūn qiū shí qí zhèng guó shāng rén
Xian Gao war ein Händler aus dem Staat Zheng zur Zeit der Frühling-und-Herbstperiode.
郑穆公元年(前627年) Xian 高往洛(Stadt)经商,在滑国遇见将袭击郑国的秦军
zhèng mù gōng yuán nián (qián 627 nián) xián gāo wǎng luò yì jīng shāng, zài huá guó yù jiàn jiāng xí jí zhèng guó de qín jūn
Im ersten Regierungsjahr des Fürsten Mu von Zheng (627 v. Chr.) war der Xian Gao unterwegs nach Luo, um Handel zu treiben.
Im (Klein)staat Hua traf er auf die Armee von Qin, die Zheng angreifen wollte.
Xian 高基于爱国,冒充郑国的使节
xián gāo jī yú àiguó, mào chōng zhèng guó de shǐ jié
Weil Xian Gao sein Vaterland liebte, gab er vor ein Abgesandter des Staates Zheng zu sein.
以四张熟牛皮和十二头肥牛 bewirten 秦军
yǐ sì zhāng shú niú pí hé shí èr tóu féi niú kào láo qín jūn
Mit vier Einheiten "heißer Kuhhaut" (chin. Gericht) und 12 fetten Kühen bewirtete er die Armee von Qin
Sympathie zeigen für 秦军孟明视、西乞术、白乙丙三位将领
wèi wèn qín jūn mèng míng shì, xī qǐ shù, bái yǐ bǐng sān wèi jiàng lǐng
um seine Sympathie für die drei Generäle Meng Mingshi, Xi Qishu und Bai Yibing zu auszudrücken.
以示郑国已预知秦军来袭
yǐ shì zhèng guó yǐ yù zhī qín jūn lái xí
und um zu zeigen, das der Staat Zheng bereits über den Angriff der Qin-Armee informiert war.
同时,他又急忙派人回国向郑穆公 benachrichtigen
tóng shí, tā yòu jí máng pài rén huí guó xiàng zhèng mù gōng bǐng gào
Gleichzeitig schickte er auch eiligst einen Boten in seinen Staat zurück, um den Zheng-Fürsten Mu zu benachrichtigen.
-----------------------------------
秦师袭郑
qín shī xí zhèng
Die Armee von Qin griff Zheng an.
-----------------------------------
及滑
及滑
jí huá
Sie erreichte Hua.
-----------------------------------
郑商人 Xian 高,
zhèng shāng rén xián gāo,
Der Händler Xian Gao aus Zheng
-----------------------------------
將市於周,
将市于周,
jiāng shì yú zhōu,
wollte auf dem Markt in Zhou handeln
-----------------------------------
遇之。
遇之。
yù zhī.
und traf sie.
-----------------------------------
Er gab vor, 郑君之命
jiǎo zhèng jūn zhī mìng
Er gab vor, auf Befehl des Fürsten von Zheng zu handeln,
-----------------------------------
以牛十二 bewirten 秦师
yǐ niú shí èr kào qín shī
um mit zwölf Rindern die Armee von Qin zu bewirten.
-----------------------------------
曰
曰
yuē
Er sagte:
-----------------------------------
寡君聞吾子
寡君闻吾子
guǎ jūn wén wú zi
Mein Fürst hörte, dass Sie, mein Herr,
-----------------------------------
將步師出於敝 Stadt
将步师出于敝 Stadt
jiāng bù shī chū yú bì yì
ihr Heer in Bewegung setzen wollen, um zu unserer (unwürdigen) Stadt zu gehen.
-----------------------------------
敢 bewirten 從者
敢 bewirten 从者
gǎn kào cóng zhě
Ich erlaube mir, ihr Gefolge zu bewirten.
-----------------------------------
且使告於_
且使告于郑
qiě shǐ gào yú zhèng
Auch ließ er Zheng informieren.
-----------------------------------
_人_備以_秦师
郑人设备以御秦师
zhèng rén shè bèi yǐ yù qín shī
Die Menschen von Zheng bereiteten sich vor, der Armee von Qin Widerstand zu leisten.
-----------------------------------
秦聞_有備
秦闻郑有备
qín wén zhèng yǒu bèi
Als Qin hörte, dass Zheng vorbereitet war,
-----------------------------------
乃不袭郑
nǎi bù xí zhèng
so griff es Zheng doch nicht an.
-----------------------------------
=== Frühling und Herbst des Lü Buwei ===
==== Wiederholung ====
{| class="wikitable"
|-
! [https://ctext.org/lv-shi-chun-qiu/meng-xia-ji/zhs Erster Sommermonat, 1. Kapitel] !! [http://www.zeno.org/nid/20009211411 Übersetzung Richard Wilhelm]
|-
|是月也,继长 erheben 高,|| In diesem Monat soll das Wachstum befördert, das Hohe erhoben werden.
|-
|无有坏隳。 || Kein Abbrechen und Einreißen soll stattfinden,
|-
|无起土功, || keine Erdarbeiten sollen unternommen werden,
|-
|无发大众,无伐大树。 || keine Menschenmengen sollen ausgesandt, keine großen Bäume sollen gefällt werden.
|-
|是月也,天子始 sich in dünnes Puerariatuch zu kleiden.。 || In diesem Monat beginnt der Himmelssohn, sich in dünnes Puerariatuch zu kleiden.
|-
|命野虞,出行田原, || Die Förster erhalten den Befehl, die Gefilde und Ebenen zu durchreisen
|-
|劳农劝民,无或失时。 || und die Bauern anzufeuern und das Volk zu ermahnen, die Zeit nicht ungenützt vorübergehen zu lassen.
|-
|命司徒, reisen zu 县鄙。|| Der Unterrichtsminister erhält den Befehl, in den Städten und Dörfern herumzureisen,
|-
|命农勉作,无伏于都。 ||um die Bauern zu fleißiger Arbeit anzuhalten und zu verhindern, daß sie sich in den Städten herumtreiben.
|-
|是月也,verjagen 兽无害五谷。 || In diesem Monat verjagt man die wilden Tiere, damit sie das Korn nicht schädigen,
|-
|无大田猎。 || doch sollen keine großen Jagden stattfinden.
|-
|农乃 bringen 麦 ein。 || Die Bauern bringen die Erstlinge der Weizenernte dar,
|-
|天子乃以 Schweinefleisch 尝麦,|| der Himmelssohn kostet den Weizen zusammen mit Schweinefleisch
|-
|先荐 in der inneren Halle des Ahnentempels。 || und opfert zuerst davon in der inneren Halle des Ahnentempels.
|}
=== [https://ctext.org/mengzi/zhs Mengzi] ===
==== Wiederholung ====
{| class="wikitable"
|-
! [https://ctext.org/mengzi/liang-hui-wang-i/zhs Mengzi, Liang Hui Wang I] !! [https://www.projekt-gutenberg.org/mongdsi/werke/titlepage.html Übersetzung Richard Wilhelm]
|-
| 梁 Hui 王曰: || König Hui von Liang sprach:
|-
| 寡人愿安承教。 || Ich will gelassen Eure Belehrung annehmen.
|-
| 孟子对曰: || Mong Dsï erwiderte:
|-
| 杀人以 Knüppel 与刃,有以异乎? || Ob man Menschen mordet mit einem Knüppel oder einem Messer: ist da ein Unterschied?
|-
| 曰:无以异也。 || Der König sprach: Es ist kein Unterschied.
|-
| 以刃与政,有以异乎? || Ob man sie mordet mit einem Messer oder durch Regierungsmaßregeln: ist da ein Unterschied?
|-
| 曰:无以异也。 || Der König sprach: Es ist kein Unterschied.
|-
| 曰: In der Hofküche 有肥肉,Ställe 有肥马, || Da hub Mong Dsï an: In der Hofküche ist fettes Fleisch und in den Ställen fette Pferde;
|-
| 民有饥色,野有 Verhungernde,|| in den Gesichtern der Leute wohnt die Not, auf dem Anger draußen wohnt der Tod:
|-
| 此 anleiten 兽而食人也。 || das heißt, die Tiere anleiten, Menschen zu fressen.
|-
| 兽相食,且人恶之。 || Die Tiere fressen einander, und die Menschen verabscheuen sie darum.
|-
| 为民父母,行政不免于 anleiten 兽而食人。 || Wenn nun ein Landesvater also die Regierung führt, daß er nicht vermeidet, die Tiere anzuleiten, Menschen zu fressen:
|-
| 恶在其为民父母也? || Worin besteht da seine Landesvaterschaft?
|-
| 仲尼曰: || Meister Kung hat einmal gesagt:
|-
| Wer 始作 Menschenbilder fertigte – um sie den Toten mit ins Grab zu geben – ,其无后乎! || Wer zuerst bewegliche Menschenbilder fertigte – um sie den Toten mit ins Grab zu geben – der müsse ohne Nachkommen geblieben sein!
|-
| 为其象人而用之也。 || Darum, daß er das Ebenbild des Menschen zu diesem Zweck mißbrauchte.
|-
| 如之何其使斯民饥而死也?|| Was würde er erst gesagt haben von einem, der seine Leute Not leiden und verhungern läßt!
|}
== Texte ==
=== Wikibook [[:en:Chinese_(Mandarin)/Lesson_8 | Chinese]]/[[Chinesisch:_Lektion_8|Chinesisch]] Lektion 8: Dialog ===
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |
<br/>楊勳:你今天好嗎?
<br/>何銘:我很好。
<br/>楊勳:你吃飯了嗎?
<br/>何銘:還沒。
<br/>楊勳:要不要一起去吃飯?
<br/>何銘:好啊。我昨天看到你跟一個女生去圖書館,她是誰?
<br/>楊勳:她是我的女朋友,她叫陳潔。
<br/>何銘:原來你有女朋友,這麼厲害啊!
<br/>楊勳:哪裡,不敢當。我們要去哪裡吃飯?
<br/>何銘:都可以
}}
||
<br/> yang2 勳: ni3 jin1 tian1 hao3 ma5 ?
<br/> he2 ming2 : wo3 hen3 hao3 。
<br/> yang2 勳: ni3 chi1 fan4 le5 ma5 ?
<br/> he2 ming2 : hai2/huan2 mei2/mo4 。
<br/> yang2 勳: yao4 bu4 yao4 yi1 qi3 qu4 chi1 fan4 ?
<br/> he2 ming2 : hao3 a1 。 wo3 zuo2 tian1 kan4 dao4 ni3 gen1 yi1 ge4 nü3/ru3 sheng1 qu4 tu2 shu1 guan3 , ta1 shi4 shei2 ?
<br/> yang2 勳: ta1 shi4 wo3 de5 nü3/ru3 peng2 you3 , ta1 jiao4 chen2 jie2 。
<br/> he2 ming2 : yuan2 lai2 ni3 you3 nü3/ru3 peng2 you3 , zhe4/zhei4 me5 li4 hai4 a1 !
<br/> yang2 勳: na3/na5/nei3 li3 , bu4 gan3 dang1/dang4 。 wo3 men5 yao4 qu4 na3/na5/nei3 li3 chi1 fan4 ?
<br/> he2 ming2 : dou1/du1 ke3/ke4 yi3
||
|}
== [[s:en:Translation:Tao_Te_Ching | Tao Te Ching]] Kapitel 49 第四十九章 ==
{{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |
圣人无常心,
以百姓心为心。
善者吾善之,
不善者吾亦善之。
德善矣,
信者吾信之,
不信者吾亦信之,
德信矣。
圣人在天下惵惵,
为天下浑其心。
百姓皆注其耳目,
圣人皆孩之。
}}
=== Übersetzung Richard Wilhelm ===
Der Berufene hat kein eigenes Herz.
Er macht das Herz der Leute zu seinem Herzen.
Zu den Guten bin ich gut,
zu den Nichtguten bin ich auch gut;
denn das Leben ist die Güte.
Zu den Treuen bin ich treu,
zu den Untreuen bin ich auch treu;
denn das Leben ist die Treue.
Der Berufene lebt in der Welt ganz still
und macht sein Herz für die Welt weit.
Die Leute alle blicken und horchen nach ihm.
Und der Berufene nimmt sie alle an als seine Kinder.
=== Übersetzung [[s:en:Translation:Tao_Te_Ching | wikisource]] ===
The master never close up their mind,
But base their mind on the people's mind.
Those kind, be kind to them,
Those unkind, be kind to them also.
Virtuous is being kind.
Those faithful, have faith in them,
Those unfaithful, have faith in them also.
Virtuous is having faith.
The master is always anxious with the world about,
And is concerned with the people.
The people attends to the master's words and expressions,
The master fosters all in innocence.
== Wiederholung Zeichen Tao Te Ching ==
{| class="wikitable"
|-
! Zeichen !! Pinyin !! Übersetzung
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |惵}} || die2 || Furcht
|-
| {{:Vokabeltexte_Chinesisch/ Vorlage:Chinesisch |注}} || zhu4 || gießen, Anmerkung
|}
<noinclude>
{{Navigation zurückhochvor|
zurücktext=Lektion 558|
zurücklink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 558|
hochtext=Buch Vokabellektionen|
hochlink=Vokabeltexte_Chinesisch/_Vokabellektionen|
vortext=Lektion 560|
vorlink=Vokabeltexte_Chinesisch/_Vokabellektionen/ Lektion 560}}
</noinclude>
9587tkp7hv2dkvnt229n1diepv9eb9s
Musterentwürfe zum gerichtlichen Mahnverfahren/ Zusatzhinweise zum gerichtlichen Mahnverfahren
0
102119
1090832
1090616
2026-09-14T12:02:00Z
Raimund Barkam
58500
1090832
wikitext
text/x-wiki
Die hier angegebenen Zusatzhinweise beziehen sich auf das gerichtliche Mahnverfahren und wurden den Büchern "BGB = 79. Auflage 2017" und "ZPO = 57. Auflage 2016" / "ZPO = 58. Auflage 2017" entnommen. Ebenso werden hier mit Unterstützung der genannten Bücher, die hier genannten Paragraphen durch Angabe aktueller Paragraphen geändert oder ergänzt und somit den gesetzgeberischen Regelungen angepasst und vervollständigt. Die Nachfolgend aufgeführten Zusatzhinweise wurden den beiden genannten Büchern entnommen und sollen die Paragraphen mit den Angaben lt. Gesetzestexten ergänzen:
:''' Paragraphen und Text lt. Buch ZPO - Zivilprozessordnung'''
ISBN 978-3-423-53106-1 (dtv) / ISBN 978-3-406-77913-8 (C. H. Beck)
::::::<Font Size="5"> '''1 Zivilprozessordnung'''</Font>
::::::In der Fassung der Bekanntmachung vom Dezember2005<sup>1)</sup>
:::::::(BGB1. I S.3202, ber. 2006 I S. 431 und 2007 I S. 1781)
<Font Size="3">                                                                  '''FNA 310-4'''
zuletzt geänd. durch Art. 14 G zur Modernisierung des notariellen Berufsrechts und zur Änd. weiterer<br>
Vorschriften v. 25.6.2021 (BGB1. I S. 2154)
<Font Size="4">                                                           '''Inhaltsübersicht'''
:::::::'''Buch 1. Allgemeine Vorschriften'''
::::::::: Abschnitt 1. Gerichte
:::::: Titel 1. Sachliche Zuständigkeit der Gerichte und Wertvorschriften
§   1        Sachliche Zuständigkeit<br>
§   2        Bedeutung des Wertes<br>
§   3        Wertfestsetzung nach freiem Ermessen<br>
§   4        Wertberechnung Nebenforderungen<br>
§   5        Mehrere Ansprüche<br>
§   6        Besitz; Sicherstellung; Pfandrecht<br>
§   7        Grunddienstbarkeit<br>
§   8        Pacht- oder Mietverhältnis<br>
§   9        Wiederkehrende Nutzungen oder Leistungen<br>
§   10        (weggefallen)<br>
§   11        Bindende Entscheidung über Unzuständigkeit<br>
:::::: Titel 2. Gerichtsstand
§   12        Allgemeiner Gerichtsstand; Begriff<br>
§   13        Allgemeiner Gerichtsstand des Wohnsitzes<br>
§   14        (weggefallen)<br>
§   15        Allgemeiner Gerichtsstand für exterritoriale Deutsche<br>
§   16        Allgemeiner Gerichtsstand wohnungsloser Personen<br>
§   17        Allgemeiner Gerichtsstand juristischer Personen<br>
§   18        Allgemeiner Gerichtsstand des Fiskus<br>
§   19        Mehrere Gerichtsbezirke am Behördensitz<br>
§   19a      Allgemeiner Gerichtsstand des Insolvenzverwalters<br>
§   19b      Ausschließlicher Gerichtsstand bei restrukturierungsbezogenen Klagen;            Verordnungsermächtigung<br>
§   20        Besonderer Gerichtsstand des Aufenthaltsorts<br>
§   21        Besonderer Gerichtsstand der Niederlassung<br>
§   22        Besonderer Gerichtsstand der Mitgliedschaft<br>
§   23        Besonderer Gerichtsstand des Vermögens und des Gegenstands<br>
§   24        Ausschließlicher dringlicher Gerichtsstand<br>
§   25        Dinglicher Gerichtsstand des Sachzusammenhanges<br>
§   26        Dinglicher Gerichtsstand für persönliche Klagen<br>
§   27        Besonderer Gerichtsstand der Erbschaft<br>
§   28        Erweiterter Gerichtsstand der Erbschaft<br>
§   29        Besonderer Gerichtsstand des Erfüllungsorts<br>
§   29a      Ausschließlicher Gerichtsstand bei Miet- und Pachträumen<br>
§   29b      (weggefallen)<br>
§   29c      Besonderer Gerichtsstand für Haustürgeschäfte<br>
§   30        Besonderer Gerichtsstand bei Beförderungen <br>
§   30a      Gerichtsstand bei Bergungsansprüchen<br>
§   31        Besonderer Gerichtsstand der Vermögensverwaltung<br>
§   32        Besonderer Gerichtsstand der unerlaubten Handlung<br>
§   32a      Ausschließlicher Gerichtsstand der Umwelteinwirkung<br>
§   32b      Ausschließlicher Gerichtsstand bei falschen, irreführenden oder unterlassenen öffentlichen Kapitalmarktinformationen<br>
§   32c      Ausschließlicher Gerichtsstand bei Musterfeststellungsverfahren<br>
§   33        Besonderer Gerichtsstand der Widerlege<br>
§   34        Besonderer Gerichtsstand des Hauptprozesses<br>
§   35        Wahl unter mehreren Gerichtsständen<br>
$   36        Gerichtliche Bestimmung der Zuständigkeit<br>
§   37        Verfahren bei gerichtlicher Bestimmung<br>
:::::: Titel 3. Vereinbarung über die Zuständigkeit der Gerichte
§   38        Zugelassene Gerichtsstandsvereinbarung<br>
§   39        Zuständigkeit infolge regenloser Verhandlung<br>
§   40        Unwirksame und unzulässige Gerichtsstandsvereinbarung<br>
:::::: Titel 4. Ausschließung und Ablehnung der Gerichtspersonen
§   41        Ausschluss von der Ausübung des Richteramtes<br>
§   42        Ablehnung eines Richters<br>
§   43        Verlust des Ablehnungsrechts<br>
§   44        Ablehnungsgesuch<br>
§   45        Entscheidung über das Ablehnungsgesuch<br>
§   46        Entscheidung des Rechtsmittel<br>
§   47        Unaufschiebbare Amtshandlungen<br>
§   48        Selbstablehnung: Ablehnung von Amts wegen<br>
§   49        Urkundsbeamte <br>
::::::: Abschnitt 2. Parteien
:::::: Titel 1. Parteifähigkeit; Prozessfähigkeit
§   50        Parteifähigkeit<br>
§   51        Prozessfähigkeit; gesetzliche Vertretung, Prozessführung<br>
§   52        Umfang der Prozessfähigkeit<br>
'''[bis 31.12.2022:]'''<br>
§   53         Prozessunfähigkeit bei Betreuung oder Pflegeschaft<br>
'''[bis 1.1.2023:]'''<br>
<i>§   53        Prozessfähigkeit bei rechtlicher Betreuung</i><br>
§   54        Besondere Ermächtigung zu Prozesshandlungen<br>
§   55        Prozessfähigkeit von Ausländern<br>
§   56        Prüfung von Amts wegen<br>
§   57        Prozesspfleger<br>
§   58        Prozesspfleger bei herrenlosem Grundstück oder Schiff<br>
:::::: Titel 2. Streitgenossenschaft
§   59        Streitgenossenschaft bei Rechtsgemeinschaft oder Identität des Grundes<br>
§   60        Streitgenossenschaft bei Gleichartigkeit der Ansprüche<br>
§   61        Wirkung der Streitgenossenschaft<br>
§   62        Notwendige Streitgenossenschaft<br>
§   63        Prozessbetrieb; Ladungen<br>
:::::: Titel 3. Beteiligung Dritter am Rechtsstreit
§   64        Hauptintervention<br>
§   65        Aussetzung des Hauptprozesses<br>
§   66        Nebenintervention<br>
§   67        Rechtsstellung des Nebenintervenienten<br>
§   68        Wirkung der Nebenintervention<br>
§   69        Streitgenössische Nebenintervention<br>
§   70        Beitritt des Nebenintervenienten<br>
§   71        Zwischenstreit über Nebenintervention<br>
§   72        Zulässigkeit der Streitverkündung<br>
§   73        Form der Streitverkündung<br>
§   74        Wirkung der Streitverkündung<br>
§   75        Gläubigerstreit<br>
§   76        Urheberbenennung bei Besitz<br>
§   77        Urheberbenennung bei Eigentumsbeeinträchtigung<br>
:::::: Titel 4. Prozessbevollmächtigte und Beistände
§   78        Anwaltsprozess<br>
§   78a     (weggefallen)<br>
§   78b     Notanwalt<br>
§   78c     Auswahl des Rechtsanwalts<br>
§   79        Parteiprozess<br>
§   80        Prozessvollmacht<br>
§   81        Umfang der Prozessvollmacht<br>
§   82        Geltung für Nebenverfahren<br>
§   83        Beschränkung der Prozessvollmacht<br>
§   84        Mehrere Prozessbevollmächtigte<br>
§   85        Wirkung der Prozessvollmacht<br>
§   86        Fortbestand der Prozessvollmacht<br>
§   87        Erlöschen der vollmacht<br>
§   88        Mangel der Vollmacht<br>
§   89        vollmachtloser Vertreter<br>
§   90        Beistand<br>
:::::: Titel 5. Prozesskosten
§   91        Grundsatz und Umsatz der Kostenpflicht<br>
§   91a     Kosten bei Erledigung der Hauptsache<br>
§   92        Kosten bei teilweisen Obsiegen<br>
§   93        Kosten bei sofortigem Anerkenntnis<br>
§   93a     (weggefallen)<br>
§   93b     Kosten bei Räumungsklagen<br>
§   94        Kosten bei übergegangenem Anspruch<br>
§   95        Kosten bei Säumnis oder Verschulden<br>
§   96        Kosten erfolgloser Angriffs- oder Verteidigungsmittel<br>
§   97        Rechtsmittelkosten<br>
§   98        Vergleichskosten<br>
§   99        Anfechtung von Kostenentscheidungen<br>
§ 100        Kosten bei Streitgenossen<br>
§ 101        Kosten einer Nebenintervention<br>
§ 102       (weggefallen)<br>
§ 103        Kostenfestsetzungsgrundlage; Kostenfestsetzungsantrag<br>
§ 104        Kostenfestsetzungsverfahren<br>
§ 105        Vereinfachter Kostenfestsetzungsbeschluss<br>
§ 106        Verteilung nach Quoten<br>
§ 107        Änderung nach Streitwertfestsetzung<br>
:::::: Titel 6. Sicherheitsleistung
§ 108        Art und Höhe der Sicherheit<br>
§ 109        Rückgabe der Sicherheit<br>
§ 110        Prozesskostensicherheit<br>
§ 111        Nachhaltige Prozesskostensicherheit<br>
§ 112        Höhe der Prozesskostensicherheit<br>
§ 113        Fristbestimmung für Prozesskostensicherheit<br>
:::::: Titel 7. Prozesskostenhilfe
§ 114        Voraussetzungen<br>
§ 115        Einsatz von Einkommen und Vermögen<br>
§ 116        Partei kraft Amtes; juristische Person; parteifähige Vereinigung<br>
§ 117        Antrag<br>
§ 118        Bewilligungsverfahren<br>
§ 119        Bewilligung<br>
§ 120        Festsetzung von Zahlungen<br>
§ 120a     Änderung der Bewilligung<br>
§ 121        Beiordnung eines Rechtsanwalts<br>
§ 122        Wirkung der Prozesskostenhilfe<br>
§ 123        Kostenerstattung<br>
§ 124        Aufhebung der Bewilligung<br>
§ 125        Einbeziehung der Kosten<br>
§ 126        Beitreibung der Rechtsanwaltskosten<br>
§ 127        Entscheidungen<br>
::::::: Abschnitt 3. Verfahren
:::::: Titel 1. Mündliche Verhandlung
§ 128        Grundsatz der Mündlichkeit; schriftliches Verfahren<br>
§ 128a      Verhandlung im Wege der Bild- und Tonübertragung<br>
§ 129        Vorbereitende Schriftsätze<br>
§ 129a     Anträge und Erklärungen zu Protokoll<br>
§ 130        Inhalt der Schriftsätze<br>
§ 130a      Elektronisches Dokument<br>
§ 130b      Gerichtliches elektronisches Instrument<br>
§ 130c      Formulare: Verordnungsermächtigung<br>
'''''[ab 1.1.2022:]'''''<br>
§ 130d      ''Nutzungspflicht für Rechtsanwälte und Behörden''<br>
§ 131        Beifügung von Urkunden<br>
§ 132        Fristen für Schriftsätze<br>
§ 133        Abschriften<br>
§ 134        Einsicht von Urkunden<br>
§ 135        Mitteilung von Urkunden unter Rechtsanwälten<br>
§ 136        Prozessleistung durch Vorsitzenden<br>
§ 137        Gang der mündlichen Verhandlung<br>
§ 138        Erklärungspflicht über Tatsachen; Wahrheitspflicht<br>
§ 139        Materielle Prozessleistung<br>
§ 140        Beanstandung von Prozessleistung oder Fragen<br>
§ 141        Anordnung des persönlichen Erscheinens<br>
§ 142        Anordnung der Urkundenvorlegung<br>
§ 143        Anordnung der Aktenübermittlung<br>
§ 144        Augenschein; Sachverständige<br>
§ 145        Prozesstrennung<br>
§ 146        Beschränkung auf einzelne Angriffs- und Verteidigungsmittel<br>
§ 147        Prozessverbindung<br>
§ 148        Aussetzung bei Vortrefflichkeit<br>
§ 149        Aussetzung bei Verdacht einer Straftat<br>
§ 150        Aufhebung von Trennung, Verbindung oder Aussetzung<br>
§ 151        (weggefallen)<br>
§ 152        Aussetzung bei Eheaufhebungsantrag<br>
§ 153        Aussetzung bei Vaterschaftsanfechtungsklage<br>
§ 154        Aussetzung bei Ehe- oder Kindschaftsstreit<br>
§ 155        Aufhebung der Aussetzung bei Verzögerung<br>
§ 156        Wiedereröffnung der Verhandlung<br>
§ 157        Untervertretung in der Verhandlung<br>
§ 158        Entfernung infolge Prozessleitungsanordnung<br>
§ 159        Protokollaufnahme<br>
§ 160        Inhalt des Protokolls<br>
§ 160a      Vorläufige Protokollaufzeichnung<br>
§ 161        Entbehrliche Feststellungen<br>
§ 162        Genehmigung des Protokolls<br>
§ 163        Wiedereröffnung der Verhandlung<br>
§ 164        Protokollberechtigung<br>
§ 165        Beweiskraft des Protokolls<br>
:::::::::Titel 2. Verfahren bei Zustellungen
:::::::Untertitel 1. Zustellungen von Amts wegen
§ 166        Zustellung<br>
§ 167        Rückwirkung der Zustellung<br>
§ 168        Aufgaben der Geschäftsstelle<br>
§ 169        Bescheinigung des Zeitpunktes der Zustellung; Beglaubigung<br>
§ 170        Zustellung an Vertreter<br>
'''''[ab 1.1.2023:]'''''<br>
§ 170a      ''Zustellung bei rechtlicher Betreuung''<br>
§ 171        Zustellung an Bevollmächtigte<br>
§ 172        Zustellung an Prozessbevollmächtigte<br>
§ 173        Zustellung durch Aushändigung an der Amtsstelle<br>
§ 174        Zustellung gegen Empfangsbekenntnis oder automatisierte Eingangsbestätigung<br>
§ 175        Zustellung durch Einschreiben mit Rückschein<br>
§ 176        Zustellungsauftrag<br>
§ 177        Ort der Zustellung<br>
§ 178        Ersatzzustellung in der Wohnung, in Geschäftsräumen oder Einrichtungen<br>
§ 179        Zustellung bei verweigerter Annahme<br>
§ 180        Ersatzzustellung durch Einlegen in den Briefkasten<br>
§ 181        Ersatzzustellung durch Niederlegung<br>
§ 182        Zustellungsurkunde<br>
§ 183        Zustellung im Ausland<br>
§ 184        Zustellungsbevollmächtigter: Zustellung durch Aufgabe zur Post<br>
§ 185        Öffentliche Zustellung<br>
§ 186        Bewilligung und Ausführung der öffentlichen Zustellung<br>
§ 187        Veröffentlichung der Benachrichtigung<br>
§ 188        Zeitpunkt der öffentlichen Zustellung<br>
§ 189        Heilung von Zustellungsmängeln<br>
§ 190        Einheitliche Zustellungsformulare<br>
:::::::Untertitel 2. Zustellungen auf Betreiben der Parteien
§ 191        Zustellung<br>
§ 192        Zustellung durch Gerichtsvollzieher<br>
§ 193        Ausführung der Zustellung<br>
§ 194        Zustellungsauftrag<br>
§ 195        Zustellung von Anwalt zu Anwalt<br>
§§ 195a-213a      weggefallen<br>
:::::::::Titel 3. Ladungen, Termine und Fristen
§ 214        Ladung zum Termin<br>
§ 215        Notwendiger Inhalt der Ladung zur mündlichen Verhandlung<br>
§ 216        Terminbestimmung<br>
§ 217        Ladungsfrist<br>
§ 218        Entbehrlichkeit der Ladung<br>
§ 219        Terminsort<br>
§ 220        Aufruf der Sache; versäumter Termin<br>
§ 221        Fristbeginn<br>
§ 222        Fristberechnung<br>
§ 223        (weggefallen)<br>
§ 224        Fristkürzung: Fristverlängerung<br>
§ 225        Verfahren bei Friständerung<br>
§ 226        Abkürzung von Zwischenfristen<br>
§ 227        Terminsänderung<br>
§ 228        (weggefallen)<br>
§ 229        Terminsänderung<br>
:::::::::Titel 4. Folgen der Versäumnis Rechtsbehelfsbelehrung: Wiedereinsetzung in den vorigen Stand
§ 230        Allgemeine Versäumungserfolge<br>
§ 231        Keine Androhung: Nachholung der Prozesshandlung<br>
§ 232        Behelfsbelehrung<br>
§ 233        Terminsänderung<br>
§ 234        Wiedereinsetzungsfrist<br>
§ 235        (weggefallen)<br>
§ 236        Wiedereinsetzungsantrag<br>
§ 237        Zuständigkeit für Wiedereinsetzung<br>
§ 238        Wiedereinsetzungsantrag<br>
:::::::::Titel 5. Unterbrechung und Aussetzung des Verfahrens
§ 239        Unterbrechung durch Tod der Partei<br>
§ 240        Unterbrechung durch Insolvenzverfahren<br>
§ 241        Unterbrechung durch Prozessunfähigkeit<br>
§ 242        Unterbrechung durch Nachfolge<br>
§ 243        Aufnahme bei Nachlasspflegschaft und Testamentsvollstreckung<br>
§ 244        Unterbrechung durch Anwaltsverlust<br>
§ 245        Unterbrechung durch Stillstand der Rechtspflege<br>
§ 246        Aussetzung bei Vertretung durch Prozessbevollmächtigten<br>
§ 247        Aussetzung bei abgeschnittenen Verkehr<br>
§ 248        Verfahren bei Aussetzung<br>
§ 249        Wirkung von Unterbrechung und Aussetzung<br>
§ 250        Form von Aufnahme und Anzeige<br>
§ 251        Ruhen des Verfahrens<br>
§ 251a      Säumnis beider Parteien; Entscheidung nach Lage der Akten<br>
§ 252        Rechtsmittel bei Aussetzung<br>
:::::::'''Buch 2. Verfahren im ersten Rechtszug'''
::::::::: Abschnitt 1. Verfahren vor den Landgerichten
:::::::::Titel 1. Verfahren bis zum Urteil
§ 253        Klageschrift<br>
§ 254        Stufenklage<br>
§ 255        Fristbestimmung im Urteil<br>
§ 256        Feststellungsklage<br>
§ 257        Klage auf künftige Zahlung oder Räumung<br>
§ 258        Klage auf wiederkehrende Leistungen<br>
§ 259        Klage wegen Besorgnis nicht rechtzeitigen Leistung<br>
§ 260        Anspruchshäufung<br>
§ 261        Rechtshängigkeit<br>
§ 262        Sonstige Wirkungen der Rechtshängigkeit<br>
§ 263        Klageänderung<br>
§ 264        Keine Klageänderung<br>
§ 265        Veräußerung oder Abtretung der Streitsache<br>
§ 266        Veräußerung eines Grundstücks<br>
§ 267        Vermutete Einwilligung in die Klageänderung<br>
§ 268        Unanfechtbarkeit der Entscheidung<br>
§ 269        Klagerücknahme<br>
§ 270        Zustellung; formlose Mitteilung<br>
§ 271        Zustellung der Klageschrift<br>
§ 272        Bestimmung der Verfahrensweise<br>
§ 273        Vorbereitung des Termins<br>
§ 274        Ladung der Parteien; Einlassungsfrist<br>
§ 275        Früher erster Termin<br>
§ 276        Schriftliches Vorverfahren<br>
§ 277        Klageerwiderung: Replik<br>
§ 278        Gütliche Streitbeilegung, Güterverhandlung, Vergleich<br>
§ 278a      Mediation, außergerichtliche Konfliktbeilegung<br>
§ 279        Mündliche Verhandlung<br>
§ 280        Abgesonderte Verhandlung über Zuverlässigkeit der Klage<br>
§ 281        Verweisung bei Unzuständigkeit<br>
§ 282        Rechtzeitigkeit des Vorbringen<br>
§ 283        Schriftsatzfrist für Erklärungen zur Vorbringen des Gegners<br>
§ 283a      Sicherungsanordnung<br>
§ 284        Schriftsatzfrist für Erklärungen zum Vorbringen des Gegners<br>
§ 285        Verhandlung nach Beweisaufnahme<br>
§ 286        Freie Beweiswürdigung<br>
§ 287        Schadensermittlung; Höhe der Forderung<br>
§ 288        Gerichtliches Geständnis<br>
§ 289        Zusätze beim Geständnis<br>
§ 290        Widerruf des Geständnisses<br>
§ 291        Offenkundige Tatsachen<br>
§ 292        Gesetzliche Vermutungen<br>
§ 292a      (weggefallen)<br>
§ 293        Fremdes Recht; Gewohnheitsrecht; Statuten<br>
§ 294        Glaubhaftmachung<br>
§ 295        Verfahrensrügen<br>
§ 296        Zurückweisung verspäteten Vorbringens<br>
§ 296a      Vorbringen nach Schluss der mündlichen Verhandlung<br>
§ 297        Form der Antragstellung<br>
§ 298        Aktenausdruck<br>
§ 298a      Elektronische Akte; Verordnungsermächtigung<br>
§ 299        Akteneinsicht; Abschriften<br>
§ 299a      Datenträgerarchiv<br>
:::::::::Titel 2. Urteil
§ 300        Endurteil<br>
§ 301        Teilurteil<br>
§ 302        Vorbehaltsurteil<br>
§ 303        Zwischenurteil<br>
§ 304        Zwischenurteil über den Grund<br>
§ 305        Urteil unter Vorbehalt erbrechtlich beschränkter Haftung<br>
§ 305a      Urteil unter Vorbehalt seerechtlich beschränkter Haftung<br>
§ 306        Verzicht<br>
§ 307        Anerkenntnis<br>
§ 308        Bindung an die Parteianträge<br>
§ 309        Erkennende Richter<br>
§ 310        Termin der Urteilsverkündung<br>
§ 311        Form der Urteilsverkündung<br>
§ 312        Anwesenheit der Parteien<br>
§ 313        Form und Inhalt des Urteils<br>
§ 313a      Weglassen von Tatbestand und Entscheidungsgründen<br>
§ 313b      Versäumnis-, Anerkenntnis- und Verzichtsurteil<br>
§ 314        Beweiskraft des Tatbestandes<br>
§ 315        Unterschrift des Richters<br>
§ 316        (weggefallen)<br>
§ 317        Urteilszustellung und -ausfertigung<br>
§ 318        Bindung des Gerichts<br>
§ 319        Berichtigung des Urteils<br>
§ 320        Berichtigung des Tatbestands<br>
§ 321        Ergänzung des Urteils<br>
§ 321a      Abhilfe bei Verletzung des Anspruchs auf rechtliches Gehör<br>
§ 322        Materielle Rechtskraft<br>
§ 323        Abänderung von Urteilen<br>
§ 323a      Abänderung von Vergleichen und Urkunden<br>
§ 323b      Verschärfte Haftung<br>
§ 324        Nachforderungsklage zur Sicherheitsleistung<br>
§ 325        Subjektive Rechtskraftwirkung<br>
§ 325a      Feststellungswirkung des Musterentscheids<br>
§ 326        Rechtskraft bei Nacherbfolge<br>
§ 327        Rechtskraft bei Testamentsvollstreckung<br>
§ 328        Anerkennung ausländischer Urteile-<br>
§ 329        Beschlüsse und Verfügungen<br>
:::::::::Titel 3. Versäumnisurteil
§ 330        Versäumnisurteil gegen den Kläger<br>
§ 331        Versäumnisurteil gegen den Beklagten<br>
§ 331a      Entscheidung nach Aktenlage<br>
§ 332        Begriff des Verhandlungstermins<br>
§ 333        Nichtverhandeln der erscheinenden Partei<br>
§ 334        Unvollständiges Verhandeln<br>
§ 335        Unzulässigkeit einer Versäumniserscheinung<br>
§ 336        Rechtsmittel bei Zurückweisung<br>
§ 337        Vertagung von Amts wegen<br>
§ 338        Einspruch<br>
§ 339        Einspruchsfrist<br>
§ 340        Einspruchsschrift<br>
§ 340a      Zustellung der Einspruchsschrift<br>
§ 341        Einspruchsprüfungbr>
§ 341a      Einspruchstermin<br>
§ 342        Wirkungen des zulässigen Einspruchs<br>
§ 343        Entscheidung nach Einspruch<br>
§ 344        Versäumniskosten<br>
§ 345        Zweites Versäumnisurteil<br>
§ 346        Verzicht und Zurücknahme des Einspruchs<br>
§ 347        Verfahren bei Widerklage und Zwischenstreit<br>
:::::::::Titel 4. Verfahren vor dem Einzelrichter
§ 348        Originärer Einzelrichter<br>
§ 348a      Obligatorischer Einzelrichter<br>
§ 349        Vorsitzender der Kammer für Handelssachen<br>
§ 350        Rechtsmittel<br>
§ 351-354 (weggefallen)<br>
:::::::::Titel 5. Allgemeine Vorschriften über die Beweisaufnahme
§ 355        Unmittelbarkeit der Beweisaufnahme<br>
§ 356        Beibringungsfrist<br>
§ 357        Parteiöffentlichkeit<br>
§ 357a      (weggefallen)<br>
§ 358        Notwendigkeit eines Beweisschlusses<br>
§ 358a      Beschwerdeschluss und Beweisaufnahme vor mündlicher Verhandlung<br>
§ 359        Inhalt des Beweisschlussses<br>
§ 360        Änderung des Beweisschlusses<br>
§ 361        Beweisaufnahme durch beauftragten Richter<br>
§ 362        Beweisaufnahme durch ersuchten Richter<br>
§ 363        Beweisaufnahme im Ausland<br>
§ 364        Parteimitwirkung bei Beweisaufnahme im Ausland<br>
§ 365        Abgabe durch beauftragten oder ersuchten Richter<br>
§ 366        Zwischenstreit<br>
§ 367        Ausbleiben der Partei<br>
§ 368        Neuer Beweistermin<br>
§ 369        Ausländische Beweisaufnahme<br>
§ 370        Fortsetzung der mündlichen Verhandlung<br>
:::::::::Titel 6. Beweis durch Augenschein
§ 371        Beweis durch Augenschein<br>
§ 371a      Beweiskraft elektronischer Dokumente<br>
§ 371b      Beweiskraft gescannter öffentlicher Urkunden<br>
§ 372        Beweisaufnahme
§ 372a      Untersuchungen zur Feststellung der Abstammung<br>
:::::::::Titel 7. Zeugenbeweis
§ 373        Beweisantritt<br>
§ 374        (weggefallen)<br>
§ 375        Beweisaufnahme durch beauftragten oder ersuchten Richter<br>
§ 376        Vernehmung bei Amtsverschwiegenheit<br>
§ 377        Zeugenladung<br>
§ 378        Aussageerleichternde Unterlagen<br>
§ 379        Auslagenvorschuss<br>
§ 380        Folgen des Ausbleiben des Zeugen<br>
§ 381        Genügende Entschuldigung des Ausbleibens<br>
§ 382        Vernehmung an bestimmten Orten<br>
§ 383        Zeugnisverweigerung aus persönlichen Gründen<br>
§ 384        Zeugnisverweigerung aus sachlichen Gründen<br>
§ 385        Ausnahmen vom Zeugnisverweigerungsrecht<br>
§ 386        Erklärung der Zeugnisverweigerung<br>
§ 387        Zwischenstreit über Zeugnisverweigerung<br>
§ 388        Zwischenstreit über schriftliche Zeugnisverweigerung<br>
§ 389        Zeugnisverweigerung vor beauftragtem oder ersuchtem Richer<br>
§ 390        Folgen der Zeugnisverweigerung<br>
§ 391        Zeugenbeeidigung<br>
§ 392        Nacheid; Eidesnorm<br>
§ 393        Uneidliche Wahrnehmung<br>
§ 394        Einzelvernehmung<br>
§ 395        Wahrheitsermahnung, Vernehmung zur Person<br>
§ 396        Vernehmung zur Sache<br>
§ 397        Fragerecht der Parteien<br>
§ 398        Wiederholte und nachträgliche Vernehmung<br>
§ 399        Verzicht auf Zeugen<br>
§ 400        Befugnisse des mit der Beweisaufnahme betrauten Richters<br>
§ 401        Zeugenentschädigung<br>
:::::: Titel 8. Beweis durch Sachverständige
§ 402        Anwendbarkeit der Vorschriften für Zeugen<br>
§ 403        Beweisantritt<br>
§ 404        Sachverständigenauswahl<br>
§ 404a      Vorläufige Leitung der Tätigkeit des Sachverständigen<br>
§ 405        Auswahl durch den mit der Beweisaufnahme betrauten Richter<br>
§ 406        Ablehnung eines Sachverständigen<br>
§ 407        Pflicht zur Erstattung des Gutachtens<br>
§ 407a      Weitere Pflichten des Sachverständigen<br>
§ 408        Gutachtenverweigerungsrecht<br>
§ 409        Folgen des Ausbleibens oder der Gutachterverweigerung<br>
§ 410        Sachverständigenbeeidigung<br>
§ 411        Schriftliches Gutachten<br>
§ 411a      Verwertung von Sachverständigengutachten aus anderen Verfahren<br>
§ 412        Neues Gutachten<br>
§ 413        Sachverständigenvergütung<br>
§ 414        Sachverständige Zeugen<br>
:::::: Titel 9. Beweis durch Urkunden
§ 415        Beweiskraft öffentliche Urkunden über Erklärungen<br>
§ 416        Beweiskraft von Privaturkunden<br>
§ 417        Beweiskraft öffentlicher Urkunden über amtliche Anordnung, Verfügung oder Entscheidung<br>
§ 418        Beweiskraft öffentlicher Urkunden mit anderem Inhalt<br>
§ 419        Beweiskraft mangelbehafteter Urkunden<br>
§ 420        Vorlegung durch Beweisführer; Beweisantritt<br>
§ 421        Vorlegung durch den Gegner; Beweisantritt<br>
§ 422        Vorlegungspflicht des Gegners nach bürgerlichem Recht<br>
§ 423        Vorlegungspflicht des Gegners bei Bezugnahme<br>
§ 424        Antrag bei Vorlegung durch<br>
§ 425        Anordnung durch Vorlegung durch Gegner<br>
§ 426        Vernehmung des Gegners über den Verbleib<br>
§ 427        Folgen der Nichtvorlegung durch Gegner<br>
§ 428        Vorlegung durch Dritte; Beweisantriss<br>
§ 429        Vorlegungspflicht Dritter
§ 430        Antrag bei Vorlegung durch Dritte<br>
§ 431        Vorlegungsfrist bei Vorlegung durch Dritte<br>
§ 432        Vorlegung durch Behörden oder Beamte: Beweisantritt<br>
§ 433        (weggefallen)<br>
§ 434        Vorlegung vor beauftragtem oder ersuchtem Richter<br>
§ 435        Vorlegung öffentlicher Urkunden in Urschrift oder beglaubigter Abschrift<br>
§ 436        Verzicht nach Vorlegung<br>
§ 437        Echtheit inländischer öffentlicher Urkunden<br>
§ 438        Echtheit ausländischer öffentlicher Urkunden<br>
§ 439        Erklärung über Echtheit von Pribaturkunden<br>
§ 440        Beweis der Echtheit von Pribaturkunden<br>
§ 441        Schriftvergleichung<br>
§ 442        Würdigung der Schriftvergleichung<br>
§ 443        Verwahrung verdächtiger Urkunden<br>
§ 444        Folgen der Bereitung einer Urkunde<br>
:::::: Titel 10. Beweis durch Urkunden
§ 445        Vernehmung des Gegners: Beweisantritt<br>
§ 446        Weigerung des Gegners<br>
§ 447        Vernehmung der Beweispflichtigen Partei auf Antrag<br>
§ 448        Vernehmung von Amts wegen<br>
§ 449        Vernehmung von Streitgenossen<br>
§ 450        Besweisschluss<br>
§ 451        Ausführung der Vernehmung<br>
§ 452        Beeidigung der Partei<br>
§ 453        Beweiswürdigung bei Parteivernehmung <br>
§ 454        Ausbleiben der Partei <br>
§ 455        Prozessunfähige <br>
§§ 456-477 (weggefallen) <br>
:::::: Titel 11. Abnahme von Eiden und Bekräftigungen
§ 478        Eidesleistung in Person <br>
§ 479        Eidesleistung vor beauftragtem oder ersuchtem Richter <br>
§ 480        Eidesbelehrung <br>
§ 481        Eidesleistung: Eidesformel <br>
§ 482        (weggefallen) <br>
§ 483        Eidesleistung sprach- oder hörbehinderter Personen <br>
§ 484        Eidesgleiche Bekräftigung <br>
:::::: Titel 12. Selbständiges Beweisverfahren
§ 485        Zulässigkeit <br>
§ 486        Zuständiges Gericht <br>
§ 487        Inhalt des Antrages <br>
§§ 488,489 (weggefallen) <br>
§ 490        Entscheidung über den Antrag <br>
§ 491        Ladung des Gegners <br>
§ 492        Beweisaufnahme <br>
§ 493        Benutzung im Prozess <br>
§ 494        Unbekannter Gegner <br>
§ 494a      Frist zur Klageerhebung<br>
::::::::: Abschnitt 2. Verfahren vor den Amtsgerichten
§ 495        Anzuwendende Vorschriften <br>
§ 496        Einrichtung von Schriftsätzen; Erklärungen zu Protokoll <br>
§ 497        Ladungen <br>
§ 498        Zustellung des Protokolls über die Klage <br>
§ 499        Belehrungen <br>
§§ 499a-503 (weggefallen) <br>
§ 504        Hinweis bei Unzuständigkeit des Amtsgerichts <br>
§ 505        (weggefallen) <br>
§ 506        Nachträgliche sachliche Unzuständigkeit <br>
§§ 507-509 (weggefallen) <br>
§ 510        Erklärung über Urkunden <br>
§ 510a      Inhalt des Protokolls <br>
§ 510b      Urteil und Vornahme einer Handlung <br>
§ 510c      (weggefallen) <br>
:::::::'''Buch 3. Rechtsmittel'''
:::::::Abschnitt 1. Berufung
§ 511        Standhaftigkeit der Berufung <br>
§ 512        Vorentscheidungen im ersten Rechtszug <br>
§ 513        Berufungsgründe <br>
§ 514        Versäumnisurteile <br>
§ 515        Verzicht auf Berufung <br>
§ 516        Zurücknahme der Berufung <br>
§ 517        Berufungsfrist <br>
§ 518        Berufungsfrist bei Urteilsergänzung <br>
§ 519        Berufungsschrift <br>
§ 520        Berufungsbegründung <br>
§ 521        Zustellung der Berufungsschrift und -begründung <br>
§ 522        Zulässigkeitsprüfung; Zurückweisungsbeschluss <br>
§ 523        Terminsbestimmung <br>
§ 524        Anschlussberufung <br>
§ 525        Allgemeine Verfahrensgrundsätze <br>
§ 526        Entscheidender Richter <br>
§ 527        Vorbereitender Einzelrichter <br>
§ 528        Bindung an die Berufungsanträge <br>
§ 529        Prüfungsumfang des Berufungsgerichts <br>
§ 530        Verspätet vorgebrachte Angriffs- und Verteidigungsmittel <br>
§ 531        Zurückgewiesene und neue Angriffs- und Verteidigungsmittel <br>
§ 532        Rügen der Unzulässigkeit der Klage <br>
§ 533        Klageänderung ; Aufrechtserklärung; Widerlege <br>
§ 534        Verlust des Rügerechts <br>
§ 535        Gerichtliches Geständnis <br>
§ 536        Parteivernehmung <br>
§ 537        Vorläufige Vollstreckbarkeit <br>
§ 538        Zurückweisung <br>
§ 539        Versäumnisverfahren <br>
§ 540        Inhalt des Berufungsurteils <br>
§ 541        Prozessakten <br>
:::::::Abschnitt 2. Revision
§ 542        Standhaftigkeit der Revision <br>
§ 543        Zulassungsrevision <br>
§ 544        Nichtzulassungsbeschwerde <br>
§ 545        Revisionsgründe <br>
§ 546        Begriff der Rechtsverletzung <br>
§ 547        Absolute Revisionsgründe <br>
§ 548        Revisionsfrist <br>
§ 549        Revisionseinlegung <br>
§ 550        Zustellung der Revisionsschrift <br>
§ 551        Revisionsbegründung <br>
§ 552        Zulässigkeitsprüfung <br>
§ 552a      Zurückweisungsbeschluß <br>
§ 553        Terminbestimmung: Einlassungsfrist <br>
§ 554        Anschlußrevision <br>
§ 555        Allgemeine Verfahrensgrundsätze <br>
§ 556        Verlust des Rügerechts <br>
§ 557        Umfang der Revisionsprüfung <br>
§ 558        Vorläufige Vollstreckbarkeit <br>
§ 559        Beschränkte Nachprüfung tatsächlicher Feststellungen <br>
§ 560        Nicht reversible Gesetze <br>
§ 561        Revisionszurückweisung <br>
§ 562        Aufhebung des angefochtenen Urteils <br>
§ 563        Zurückverweisung; eigene Sachentscheidung<br>
§ 564        Keine Begründung der Entscheidung bei Rügen von Verfahrensmängeln <br>
§ 565        Anzuwendende Vorschriften des Berufungsverfahrens <br>
§ 566        Sprungrevision <br>
::::::::: Abschnitt 3. Beschwerde
:::::::: Titel 1. Sofortige Beschwerde
§ 567        Sofortige Beschwerde; Anschlussbeschwerde <br>
§ 568        Originärer Einzelrichter <br>
§ 569        Frist und Form <br>
§ 570        Aufschiebende Wirkung; einstweilige Anordnungen <br>
§ 571        Begründung, Präklusion, Ausnahmen vom Anwaltszwang <br>
§ 572        Gang des Beschwerdeverfahrens <br>
§ 573        Erinnerung <br>
:::::::: Titel 2. Rechtsbeschwerde
§ 574        Rechtsbeschwerde; Anschlussbeschwerde <br>
§ 575        Frist, Form und Begründung der Rechtsbeschwerde <br>
§ 576        Gründe der Rechtsbeschwerde <br>
§ 577        Prüfung und Entscheidung der Rechtsbeschwerde <br>
:::::::'''Buch 4. Wiederaufnahme des Verfahrens'''
§ 578        Arten der Wiederaufnahme <br>
§ 579        Nichtigkeitsklage <br>
§ 580        Restitutionsklage <br>
§ 581        Besondere Voraussetzungen der Restitutionsklage <br>
§ 582        Hilfsnatur der Restitutionsklage <br>
§ 583        Vorentscheidungen <br>
§ 584        Ausschließliche Zuständigkeit für Nichtigkeit- und Restitutionsklagen <br>
§ 585        Allgemeine Verfahrensgrundsätze <br>
§ 586        Klagefrist <br>
§ 587        Klageschrift <br>
§ 588        Inhalt der Klageschrift <br>
§ 589        Zulässigkeitsprüfung <br>
§ 590        Neue Verhandlung <br>
§ 591        Rechtsmittel <br>
:::::::'''Buch 5. Urkunden und Wechselprozess'''
§ 592        Zulässigkeit <br>
§ 593        Klageinhalt; Urkunden <br>
§ 594        (weggefallen) <br>
§ 595        Keine Widerklage; Beweismittel <br>
§ 596        Abstehen vom Urkundenprozess <br>
§ 597        Klageabweisung <br>
§ 598        Zurückweisung von Einwendungen <br>
§ 599        Vorbehaltsurteil <br>
§ 600        Nachverfahren <br>
§ 601        (weggefallen) <br>
§ 602        Wechselprozess <br>
§ 603        Gerichtsstand <br>
§ 604        Klageinhalt; Ladungsfrist <br>
§ 605        Beweisvorschriften <br>
§ 605a      Scheckprozess <br>
:::::::'''Buch 6. Musterfeststellungsverfahren'''
§ 606        Musterfeststellungsklage <br>
§ 607        Bekanntmachung der Musterfeststellungsklage <br>
§ 608        Anmeldung von Ansprüchen oder Rechtsverhältnissen <br>
§ 609        Klageregister; Verordnungsermächtigung <br>
§ 610        Besonderheiten der Musterfeststellungsklage <br>
§ 611        Vergleich <br>
§ 612        Bekanntmachungen zum Musterfeststellungsurteil <br>
§ 613        Bindungswirkung des Musterfeststellungsurteils; Aussetzung <br>
§ 614        Rechtsmittel <br>
§§ 615-687 (weggefallen) <br>
:::::::'''Buch 7. Mahnverfahren'''
§ 688        Zulässigkeit <br>
§ 689        Zuständigkeit; maschinelle Bearbeitung <br>
§ 690        Mahnantrag <br>
§ 691        Zurückweisung des Mahnantrags <br>
§ 692        Mahnbescheid <br>
§ 693        Zurückstellung des Mahnbescheids <br>
§ 694        Widerspruch gegen den Mahnbescheid <br>
§ 695        Mitteilung des Widerspruchs; Abschriften <br>
§ 696        Verfahren nach Widerspruch <br>
§ 697        Einleitung des Streitverfahrens <br>
§ 698        Abgabe des Vefahrens am selben Gericht <br>
§ 699        Vollstreckungsbescheid <br>
§ 700        Einspruch gegen den Vollstreckungsbescheid <br>
§ 701        Wegfall der Wirkung des Mahnbescheids <br>
§ 702        Form von Anträgen und Erkläriungen <br>
§ 703        Kein Nachweis der Vollmacht <br>
§ 703a      Urkunden Wechsel- und Scheckverfahren <br>
§ 703b      Sonderregelungen für maschinelle Bearbeitung <br>
§ 703c      Formulare; Einführung der maschinellen Bearbeitung <br>
§ 703d      Formulare; Antragsgegner ohne allgemeinen inländischen Gerichtsstand <br>
:::::::'''Buch 8. Zwangsvollstreckung'''
::::::::: Abschnitt 1. Allgemeine Vorschriften
§ 704        Vollstreckbare Endurteile <br>
§ 705        Formelle Rechtskraft <br>
§ 706        Rechtskraft- und Notfristzeugnis <br>
§ 707        Einstweilige Einstellung der Zwangsvollstreckung <br>
§ 708        Vorläufige Vollstreckbarkeit ohne Sicherheitsleistung <br>
§ 709        Vorläufige Vollstreckbarkeit gegen Sicherheitsleistung <br>
§ 710        Ausnahmen von der Sicherheitsleistung des Gläubigers <br>
§ 711        Abwendungsbefugnis <br>
§ 712        Schutzantrag des Schuldners <br>
§ 713        Unterbleiben von Schuldnerschutzanordnungen <br>
§ 714        Antrag zur vorläufigen Vollstreckbarkeit <br>
§ 715        Rückgabe der Sicherheits <br>
§ 716        Ergänzung des Urteils <br>
§ 717        Wirkungen eines aufhebenden oder abändernden Urteils <br>
§ 718        Vorentscheidung über vorläufige Vollstreckbarkeit <br>
§ 719        Einstweilig Einstellung bei Rechtsmittel und Einspruch <br>
§ 720        Hinterlegung bei Abwendung der Vollstreckung <br>
§ 720a      Sicherungsvollstreckung <br>
§ 721        Räumungsfrist <br>
§ 722        Vollstreckbarkeit ausländischer Urteile <br>
§ 723        Vollstreckungsurteil <br>
§ 724        Vollstreckbare Ausfertigung <br>
§ 725        Vollstreckungsklausel <br>
§ 726        Vollstreckbare Ausfertigung bei bedingten Leistungen <br>
§ 727        Vollstreckbare Ausfertigung für und gegen Rechtsnachfolger <br>
§ 728        Vollstreckbare Ausfertigung bei Nacherbe und Testamentsvollstrecker <br>
§ 729        Vollstreckbare Ausfertigung gegen Vermögens- und Firmenübernehmer <br>
§ 730        Anhörung des Schuldners <br>
§ 731        Klage auf Erteilung der Vollstreckungsklausel <br>
§ 732        Erinnerung gegen Erteilung der Vollstreckungsklausel <br>
§ 733        Weitere vollstreckbare Ausfertigung <br>
§ 734        Vermerk über Ausfertigungserteilung auf der Urteilsschrift <br>
§ 735        Hinterlegung bei Abwendung der Vollstreckung <br>
§ 736        Zwangsvollstreckung gegen BGB-Gesellschaft <br>
§ 737        Zwangsvollstreckung bei Vermögens- oder Erbschaftsnießbrauch <br>
§ 738        Vollstreckbare Ausfertigung gegen Nießbraucher <br>
§ 739        Gewahrsamsvermutung bei Zwangsvollstreckung gegen Ehepartner und Lebensgatten <br>
§ 740        Zwangsvollstreckung in das Gesamtgut <br>
§ 741        Zwangsvollstreckung in das Gesamtgut bei Erwerbsgeschäft <br>
§ 742        Vollstreckbare Ausfertigung bei Gütergemeinschaft während des Rechtsstreits <br>
§ 743        Beendete Gütergemeinschaft <br>
§ 744        Vollstreckbare Ausfertigung bei beendeter Gütergemeinschaft <br>
§ 744a      Zwangsvollstreckung bei Eigentums und Vermögensgemeinschaft <br>
§ 745        Zwangsvollstreckung bei fortgesetzter Gütergemeinschaft <br>
§ 746        (weggefallen) <br>
§ 747        Zwangsvollstreckung in ungeteilten Nachlass <br>
§ 748        Zwangsvollstreckung bei Testamentsvollstrecker <br>
§ 749        Vollstreckbare Ausfertigung für und gegen Testamentsvollstrecker <br>
§ 750        Voraussetzunge der Zwangsvollstreckung <br>
§ 751        Bedingungen für Vollstreckungsbeginn <br>
§ 752        Sicherheitsleistung bei Teilvollstreckung <br>
§ 753        Vollstreckung durch Gerichtsvollzieher; Verordnungsermächtigung <br>
§ 753a      Vollstreckungsnachweis <br>
§ 754        Vollstreckungsauftrag und vollstreckbare Ausfertigung <br>
§ 754a      Vereinfachter Vollstreckungsauftrag bei Vollstreckungsbescheiden <br>
§ 755        Ermittlung des Aufenthaltsorts des Schuldners <br>
§ 756        Zwangsvollstreckung bei Leistung Zug um Zug <br>
§ 757        Übergabe des Titels und Quittung <br>
'''''[ab 1.1.2022:]''''' <br>
§ 757a      Auskunft- und Unterstützungsersuchen <br>
§ 758        Durchsuchung; Gewaltanwendung <br>
§ 759        Zuziehung von Zeugen <br>
§ 760        Akteneinsicht; Aktenabschrift <br>
§ 761        (weggefallen) <br>
§ 762        Protokoll über Vollstreckungshandlungen <br>
§ 763        Aufforderungen und Mitteilungen <br>
§ 764        Vollstreckungsgericht <br>
§ 765        Vollstreckungsgerichtliche Anordnungen bei Leistung Zug um Zug <br>
§ 765a      Vollstreckungsschutz <br>
§ 766        Erinnerung gegen Art und Weise der Zwangsvollstreckung <br>
§ 767        Vollstreckungsabwehrklage <br>
§ 768        Klage gegen Vollstreckungsklausel <br>
§ 769        Einstweilige Anordnungen <br>
§ 770        Einstweilige Anordnungen im Urteil <br>
§ 771        Drittwiderspruchsklage <br>
§ 772        Drittwiderspruchsklage bei Veräußerungsverbot <br>
§ 773        Drittwiderspruchsklage des Nacherben <br>
§ 774        Drittwiderspruchsklage des Ehegatten oder Lebenspartners <br>
§ 775        Einstellung oder Beschränkung der Zwangsvollstreckung <br>
§ 776        Aufhebung von Vollstreckungsmaßregeln <br>
§ 777        Erinnerung bei genügender Sicherung des Gläubigers<br>
§ 778        Zwangsvollstreckung vor Erbschaftsannahme <br>
§ 779        Fortsetzung der Zwangsvollstreckung nach dem Tod des Schuldners <br>
§ 780        Vorbehalt der beschränkten Erbenhaftung <br>
§ 781        Beschränkte Erbenhaftung in der Zwangsvollstreckung <br>
§ 782        Einreden des Erben gegen Nachlassgläubiger <br>
§ 783        Einreden des Erben gegen persönliche Gläubiger <br>
§ 784        Zwangsvollstreckung bei Nachlassverwaltung und Insolvenzverfahren <br>
§ 785        Vollstreckungsabwehrklage des Erben <br>
§ 786        Vollstreckungsabwehrklage bei beschränkter Haftung <br>
§ 786a      See- und binnenschifffahrtsrechtliche Haftungsbeschränkung <br>
§ 787        Zwangsvollstreckung bei herrenlosem Grundstück oder Schiff <br>
§ 788        Kosten der Zwangsvollstreckung <br>
§ 789        Einschreiten von Behörden <br>
§ 790        (weggefallen) <br>
§ 791        (weggefallen) <br>
§ 792        Erteilung von Urkunden an Gläubiger <br>
§ 793        Sofortige Beschwerde <br>
§ 794        Weitere Vollstreckungstitel <br>
§ 794a      Zwangsvollstreckung aus Räumungsverkauf <br>
§ 795        Anwendung der allgemeinen Vorschriften auf die weiteren Vollstreckungstitel<br>
§ 795a      Zwangsvollstreckung aus Kostenfestsetzungsbeschluss <br>
§ 795b      Vollstreckbarerklärung des gerichtlichen Vergleichs <br>
§ 796        Zwangsvollstreckung aus Vollstreckungsbescheiden<br>
§ 796a      Voraussetzungen für die Vollstreckbarerklärung des Anwaltsvergleichs <br>
§ 797        Verfahren bei vollsteckbaren Urkunden<br>
§ 798        Wartefrist <br>
§ 798a      (weggefallen) <br>
§ 799        Vollstreckbare Urkunde bei Rechtsnachfolge <br>
§ 799a      Schadensersatzpflicht bei der Vollstrecking aus Urkunden durch andere Gläubiger <br>
§ 800        Vollstreckbare Urkunde gegen den jeweiligen Grundstückseigentümer <br>
§ 800a      Vollstreckbare Urkunde bei Schiffshypothek <br>
§ 801        Landesrechtliche Vollstreckungstitel <br>
§ 802        Auschließlichkeit der Gerichtsstände <br>
::::::::: Abschnitt 2. Zwangsvollstreckung wegen Geldforderungen
:::::::::::::Titel 1. Allgemeine Vorschriften
§ 802a      Grundsätze der Vollstreckung; Regelbefugnisse des Gerichtsvollziehers <br>
§ 802b      Gütliche Erledigung; Vollstreckungsaufschub bei Zahlungsvereinbarung <br>
§ 802c      Vermögensauskunft des Schuldners <br>
'''''[bis 31.12.2021:]''''' <br>
§ 802d      Erneute Vermögensauskunft <br>
'''''[ab 1.1.2022:]''''' <br>
§ 802e      Zuständigkeit <br>
§ 802f      Verfahren zur Abnahme der Vermögensauskunft <br>
§ 802g      Erzwingungshaft <br>
§ 802h      Unzulässigkeit der Haftvollstreckung <br>
§ 802i      Vermögensauskunft des verhafteten Schuldners <br>
§ 802j      Dauer der Haft; erneute Haft <br>
§ 802k      Zentrale Verwaltung der Vermögensverhzeichnisse <br>
§ 802l      Auskunftsrechte des Gerichtsvollziehers <br>
:::::::::::::Titel 2. Zwangsvollstreckung in das bewegliche Vermögen
:::::::::::::::::Untertitel 1. Allgemeine Vorschriften
§ 803        Pfändung <br>
§ 804        Pfändungspfandrecht <br>
§ 805        Klage auf Vorzugsweise Befriedigung <br>
§ 806        Keine Gewährleistung der Pfandveräusserung <br>
§ 806a      Mitteilungen und Befragung durch den Gerichtsvollzieher <br>
§ 807        Abnahme der Vermögensauskunft nach Pfandversuch <br>
:::::::::::::Untertitel 2. Zwangsvollstreckung in körperliche Sachen
§ 808        Pfändung beim Schuldner <br>
§ 809        Pfändung beim Gläubiger oder bei Dritten <br>
§ 810        Pfändung ungetrennter Früchte <br>
'''''[ab 31.12.2021:]''''' <br>
§ 811        Unpfändbare Sachen <br>
'''''[ab 1.1.2022:]''''' <br>
§ 811        ''Unpfändbare Sachen und Tiere ''<br>
§ 811a      Austauschpfändung<br>
§ 811b      Vorläufige Austauschpfändung<br>
'''''[ab 31.12.2021:]''''' <br>
§ 811c      Unpfändbarkeit von Haustieren<br>
§ 811d      Vorwegpfändung<br>
§ 812        Pfändung von Hausrat<br>
§ 813        Schätzung<br>
§ 814        Öffentliche Versteigerung<br>
§ 815        Gepfändetes Geld<br>
§ 816        Zeit und Ort der Versteigerung<br>
§ 817        Zuschlag und Ablieferung<br>
§ 817a      Mindestgebot<br>
§ 818        Einstellung der Versteigerungt<br>
§ 819        Wirkung des Erlösempfängers<br>
§ 820        (weggefallen)<br>
§ 821        Verwertung von Werkpapieren<br>
§ 822        Umschreibung von Namenspapieren<br>
§ 823        Außer Kurs gesetzte Inhaberpapiere<br>
§ 824        Pfändung von Hausrat<br>
§ 825        Andere Verwertungsart<br>
§ 826        Anschlussprüfung<br>
§ 827        Verfahren bei mehrfacher Pfändung<br>
:Untertitel 3. Zwangsvollstreckung in Forderungen und anderen Vermögensrechte
§ 828        Zuständigkeit des Vollstreckungsgerichts<br>
§ 829        Pfändung einer Geldforderung<br>
§ 830        Pfändung einer Hypothekenforderung<br>
§ 831        Pfändung indossabler Papiere<br>
§ 832        Pfändungsumfang bei fortlaufenden Bezügen<br>
§ 833        Pfändungsumfang bei Arbeits- oder Diensteinkommen<br>
§ 833a      Pfändungsumfang bei Kontoguthaben<br>
§ 834        Keine Anhörung des Schuldners<br>
§ 835        Überweisung einer Geldforderung<br>
§ 836        Wirkung der Überweisung<br>
§ 837        Überweisung einer Hypothekenforderung<br>
§ 837a      Überweisung einer Schiffshypothekenforderung<br>
§ 838        Einrede des Schuldners bei Faustpfand<br>
§ 839        Überweisung bei Anwendungsbefugnis<br>
§ 840        Erklärungspflicht des Drittschuldners<br>
§ 841        Pflicht zur Streitverkündungs<br>
§ 842        Schadensersatz bei verzögerter Beitreibung<br>
§ 843        Verzicht des Pfandgläubigers<br>
§ 844        Andere Verwendungen<br>
§ 845        Vorpfändung<br>
§ 846        Zwangsvollstreckung in Herausgabeansprüche<br>
§ 847        Herausgabeanspruch auf eine bewegliche Sache<br>
§ 848        Herausgabeanspruch auf eine unbewegliche Sache<br>
§ 849        Keine Überweisung an Zahlungs statt<br>
§ 850        Pfändungsschutz für Arbeitseinkommen<br>
§ 850a      Unpfändbare Bezüge<br>
§ 850b      Bedingt pfändbare Bezüge<br>
§ 850c      Pfändungsgrenzen für Arbeitseinkommen<br>
§ 850d      Pfändbarkeit bei Unterhaltsansprüchen<br>
§ 850e      Berechnung des pfändbaren Arbeitseinkommen<br>
§ 850f       Änderung des unpfändbare Betrages<br>
§ 850g      Änderung der Unpfändbarkeitsvoraussetzungen<br>
§ 850h      Verschleiertes Arbeitseinkommen<br>
§ 850i       Pfändungsschutz für sonstige Einkünfte<br>
'''''[ab 30.11.2021:]''''' <br>
§ 850k       Pfändungsschutzkonto<br>
§ 850l       Anordnung der Unpfändbarkeit von Kontoguthaben auf dem Pfändungsschutzkonto<br>
'''''[ab 01.12.2021:]''''' <br>
§ ''850k''       ''Einrichtung und Beendigung des Pfandschutzkontos''<br>
§ ''850l''       ''Pfändung des Gemeinschaftskontos''<br>
§ 851        Nicht übertragbare Forderungen<br>
§ 851a       Pfändungsschutz für Landwirte<br>
§ 851b       Pfändungsschutz bei Miet- und Pachtzinsen<br>
§ 851c       Pfändungsschutz bei Altersrenten<br>
§ 851d       Pfändungsschutz bei steuerlich gefördertem Altersvorsorgevermögen<br>
§ 852        Beschränkt pfändbare Forderungen<br>
§ 853        Mehrfache Pfändung einer Geldforderung<br>
§ 854        Mehrfache Pfändung eines Anspruchs auf bewegliche Sachen<br>
§ 855        Mehrfache Pfändung eines Anspruchs auf unbewegliche Sachen<br>
§ 855a      Mehrfache Pfändung eines Anspruchs auf ein Schiff<br>
§ 856        Klage bei mehrfacher Pfändung<br>
§ 857        Zwangsvollstreckung in andere Vermögensrechte<br>
§ 858        Zwangsvollstreckung in Schiffspart<br>
§ 859        Pfändung von Gesamthandanteilen<br>
§ 860        Pfändung von Gesamtgutanteilen<br>
§§ 861, 862 (weggefallen)<br>
§ 863        Pfändungsbeschränkungen bei Erbschaftsnutzungen<br>
:::::::::::::Titel 3. Zwangsvollstreckung in das unbewegliche Vermögen<br>
§ 864        Gegenstand der Immobiliarvollstreckung<br>
§ 865        Verhältnis zur Mobiliarvollstreckung<br>
§ 866        Arten der Vollstreckung<br>
§ 867        Zwangshypothek<br>
§ 868        Erwerb der Zwangshypothek durch den Eigentümer<br>
§ 869        Erwerb der Zwangsversteigerung und Zwangsverwaltung<br>
§ 870        Grundstücksgleiche Rechte<br>
§ 870a      Zwangsvollstreckung in ein Schiff oder Schiffsbauwerk<br>
§ 871        Landesrechtlicher Vorbehalt bei Eisenbahnen<br>
:::::::::::::Titel 4. Verteilungsverfahren
§ 872        Voraussetzungen<br>
§ 873        Aufforderung des Verteilungsgerichts<br>
§ 874        Teilungsplan<br>
§ 875        Terminsbestimmung<br>
§ 876        Termin zur Erklärung und Ausführung<br>
§ 877        Säumnisfolgen<br>
§ 878        Widerspruchsklage<br>
§ 879        Zuständigkeit für die Widerspruchsklage<br>
§ 880        Inhalt des Urteils<br>
§ 881        Versäumnisurteil<br>
§ 882        Verfahren nach dem Urteil<br>
::::::Titel 5. ''[bis 30.11.2021: Zwangsvollstreckung gegen juristische Personen des öffentlichen Rechts''']<br>
:::::[ab 1.12.20211: Zwangsvollstreckung in Sachen, die der Erfüllung öffentlicher Aufgaben dienen]
§ 882a       Zwangsvollstreckung wegen einer Geldforderung<br>
:::::::::::::Titel 6. Schuldnerverzeichnbis
§ 882b       Inhalt des Schuldnerverzeichnisses<br>
§ 882c       Eintragungsanordnung<br>
§ 882d       Vollziehung der Eintragungsanordnung<br>
§ 882e       Löschung<br>
§ 882f       Einsicht in das Schuldnerverzeichnis<br>
§ 882g       Erteilung von Abdrucken<br>
§ 882h       Zuständigkeit; Ausgestaltung des Schuldnerverzeichnisses<br>
§ 882i       Rechte der Betroffenen<br>
Abschnitt 3. Zwangsvollstreckung zur Erwirkung der Herausgabe von Sachen und zur Erwirkung von<br>
::::::::::::Handlungen oder Unterlassungen
§ 883        Herausgabe bestimmter beweglicher Sachen<br>
§ 884        Leistung einer bestimmten Menge vertretbarer Sachen<br>
§ 885        Herausgabe von Grundstücken oder Schiffen<br>
§ 886        Herausgabe bei Gewahrsam eines Dritten<br>
§ 887        Vertretbare Handlungen<br>
§ 888        Nicht vertretbare Handlungen<br>
§ 888a      Keine Handlungsvollstreckung bei Entschädigungspflicht<br>
§ 889        Eidesstattliche Versicherung nach bürgerlichem Recht<br>
§ 890        Erzwingung von Unterlassungen und Duldungen<br>
§ 891        Verfahren; Anhörung des Schuldners; Kostenentscheidung<br>
§ 892        Widerstand des Schuldners<br>
§ 893        Klage auf Leistung des Interesses<br>
§ 894        Fiktion der Abgabe einer Willenserklärung<br>
§ 895        Willenserklärung zwecks Eintragung bei vorläufig vollstreckbarem Urteil<br>
§ 896        Erteilung von Urkunden an Gläubiger<br>
§ 897        Übereignung; Verschiffung von Grundpfandrechten<br>
§ 898        Gutgläubiger Erwerb<br>
'''''[bis 30.11.2021:]''''' <br>
§§ 899 - 915h (aufgehoben)
'''''[ab 1.12.2021:]''''' <br>
::::::::: Abschnitt 4. Wirkungen des Pfändungsschutzkontos
§ 899        Pfändungsfreier Betrag; Übertragung<br>
§ 900        Moratorium bei Überweisung an den Gläubiger<br>
§ 901        Verbot der Aufrechnung und Verrechnung<br>
§ 902        Erhöhungsbeträge<br>
§ 903        Nachweise über Erhöhungsbeträge<br>
§ 904        Nachzahlung von Leistungen<br>
§ 905        Festsetzung der Erhöhungsbeträge durch das Vollstreckungsgericht<br>
§ 906        Festsetzung eines abweichenden pfändungsfreien Betrages durch das Vollstreckungsgericht<br>
§ 907        Festsetzung der Unpfändbarkeit von Kontoguthaben auf dem Pfändungskonto<br>
§ 908        Aufgaben des Kreditinstituts<br>
§ 909        Datenweitergabe; Löschungspflicht<br>
§ 910        Verwaltungsvollsteckung<br>
§. 911 bis 915h (weggefallen)<br>
::::::::: Abschnitt 5. Arrest und einstweilige Verfügung<br>
§ 916        Arrestanspruch<br>
§ 917        Arrestgrund bei dinglichem Arrest<br>
§ 918        Arrestgrund bei persönlichem Arrest<br>
§ 919        Arrestgericht<br>
§ 920        Arrestgesuch<br>
§ 921        Entscheidung über das Arrestgesuch<br>
§ 922        Arresturteil und Arrestbeschluss<br>
§ 923        Anwendungsbefugnis<br>
§ 924        Widerspruch<br>
§ 925        Entscheidung nach Widerspruch<br>
§ 926        Anordnung der Klageerhebung<br>
§ 927        Aufhebung wegen veränderter Umstände<br>
§ 928        Vollziehung des Arrestes<br>
§ 929        Vollstrechungsklausel; Vollziehungsfrist<br>
§ 930        Vollziehung in bewegliches Vermögen und Forderungen<br>
§ 931        Vollziehung in eingetragenes Schiff oder Schiffsbauwerk<br>
§ 932        Arresthypothek<br>
§ 933        Vollziehung des persönlichen Arrestes<br>
§ 934        Aufhebung der Arrestvollziehung<br>
§ 935        Einstweilige Verfügung bezüglich Streitgegenstand<br>
§ 936        Anwendung der Arrestvorschriften<br>
§ 937        Zuständiges Gericht<br>
§ 938        Inhalt der Einstweiligen Verfügung<br>
§ 939        Aufhebung gegen Sicherheitsleistung<br>
§ 940        Einstweilige Verfügung zur Regelung eines weiteren Zustandes<br>
§ 940a      Räumung von Wohnraum<br>
§ 941        Ersuchen um Eintragungen ins Grundbuch usw.<br>
§ 942        Zuständigkeit des Amtsgerichts der belegenen Sache<br>
§ 943        Gericht der Hauptsache<br>
§ 944        Entscheidung des Vorsitzenden bei Dringlichkeit<br>
§ 945        Schadensersatzprlicht<br>
§ 945a      Einreichung von Schutzvorschriften<br>
§ 945b      Verordnungsermächtigung<br>
::::::::: Abschnitt 6. Grenzüberschreitende vorläufige Kontenpfändung<br>
::::::::: Titel 1. Erlass des Beschlusses zur vorläufigen Kontenpfändung<br>
§ 946        Zuständigkeit<br>
§ 947        Verfahren<br>
§ 948        Ersuchen um Einholen von Konteninformationen<br>
§ 949        Nicht rechtzeitige Einleitung des Hauptverfahrens<br>
::::::::: Titel 2. Vollziehung des Beschlusses zur vorläufigen Kontenpfändung<br>
§ 950        Anwendbare Vorschriften<br>
§ 951        Vollziehung von im Inland erlassenen Beschlüssen<br>
§ 952        Vollziehung von einem anderen Mitgliedstaat erlassenen Beschlüssen<br>
::::::::: Titel 3. Rechtsbehelfe
§ 953        Rechtsbehelfe des Gläubigers<br>
§ 954        Rechtsbehelfe nach den Artikeln 33 bis 35 der Verordnung (EU) Nr. 655/2014<br>
§ 955        Sicherheitsleistung nach Artikel 38 der Verordnung (EU) Nr. 655/2014<br>
§ 956        Rechtsmittel gegen die Entscheidungen nach § 954 Absatz 1 bis 3 und § 955<br>
§ 957        Ausschluss der Rechtsbeschwerde<br>
::::::::: Titel 4. Schadensersatz, Verordnungsermächtigung
§ 958        Schadensersatz<br>
§ 959        Verordnungsermächtigung<br>
:::::::::::: '''Buch 9.''' (weggefallen)
§§ 960 - 1024        (aufgehoben)<br>
::::::::: '''Buch 10. Schiedsrichterliches Verfahren '''
:::::::::: Abschnitt 1. Allgemeine Vorschriften
§ 1025        Anwendungsbereich<br>
§ 1026        Umfang gerichtlicher Tätigkeit<br>
§ 1027        Verlust des Rügerechts<br>
§ 1028        Empfang schriftlicher Mitteilungen bei unbekanntem Aufenthalt<br>
:::::::::: Abschnitt 2. Schiedsvereinbarung
§ 1029        Begriffsbestimmung<br>
§ 1030        Schiedsfähigkeitimmung<br>
§ 1031        Form der Schiedsvereinbarung<br>
§ 1032        Schiedsvereinbarung und Klage vor Gericht<br>
= § 1 (ZPO) Sachliche Zuständigkeit. =
Die sachliche Zuständigkeit der Gerichte wird durch das Gesetz über die Gerichtsverfassung 2) bestimmt. '''(Quellinfo = Buch "ZPO" S. 22 ff.)'''
= § 2 (ZPO) Bedeutung des Wertes. =
Kommt es nach den Vorschriften dieses Gesetztes oder des Gerichtsverfassungsgesetzes 2) auf den Wert des Streitgegenstandes des Beschwerdegegenstandes, der Beschwerde oder der Verurteilung an, so gelten die nachfolgenden Vorschriften. '''(Quellinfo = Buch "ZPO" S. 22 ff.)'''
= § 3 (ZPO) Wertfestsetzung nach freiem Ermessen. =
Der Wert wird von dem Gericht nach freiem Ermessen festgesetzt; es kann eine beantragte Beweisaufnahme sowie von Amts wegen die Einnahme des Augenscheins und die Begutachtung durch Sachverständige anordnen. '''(Quellinfo = Buch "ZPO" S. 22 ff.)'''
= § 4 (ZPO) Wertberechnung: Nebenforderungen. =
(1) Für die Wertberechnung 3) ist der Zeitpunkt der Einreichung der Klage, in der Rechtsmittelinstanz der Zeitpunkt der Einlegung des Rechtsmittels, bei der Verurteilung der Zeitpunkt des Schlusses der mündlichen Verhandlung, auf die das Urteil ergeht, entscheidend; Früchte, Nutzungen, Zinsen und Kosten bleiben unberücksichtigt, wenn sie als Nebenforderungen geltend gemacht werden. (2) Bei Ansprüchen aus Wechseln im Sinne des Wechselgesetzes sind Zinsen, Kosten und Provision, die außer der Wechselsumme gefordert werden, als Nebenforderungen anzusehen. '''(Quellinfo = Buch "ZPO" S. 22 ff.)'''
= § 5 (ZPO) Mehrere Ansprüche. =
Mehrere in einer Klage geltend gemachte Ansprüche werden zusammengerechnet; dies gilt nicht für den Gegenstand der Klage und der Widerklage. '''(Quellinfo = Buch "ZPO" S. 22 ff.)'''
= § 6 (ZPO) Besitz; Sicherstellung; Pfandrecht. =
<sup>1</sup> Der Wert wird bestimmt; durch den Wert einer Sache; wenn es auf deren Besitz und durch den Betrag einer Forderung, wenn es auf deren Sicherstellung oder ein Pfandrecht ankommt.<sup>2</sup> Hat der Gegenstand des Pfandrechts einen geringeren Wert, so ist dieser maßgebend. '''(Quellinfo = Buch "ZPO" S. 22 ff.)'''
= § 7 (ZPO) Grunddienstbarkeit. =
Der Wert einer Grunddienstbarkeit wird durch den Wert, den sie für das herrschende Grundstück hat, und wenn der Betrag, um den sich der Wert des dienenden Grundstücks durch die Dienstbarkeit mindert, größer ist, durch diesen Betrag bestimmt. '''(Quellinfo = Buch "ZPO" S. 22 ff.)'''
= § 8 (ZPO) <sup> 1) </sup> Pacht- oder Mietverhältnis. =
Ist das Bestehen oder die Dauer eines Pacht- oder Mietverhältnisses streitig, so ist der Betrag der auf die gesamte streitige Zeit entfallenden Pacht oder Miete und, wenn der 25fache Betrag des einjährigen Entgelts geringer ist, dieser Betrag für die Wertberechnung entscheidend. '''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 9 (ZPO) <sup> 2) </sup> Wiederkehrende Nutzungen oder Leistungen. =
1 Der Wert des Rechts auf wiederkehrende Nutzungen oder Leistungen wird nach dem dreieinhalbfachen Wert des einjährigen Bezuges berechnet. 2 Bei bestimmter Dauer des Bezugsrechts ist der Gesamtbetrag der künftigen Bezüge maßgebend, wenn er der geringere ist. '''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 10 (ZPO) (weggefallen) =
'''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 11 (ZPO) Bindende Entscheidung über Unzuständigkeit =
Ist die Unzuständigkeit eines Gerichts auf Grund der Vorschriften über die sachliche Zuständigkeit der Gerichte rechtskräftig ausgesprochen, so ist diese Entscheidung für das Gericht bindend, bei dem die Sache später anhängig wird. '''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
:::'''Titel 2. Gerichtsstand'''
= § 12³) (ZPO) Allgemeiner Gerichtsstand; Begriff. =
Das Gericht, bei dem eine Person ihren allgemeinen Gerichtsstand hat, ist für alle gegen sie zu erhebenden Klagen zuständig, sofern nicht für eine klage ein ausschließlicher Gerichtsstand begründet ist. '''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 13) (ZPO) Allgemeiner Gerichtsstand des Wohnsitzes. =
Der allgemeine Gerichtsstand einer Person wird durch den Wohnsitz bestimmt '''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 14) (ZPO) (weggefallen) =
'''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 15 (ZPO) Allgemeiner Gerichtsstand für exterritoriale Deutsche =
(1)<sup>1</sup> Deutsche, die das Recht der Exterritorialität genießen, sowie die im Ausland beschäftigten deutschen Angehörigen des öffentlichen Diensts behalten den Gerichtsstand ihres letzten inländischen Wohnsitzes. <sup>2</sup> Wenn sie einen solchen Wohnsitz nicht hatten, habe sie ihren allgemeinen Gerichtsstand beim Amtsgericht Schöneberg in Berlin. (2) Auf Honorarkonsuln ist diese Vorschrift nicht anzuwenden.
'''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 16 (ZPO) Allgemeiner Gerichtsstand wohnsitzloser Personen =
Der allgemeine Gerichtstand einer Person, die keinen Wohnsitz hat, wird durch den Aufenthaltsort im Inland und, wenn ein solcher nicht bekannt ist, durch den letzten Wohnsitz bestimmt. '''(Quellinfo = Buch "ZPO" S. 23 ff.)'''
= § 17 (ZPO) Allgemeiner Gerichtsstand juristischer Personen =
(1) <sup> 1 </sup> Der allgemeine Gerichtsstand der Gemeinden, der Korporationen sowie derjenigen Gesellschaften, Genossenschaften oder anderen Vereine und derjenigen Stiftungen, Anstalten und Vermögensmassen, die als solche verklagt werden können, wird durch ihren Sitz bestimmt. <sup> 2 </sup> Als Sitz gilt, wenn sich nichts anderes ergibt, der Ort, wo die Verwaltung geführt wird. (2) Gewerkschaften haben den allgemeinen Gerichtstand bei dem Gericht, in dessen Bezirk das Bergwerk liegt, Behörden, wenn sie als solche verklagt werden können, bei dem Gericht ihres Amtssitzes. (3) Neben dem durch die Vorschriften dieses Paragraphen bestimmten Gerichtsstand ist ein durch Statut oder in anderer Weise besonders geregelter Gerichtsstand zulässig. '''(Quellinfo = Buch "ZPO" S. 24 ff.)'''
= § 18 Allgemeiner Gerichtsstand des Fiskus =
Der allgemeine Gerichtsstand des Fiskus wird durch den Sitz der Behörde bestimmt, die berufen ist, den Fiskus in dem Rechtsstreit zu vertreten. '''(Quellinfo = Buch "ZPO" S. 24 ff.)'''
= § 19 Mehrere Gerichtsbezirke am Behördensitz =
Ist der Ort, an dem eine Behörde ihren Sitz hat, in mehrere Gerichtsbezirke geteilt, so wird der Bezirk der im Sinne der §§ 17, 18 als Sitz der Behörde gilt, für die Bundesbehörden von dem Bundesministerium der Justiz und für Verbraucherschutz, im Übrigen von der Landesjustizverwaltung durch allgemeine Anordnung bestimmt. '''(Quellinfo = Buch "ZPO" S. 24 ff.)'''
= § 19 <sub> a </sub> Allgemeiner Gerichtsstand des Insolvenzverwalters. =
Der allgemeine Gerichtsstand eines Isolvenzverwalters für Klagen, die sich auf die Insolvenzmasse beziehen, wird durch den Sitz des Insolvenzgerichts bestimmt. '''(Quellinfo = Buch "ZPO" S. 24 ff.)'''
= § 19 <sub> b </sub> Allgemeiner Gerichtsstand bei restrukturierungsbezogene Klagen; Verordnungsermächtigung. =
(1) Für Klagen, die sich auf Restrukturierungssachen nach dem Unternehmensstabilisierungs- und -retrukturierungsgesetz beziehen, ist ausschließlich das Gericht zuständig, in dessen Bezirk das für die Restrukturierungssache zuständige Restrukturierungsgericht seinen Sitz hat.
<div style="text-indent: 38px;"> (2) <sup> 1 </sup>Die Landesregierungen werden ermächtigt, durch Rechtsverordnung die in Absatz 1 genannten Klagen einem Landgericht für die Bezirke mehrerer Oberlandesgerichte zuzuweisen, sofern dies der sachlichen Förderung oder schnelleren Erledigung der Verfahren dienlich ist. <sup>2</sup>Die Landesregierungen können die Ermächtigung durch Rechtsverordnung auf die Landesjustizverwaltungen übertragen. '''(Quellinfo = Buch "ZPO" S. 24 ff.)'''</div>
= § 20 Besonderer Gerichtsstand des Aufenthaltsorts. =
Wenn Personen an einem Ort unter Verhältnissen, die ihrer Natur nach auf einen Aufenthalt von längerer Dauer hinweisen, insbesondere als Hausgehilfen, Arbeiter, Gewerbehilfen, Studierende, Schüler oder Lehrlinge sich aufhalten, so ist das Gericht des Aufenthaltsortes für alle Klagen zuständig, die gegen dieser Personen wegen vermögensrechtlicher Ansprüche erhoben werden. '''(Quellinfo = Buch "ZPO" S. 24 ff.)'''
= § 21 Besonderer Gerichtsstand der Niederlassung. =
(1) hat jemand zum Betrieb einer Fabrik, einer Handlung oder eines anderen Gewerbes eine Niederlassung, von der aus unmittelbar Geschäfte geschlossen werden, so können gegen ihn alle Klagen, die auf den Geschäftsbetrieb der Niederlassung Bezug haben, bei dem Gericht des Ortes erhoben werden, wo die Niederlassung sich befindet. '''(Quellinfo = Buch "ZPO" S. 24 ff.)'''
= § 22 Besonderer Gerichtsstand der Mitgliedschaft. =
Das Gericht, bei dem Gemeinden, Korporationen, Gesellschaften, Genossenschaften oder andere Vereine den allgemeinen Gerichtsstand haben, ist für die Klagen zuständig, die von ihnen oder von dem Insolvenzverwalter gegen die Mitglieder als solche oder von den Mitgliedern in dieser Eigenschaft gegeneinander erhoben werden. '''(Quellinfo = Buch "ZPO" S. 25 ff.)'''
= § 23<sup>1)</sup>Besonderer Gerichtsstand des Vermögens und des Gegenstands. =
<sup>1</sup> Für Klagen wegen vermögensrechtlicher Ansprüche gegen eine Person, die im Inland keinen Wohnsitz hat, ist das Gericht zuständig, in dessen Bezirk sich Vermögen derselben oder der mit der Klage in Anspruch genommene Gegenstand befindet. <sup>2</sup> Bei Forderungen gilt als der Ort, wo das Vermögen sich befindet, der Wohnsitz des Schuldners und, wenn für die Forderungen eine Sache zur Sicherheit haftet, auch der Ort, wo die Sache sich befindet. '''(Quellinfo = Buch "ZPO" S. 25 ff.)'''
= § 23a (aufgehoben) =
= § 24 Ausschließlicher dinglicher Gerichtsstand. =
(1) Für Klagen, durch die das Eigentum, eine dingliche Belastung oder die Freiheit von einer solchen geltend gemacht wird, für Grenzscheidungs-, Teilung- und Besitzklagen ist, sofern es sich um unbewegliche Sachen handelt, das Gericht ausschließlich zuständig, in dessen Bezirk die Sache belegen ist. (2) Bei den eine Grunddienstbarkeit, eine Reallast oder ein Vorkaufsrecht betreffenden Klagen ist die Lage des dienenden oder belasteten Grundstücks entscheidend. '''(Quellinfo = Buch "ZPO" S. 25 ff.)'''
= § 25 Dinglicher Gerichtsstand des Sachzusammenhanges. =
In dem dinglichen Gerichtsstand kann mit der Klage aus einer Hypothek, Grundschuld oder Rentenschuld die Schuldklage, mit der Klage auf Umschreibung oder Löschung einer Hypothek, Grundschuld oder Rentenschuld die Klage auf Befreiung von der persönlichen Verbindlichkekt mit der Klage auf Anerkennung einer Reallast die Klage auf rückständige Leistungen erhoben werden, wenn die verbundenen Klagen gegen denselben Beklagten gerichtet sind. '''(Quellinfo = Buch "ZPO" S. 25 ff.)'''
= § 26 Dinglicher Gerichtsstand für persönliche Klagen. =
In dem dinglichen Gerichtsstand können persönliche Klagen, die gegen die Eigentümer oder Besitzer einer unbeweglichen Sache als solche gerichtet werden, sowie Klagen wegen Beschädigung eines Grundstücks oder hinsichtlich der Entschädigung wegen Enteignung eines Grundstücks erhoben werden. '''(Quellinfo = Buch "ZPO" S. 25 ff.)'''
= § 27 Besonderer Gerichtsstand der Erbschaft. =
(1) Kagen, welche die Feststellung des Erbrechts, Ansprüche des Erben gegen einen Erbschaftsbesitzer, Anprüche aus Vermächtnissen oder sonstigen Verfügungen von Todes wegen, Pflichtteilsansprüche oder die Teilung der Erbschaft zum Gegenstand haben, können vor dem Gericht erhoben werden, bei dem er Erblasser zur zeit seines Todes den allgemeinen Gerichtsstand gehabt hat. (2) Ist der Erblasser ein Deutscher und hatte er zur Zeit seines Todes im Inland keinen allgemeinen Gerichtsstand, so können die im Absatz 1 bezeichneten Klagen vor dem Gericht erhoben werden, in dessen Bezirk der Erblasser seinen letzten inländischen Wohnsitz hatte, wenn er einen solchen Wohnsitz nicht hatte, so gilt die Vorschrift des § 15 Abs., 1 Satz 2 entsprechend. '''(Quellinfo = Buch "ZPO" S. 26 ff.)'''
= § 28 Erweiterter Gerichtsstand der Erbschaft. =
In dem Gerichtsstand der Erbschaft können auch Klagen wegen anderer Nachlassverbindlichkeiten erhoben werden, solange sich der Nachlass noch ganz oder teilweise im Bezirk des Gerichts befindet oder die vorhandenen mehreren Erben noch als Gesamtschuldner haften. '''(Quellinfo = Buch "ZPO" S. 26 ff.)'''
= § 29 Besonderer Gerichtsstand des Erfüllungsorts. =
(1) Für Streitigkeiten aus einem Ertragsverhältnis und über deren Betehen ist das Gericht des Ortes zuständig, an dem die streitige Verpflichtung zu erfüllen ist. (2) Eine Vereinbarung über den Erfüllungsort begründet die Zuständigkeit nur, wenn die Vertragsparteien Kaufleute, juristische Personen des öffentlichen Rechts oder öffentlich-rechtliche Sondervermögen sind. '''(Quellinfo = Buch "ZPO" S. 26 ff.)'''
= § 29a Ausschließlicher Gerichtstand bei Miet- oder Pachträumen. =
(1) Für Streitigkeiten über Ansprüche aus Miet- oder Pachtverhältnissen über Räume oder über dessen Bestehen solcher Verhältnisse ist das Gericht ausschließlich zuständig, in dessen Bezirk sich die Räume befinden. (2) Absatz 1 ist nicht anzuwenden, wenn es sich um Wohnraum der in § 549 Abs. 2 Nr. 1 bis 3 des Bürgerlichen Gesetzbuchs genannten Art handelt. '''(Quellinfo = Buch "ZPO" S. 26 ff.)'''
= § 29b (aufgehoben) =
= § 29c Besonderer Gerichtsstand für Haustürgeschäfte. =
(1)<sup>1</sup>Für Klagen aus außerhalb von Geschäftsräumen geschlossenen Verträgen (§312b des Bürgerlichen Gesetzbuchs) ist das Gericht zuständig, in dessen Bezirk der Verbraucher zur Zeit der Klageerhebung seinen Wohnsitz, in Ermangelung eines solchen seinen gewöhnlichen Aufenthalt hat. <sup>2</sup> Für Klagen gegen den Verbraucher ist dieses Gericht ausschließlich zuständig. (2) Verbraucher ist jede natürliche Person, die bei dem Erwerb des Anspruchs oder der Begründung des Rechtsverhältnisses nicht überwiegend im Rahmen ihrer gewerblichen oder selbständigen beruflichen Tätigkeit handelt. (3) § 33 Abs. 2 findet auf Widerklagen der anderen Vertragspartei keine Anwendung. (4) Eine von Absatz 1 abweichende Vereinbarung ist zulässig für den Fall, dass der Verbraucher nach Vertragsschluss seinen Wohnsitz oder gewöhnlicher Aufenthalt im Zeitpunkt der Klageerhebung nicht bekannt ist.
'''(Quellinfo = Buch "ZPO" S. 26 ff.)'''
= § 30 Gerichtsstand bei Beförderungen. =
(1)<sup>1</sup>Für Rechtsstreitigkeiten aus einer Güterbeförderung ist auch das Gericht zuständig, in dessen Bezirk der Ort der Übernahme des Gutes oder der für die Ablieferung des Gutes vorgegebene Ort liegt. <sup>2</sup>Eine Klage gegen den ausführenden Frachtführer oder ausführenden Verfrachter kann auch in dem Gerichtstand des Frachtführers oder Verfrachtete erhoben werden. <sup>3</sup> Eine Klage gegen den Frachtführer oder ausführenden Verfrachter kann auch in dem Gerichtsstand des ausführenden Frachtführers oder ausführenden Verfrachtete erhoben werden. (2)<sup>1</sup> Für Rechtsstreitigkeiten wegen einer Beförderung von Fahrgästen und ihrem Gepäck auf Schiffen ist auch das Gericht zuständig, in dessen Bezirk sich der im Beförderungsvertrag bestimmte Abgangs- oder Bestimmungsort befindet. <sup>2</sup>Eine von Satz 1 abweichende Vereinbarung ist unwirksam, wenn sie vor Eintritt des Ereignisses getroffen wird, das den Tod oder die Körperverletzung des Fahrgasts oder den Verlust, die Beschädigung oder die verspätete Aushändigung des Gepäcks verursacht hat.'''(Quellinfo = Buch "ZPO" S. 26 ff.)'''
= § 30a Gerichtsstand bei Bergungsansprüchen. =
Für Klagen wegen Ansprüchen aus Bergung von Schiffen oder sonstigen Vermögensgegenständen in einem Gewässer gegen eine Person, die im Inland keinen Gerichtsstand hat, ist das Gericht zuständig, bei dem der Kläger im Inland seinen allgemeinen Gerichtstand hat. '''(Quellinfo = Buch "ZPO" S. 27 ff.)'''
= § 31 Besonderer Gerichtstand der Vermögensverwaltung. =
Für Klagen, die aus einer Vermögensverwaltung von dem Geschäftsherrn gegen den Verwalter oder von dem Verwalter gegen den Geschätsherrn erhoben werden, ist das Gericht des Ortes zuständig, wo die Verwaltung geführt ist. '''(Quellinfo = Buch "ZPO" S. 276 ff.)'''
= § 32 Besonderer Gerichtsstand der unerlaubten Handlung. =
Für Klagen aus unerlaubten Handlungen ist das Gericht zuständig, in dessen Bezirk die Handlung begangen ist. '''(Quellinfo = Buch "ZPO" S. 27 ff.)'''
= § 32a Ausschließlicher Gerichtsstand der Umwelteinwirkung. =
<sup>1</sup>Für Klagen gegen den Inhaber einer im Anhang 1 des Umwelthaftungsgesetzes genannten Anlage, mit denen der Ersatz eines durch eine Umwelteinwirkungverursachten Schadens geltend gemacht wird, ist das Gericht ausschließlich zuständig, in dessen Bezirk die Umwelteinwirkung von der Anlage ausgegangen ist. <sup>2</sup>Dies gilt nicht, wenn die Anlage im Ausland belegen ist.
= § 32b<sup>1)</sup> Ausschließlicher Gerichtsstand bei falschen, irreführenden oder unterlassenen öffentlichen Kapitalmarktinformationen. =
(1) Für Klagen, in denen 1. ein Schadensersatzanspruch wegen falscher, irreführender oder unterlassener öffentlicher Kapitalmarktinformation, 2. ein Schadensersatzanpruch wegen Verwendung einer falschen oder irreführenden öffentlichen Kapitalmarktinformation oder wegen Unterlassung der gebotenen Aufklärung darüber das eine öffentliche Kapitalmarktinformation falsch oder irreführend ist, oder 3. ein Erfüllunganspruch aus Vertrag, der auf einem Angebot nach dem Wertpapiererwerbs- und Übernahmegesetz beruht, geltend gemacht wird, ist das Gericht ausschließlich am Sitz des betroffenen Emittenten, des betroffenen Anbieters von sonstigen Vermögensanlagen oder der Zielgesellschaft zuständig, wenn sich dieser Sitz im Inland befindend und die Klage zumindest auch gegen den Emittenten, den Anbieter oder die Zielgesellschaft gerichtet wird. (2)<sup>1</sup> Die Landesregierungen werden ermächtigt, durch Rechtsverordnung, die im Absatz 1 genannten Klagen einem Landgericht für die Bezirke mehrerer Landgerichte zuzuweisen, sofern dies der sachlichen Forderung oder schnelleren Erledigung der Verfahren dienlich ist. <sup>2</sup>Die Landesregierungen können diese Ermächtigung auf die Landesjustizverwaltungen übertragen.
: <sup>1)</sup> Beachte hierzu Übergangsvorschrift in § 31 EGZPO (Nr. 1a).
= § 32c Ausschließlicher Gerichtsstand bei Musterfeststellungsverfahren. =
Für Klagen in Musterfeststellungsverfahren nach Buch 6 ist das Gericht des allgemeinen Gerichtsstands des Beklagten ausschließlich zuständig, sofern sich dieser im Inland befindet.
'''(Quellinfo = Buch "ZPO" S. 28 ff.)'''
= § 33 Besonderer Gerichtsstand der Widerklage. =
(1) Bei dem Gericht der Klage kann eine Widerklage erhoben werden, wenn der Gegenanspruch mit dem in der Klage geltend gemachten Anspruch oder mit den gegen ihn vorgebrachten Verteidigungsmitteln in Zusammenhang steht. (2) Dies gilt nicht, wenn für eine Klage wegen des Gegenanspruchs die Vereinbarung der Zuständigkeit des Gerichts nach § 40 Abs. 2 unzulässig ist. '''(Quellinfo = Buch "ZPO" S. 28 ff.)'''
= § 34 Besonderer Gerichtsstand des Hauptprozesses. =
Für Klagen der Prozessbevollmächtigten, der Beistände, der Zustellungsbevollmächtigten und der Gerichtsvollzieher wegen Gebühren und Auslagen ist das Gericht des Hauptrozesses zuständig. '''(Quellinfo = Buch "ZPO" S. 28 ff.)'''
= § 35 Wahl unter mehreren Gerichtsständen. =
Unter mehreren zuständigen Gerichten hat der Kläger die Wahl. '''(Quellinfo = Buch "ZPO" S. 28 ff.)'''
= § 35a (aufgehoben) =
= § 36 Gerichtliche Bestimmung der Zuständigkeit.=
(1) Das zuständige Gericht wird durch das im Rechtszug zunächst höhere Gericht bestimmt:1. wenn das an sich zuständige Gericht in einem Einzelnen Fall an der Ausübung des Richteramtes rechtlich oder tatsächlich verhindert ist; 2. wenn es mit Rücksicht auf die Grenzen verschiedener Gerichtsbezirke ungewiss ist, welches Gericht für den Rechtsstreit zuständig sei; 3. wenn mehrere Personen, die bei verschiedenen Gerichten ihren allgemeinen Gerichtsstand haben als Streitgenossen im allgemeinen Gerichtstand verklagt werden sollen und für den Rechtsstreit ein gemeinschaftlicher besonderer Gerichtstand nicht begründet ist; 4. wenn die Klage in den dinglichen Gerichtsstand erhoben werden soll und die Sache in den Bezirken verschiedener Gerichte belegen ist; 5. wenn in einem Rechtsstreit verschiedene Gerichte sich rechtskräftig für zuständig erklärt haben; 6. wenn verschiedene Gerichte, von denen eines für den Rechtsstreit zuständig ist, sich rechtskräftig für unzuständig erklärt haben,
(2) Ist das zunächst höhere gemeinschaftliche Gericht der Bundesgerichtshof, so wird das zuständige Gericht durch das Oberlandesgericht bestimmt, zu dessen Bezirk das zuerst mit der Sache befasste Gericht gehört. '''(Quellinfo = Buch "ZPO" S. 28 ff.)'''
= § 37 Verfahren bei gerichtlicher Bestimmung. =
(1) Die Entscheidung über das Gesuch um Bestimmung des zuständigen Gerichts ergeht durch Beschluss. (2) Der Beschluss, der das zuständige Gericht bestimmt, ist nicht anfechtbar.
'''(Quellinfo = Buch "ZPO" S. 29 ff.)'''
:::'''Titel 3. Vereinbarung über die Zuständigkeit des Gerichts'''
= § 38 Zugelassene Gerichtsstandsvereinbarung =
(1) Ein an sich unzuständiges Gericht des ersten Rechtszuges wird durch ausdrückliche oder stillschweigende Vereinbarung der Parteien zuständig, wenn die Vertragsparteien Kaufleute, juristische Personen des öffentlichen Rechts oder öffentlich-rechtliche Sondervermögen sind. (2)<sup>1)</sup> <sup>1</sup> Die Zuständigkeit eines Gerichts des ersten Rechtszuges kann ferner vereinbart werden, wenn mindestens eine der Vertragsparteien keinen allgemeinen Gerichtsstand in Inland hat. <sup>2</sup> Die Vereinbarung muss schriftlich abschlossen oder, falls sie mündlich getroffen wird, schriftlich bestätigt werden.<sup>3</sup>Hat eine der Parteien einen inländischen allgemeinen Gerichtsstand, so kann für das Inland nur ein Gericht gewählt werden, bei dem diese Partei ihren allgemeinen Gerichtstand hat oder ein besonderer Gerichtstand begründet ist.(3) Im Übrigen ist eine Gerichtsstandsvereinbarung nur zulässig, wenn sie ausdrücklich und schriftlich 1. nach dem Entstehen der Streitigkeit oder 2. für den Fall geschlossen wird, das die im Klageweg in Anspruch zu nehmende Partei nach Vertragsschluss ihren Wohnsitz oder gewöhnlichen Aufenthaltsort aus dem Geltungsbereich dieses Gesetztes verlegt oder ihr Wohnsitz oder gewöhnlicher Aufenthalt im Zeitpunkt der Klageerhebung nicht bekannt ist. '''(Quellinfo = Buch "ZPO" S. 29 ff.)'''
= § 39 Zuständigkeit infolge rügeloser Verhandlung. =
<sup>1</sup>Die Zuständigkeit eines Gericht des ersten Rechtszuges wird ferner dadurch begründet, dass der Beklagte, ohne die Unzuständigkeit geltend zu machen, zur Hauptsache mündlich verhandelt. <sup>2</sup>Dies gilt nicht, wenn die Belehrung nach § 504 unterblieben ist. '''(Quellinfo = Buch "ZPO" S. 29 ff.)'''
= § 40 Unwirksame und unzulässige Gerichtsstandsvereinbarung. =
(1) Die Vereinbarung hat keine rechtliche Wirkung, wenn sie nicht auf ein bestimmtes Rechtsverhältnis und die aus ihm entspringenden Rechtsstreitigkeiten sich bezieht. (2) Eine Vereinbarung is unzulässig, wenn 1. der Rechtsstreit nichtvermögensrechtliche Ansprüche betrifft, die den Amtsgerichten ohne Rücksicht auf den Wert des Streitgegenstandes zugewiesen sind, oder 2. für de Klage ein ausschließlicher Gerichtsstand begründet ist. <sup>2</sup> In diesen Fällen wird die Zuständigkeit eines Gerichts auch nicht durch rügeloses Verhandeln zur Hauptsache begründet. '''(Quellinfo = Buch "ZPO" S. 29 ff.)'''
:::'''Titel 4. Ausschließung und Ablehnung der Gerichtspersonen'''
= § 41 Ausschluss von der Ausübung des Richteramtes. =
Ein Richter ist von der Ausübung des Richteramtes kraft Gesetzes ausgeschlossen; 1. in Sachen, in denen er selbst Partei ist oder bei denen er zu einer Partei in dem Verhältnis eines Mitberechtigten, Mitverpflichteten oder Regresspflichtigen steht;2. in Sachen eines Ehegatten, auch wenn die Ehe nicht mehr besteht; 2a. in Sachen seines Lebenspartners, auch wenn die Lebenspartnerschaft nicht mehr besteht. 3. in Sachen einer Person, mit der er in gerader Linie verwandt oder verschwägert, in der Seitenlinie bis zum dritten Grad verwandt oder bis zum zweiten Grad verschwägert ist oder war; 4. in Sachen, in denen er als Prozessbevollmächtigter oder Beistand einer Partei bestellt oder als gesetzlicher Vertreter einer Partei aufzutreten berechtigt ist oder gewesen ist; 5. in Sachen, in denen er als Zeuge oder Sachverständiger vernommen ist; 6. in Sachen, in denen er in einem früheren Rechtszug oder im schiedsrichterlichen Verfahren bei dem Erlass der angefochtenen Entscheidung mitgewirkt hat, sofern er sich nicht um die Tätigkeit eines beauftragten oder ersuchten Richters handelt; 7. in Sachen wegen überlanger Gerichtsverfahren, wenn er in dem beanstandeten Verfahren in einem Rechtszug mitgewirkt hat, auf dessen Dauer der Entschädigungsanspruch gestützt wird; 8. in Sachen, in denen er an einem Meditationsverfahren oder einem anderen Verfahren der außergerichtlichen Konlikbeilegung mitgewirkt hat.
= § 42 Ablehnung eines Richters. =
(1) Ein Richter kann sowohl in den Fällen, in denen er von der Ausübung des Richteramts kraft Gesetzes ausgeschlossen ist, als auch wegen Besorgnis der Befangenheit abgelehnt werden. (2) Wegen Besorgnis der Befangenheit findet die Ablehnung statt, wenn ein Grund vorliegt, der geeignet ist, Misstrauen gegen die Un parteilichkeit eines Richters zu rechtfertigen. (3) Das Ablehnungsrecht steht in jedem Fall beiden Parteien zu. '''(Quellinfo = Buch "ZPO" S. 29 ff.)'''
= § 43 Verlust des Ablehnungsrechts. =
Eine Partei kann einen Richter wegen Besorgnis der Befangenheit nicht mehr ablehnen, wenn sie sich bei ihm, ohne den ihr bekannten Ablehnungsgrund geltend zu machen, in eine Verhandlung eingelassen oder Anträge gestellt hat. '''(Quellinfo = Buch "ZPO" S. 31 ff.)'''
= § 44 Ablehnungsgesuch. =
(1) Das Ablehnungsgesuch ist bei dem Gericht, dem der Richter angehört, anzubringen; es kann vor der Geschäftsstelle zu Protokoll erklärt werden. (2)<sup>1</sup>Der Ablehnungsgrund ist glaubhaft zu machen, zur Versicherung an Eides statt darf die Partei nicht zugelassen werden. <sup>2</sup>Zur Glaubhaftmachung kann auf das Zeugnis des abgelehnten Richters Bezug genommen werden. (3) Der abgelehnte Richter hat sich über den Ablehnungsgrund dienstlich zu äußern. (4)<sup>1</sup>Wird ein Richter, bei dem die Partei sich in eine Verhandlung eingelassen oder Anträge gestellt hat, wegen Besorgnis der Befangenheit abgelehnt, so ist glaubhaft zu machen, dass der Ablehnungsgrund erst später entstanden oder der Partei bekannt geworden sei.<sup>2</sup>Das Ablehnungsgesuch ist unverzüglich anzubringen. '''(Quellinfo = Buch "ZPO" S. 31 ff.)'''
= § 45 Entscheidung über das Ablehnungsgesuch. =
(1)Über das Ablehnungsgesuch entscheidet das Gericht, dem der Abgelehnte angehört, ohne dessen Mitwirkung. (2)<sup>1</sup>Wird ein Richter beim Amtsgericht abgelehnt, so entscheidet ein anderer Richter des Amtsgerichts über das Gesuch.<sup>2</sup>Einer Entscheidung bedarf es nicht, wenn der abgelehnte Richter das Ablehnungsgesuch für begründet hält. (3)Wird das zur Entscheidung berufene Gericht durch Ausscheiden des abgelehnten Mitglieds beschlussunfähig, so entscheidet das im Rechtszug zunächst höhere Gericht. '''(Quellinfo = Buch "ZPO" S. 31 ff.)'''
= § 46 Entscheidung und Rechtsmittel. =
(1)Die Entscheidung über das Ablehnungsgesuch ergeht durch Beschluss. (2)Gegen den Beschluss, durch den das Gesuch für begründet erklärt wird findet kein Rechtsmittel, gegen den Beschluss, durch den das Gesuch für unbegründet erklärt wird, findet sofortige Beschwerde statt. '''(Quellinfo = Buch "ZPO" S. 31 ff.)'''
= § 47 Unaufschiebbare Amtshandlungen. =
(1) Ein abgelehnter Richter hat vor Erledigung des Ablehnungsgesuchs nur solche Handlungen vorzunehmen, die keinen Aufschub gestatten. (2)<sup>1</sup>Wird ein Richter während der Verhandlung abgelehnt und würde die Entscheidung über die Ablehnung eine Vertagung der Verhandlung erfordern, so kann der Termin unter Mitwirkung des abgelehnten Richters fortgesetzt werden.<sup>2</sup>Wird die Ablehnung für begründet erklärt, so ist der nach Anbringung des Ablehnungsgesuchs liegende Teil der Verhandlung zu wiederholen. '''(Quellinfo = Buch "ZPO" S. 31 ff.)'''
= § 48 Selbstablehnung: Ablehnung von Amts wegen. =
Das für die Erledigung eines Ablehnungsgesuchs zuständige Gericht hat auch dann zu entscheiden, wenn ein solches Gesuch nicht angebracht ist, ein Richter aber von einem Verhältnis Anzeige macht, das eine Ablehnung rechtfertigen könnte, oder wenn aus anderer Veranlassung Zweifel darüber entstehen, ob ein Richter kraft Gesetzes ausgeschlossen sei. '''(Quellinfo = Buch "ZPO" S. 31 ff.)'''
= § 49 Urkundsbeamte. =
Die Vorschriften dieses Titels sind auf den Urkundsbeamten der Geschäftsstelle entsprechend anzuwenden; die Entscheidung ergeht durch das Gericht, bei dem er angestellt ist.
:::::::'''Abschnitt 2 Parteien'''
::::'''Titel 1. Parteifähigkeit: Prozessfähigkeit'''
= § 50 Parteifähigkeit. =
(1) Parteifähig ist, wer rechtsfähig ist. (2) Ein Verein, der nicht rechtsfähig ist, kann klagen und verklagt werden; in dem Rechtsstreit hat der Verein die Stellung eines rechtsfähigen Vereins.
= § 51 Prozessfähigkeit; gesetzliche Vertretung; Prozessführung. =
(1) Die Fähigkeit einer Partei, vor Gericht zu stehen, die Vertretung nicht prozessfähiger Parteien durch andere Personen (gesetzliche Vertreter) und die Notwendigkeit einer besonderen Ermächtigung zur Prozessführung bestimmt sich nach den Vorschriften des bürgerlichen Rechts, soweit nicht die nachfolgenden Paragraphen abweichende Vorschriften enthalten. (2) Das Verschulden eines gesetzlichen Vertreters steht dem Verschulden der Partei gleich. (3) Hat eine nicht prozessfähige Partei, die eine volljährige natürliche Person ist, wirksam eine andere natürliche Person schriftlich mit ihrer gerichtlichen Vertretung bevollmächtigt, so steht diese Person einem gesetzlichen Vertreter gleich, wenn die Bevollmächtigung geeignet ist, gemäß '''''[''bis 31.12.2022:'''§ 1896 Abs. 2 Satz 2 des Bürgerlichen Gesetzbuchs'']''''' [ab 1.1.2023:''' ''§ 1814 Absatz 3 Satz 2 Nummer 1 des Bürgerlichen Gesetzbuchs''']''''' die Erforderlichkeit einer Betreuung entfallen zu lassen.
= § 52 Umfang der Prozessfähigkeit. =
(1)<sup>1</sup> Eine Person ist insoweit prozessfähig, als sie sich durch Verträge verpflichten kann
= § 53 Prozessfähigkeit bei Betreuung oder Pflegschaft. =
''[§ 53 bis 31.12.2022:]''
Wird in einem Rechtsstreit eine prozessfähige Person durch einen Betreuer oder Pfleger vertreten, so steht sie für den Rechtsstreit einer nicht prozessfähigen Person gleich.
= § 53 Prozessfähigkeit bei rechtlicher Betreuung. =
''[§ 53 ab 1.1.2023:]''
(2) Bei Personen, für die ein Betreuer bestellt ist, richtet sich die Prozessfähigkeit nach den allgemeinen Vorschriften.(2)<sup>1</sup>Wird ein Betreuer in einem Rechtsstreit durch einen Betreuer vertreten, kann der Betreuer in jeder Lage des Verfahrens gegenüber dem Prozessgericht schriftlich oder zu Protokoll der Geschäftsstelle erklären, dass der Rechtsstreit fortan ausschließlich durch ihn geführt wird (Ausschließlichkeitserklärung).<sup>2</sup>Mit Eingang der Ausschließlichkeitserklärung steht der Betreute für den weiteren Rechtsstreit einer nicht prozessfähigen Person gleich.<sup>3</sup>Der Betreuer kann die Ausschließlichkeitserklärung jederzeit mit Wirkung für die Zukunft zurücknehmen.
= § 53a =
(aufgehoben)
= § 54 Besondere Ermächtigung zu Prozesshandlungen. =
Einzelne Prozesshandlungen, zu denen nach den Vorschriften des bürgerlichen Rechts eine besondere Ermächtigung erforderlich ist, sind ohne sie gültig, wenn die Ermächtigung zur Prozessführung im Allgemeinen erteilt oder die Prozessführung auch ohne eine solche Ermächtigung im Allgemeinen statthaft ist. '''(Quellinfo = Buch "ZPO" S. 32 ff.)'''
= § 55 Prozessfähigkeit von Ausländern. =
Ein Ausländer, dem nach dem Recht seines Landes die Prozessfähigkeit mangelt, gilt als prozessfähig, wenn ihm nach dem Recht des Prozessgerichts die Prozessfähigkeit zusteht. '''(Quellinfo = Buch "ZPO" S. 33 ff.)'''
= § 56 Prüfung von Amts wegen. =
(1) Das Gericht hat den Mangel der Parteifähigkeit, der Prozessfähigkeit, der Legitimation eines gesetzlchen Vetreters und der erforderlichen Ermächtigung zur Prozessführung von Amts wegen zu berücksichtigen. '''(Quellinfo = Buch "ZPO" S. 33 ff.)'''
= § 57 Prozesspfleger. =
(1) Soll eine nicht prozessfähige Partei verklagt werden, die ohne gesetzlichen Vertreter ist, so hat ihr der Vorsitzende des Prozess-Eintritt des gesetzten Vertreters einen besonderen Vertreter zu bestellen.
'''(Quellinfo = Buch "ZPO" S. 33 ff.)'''
= § 58 Prozesspfleger bei herrenlosem Grundstück oder Schiff. =
(1) Soll ein Recht an einem Grundstück, das von dem bisherigen Eigentümer nach § 928 des Bürgerlichen Gesetzbuchs aufgegeben und von dem Aneignungsberechtigten noch nicht erworben worden ist,im Wege der Klage geltend gemacht werden, so hat der Vorsitzende des Prozessgerichts auf Antrag einen Vertreter zu bestellen, dem bis zur Eintragung eines neuen Eigentümers die Wahrnehmung, der sich aus dem Eigentum ergebenden Rechte und Verpflichtungen im Rechtsstreit obliegt. (2) Absatz 1 gilt entsprechend, wenn im Wege der Klage ein Recht an einem eingetragenen Schiff oder Schiffsbauwerk geltend gemacht werden soll, da von dem bisherigen Eigentümer nach § 7 des Gesetztes über Rechte an eingetragenen Schiffen und Schiffsbauwwerken vom 15. November 1940 (RGB1. IS. 1499) aufgegeben und von Aneignungsberechtigten noch nicht erworben worden ist. '''(Quellinfo = Buch "ZPO" S. 33 ff.)'''
:::'''Titel 2. Streitgenossenschaft'''
= § 59 Streitgenossenschaft bei Rechtsgemeinschaft oder Identität des Grundes. =
Mehrere Personen können als Streitgenossen gemeinschaftlich klagen oder verklagt werden, wenn Sie hinsichtlich des Streitgegenstandes in Rechtsgemeinschaft stehen oder wenn sie aus demselben tatsächlichen und rechtlichen Grund berechtigt oder verpflichtet sind.
= § 60 Streitgenossenschaft bei Gleichartigkeit der Ansprüche. =
Mehrere Personen können auch dann als Streitgenossen gemeinschaftlich klagen oder verklagt werden, wenn gleichartige und auf einem im Wesentlichen gleichartigen tatsächlichen und rechtlichen Grund beruhende Ansprüche oder Verpflichtungen. den Gegenstand des Rechtsstreits bilden. '''(Quellinfo = Buch "ZPO" S. 34 ff.)'''
= § 61 Wirkung der Streitgenossenschaft. =
Streitgenossen stehen, soweit nicht aus den Vorschriften des bürgerlichen Rechts oder dieses Gesetzes sich ein anderes egibt, dem Gegner dergestallt als Einzelne <sup>1)</sup> gegenüber, dass die Handlungen des einen Streitgenossen dem anderen weder zum Vorteil noch zum Nachteil gereichen. '''(Quellinfo = Buch "ZPO" S. 34 ff.)'''
= § 62 Notwendige Streitgenossenschaft. =
(1) Kann das streitige Rechtsverhäntlnis allen Streigenossen gegenüber nur einheitlich festgestellt werden oder werden, wenn ein Termin oder eine Frist nur von einzelnen Streitgenosen versäumt wird, die säumigen Steitgenossen als durch die nicht säumigen vertreten angesehen. (2) Die säumigen Streitgenossen ind auch in dem späteren Verfahren zuzuziehen. '''(Quellinfo = Buch "ZPO" S. 34 ff.)'''
= § 63 Prozessbetrieb; Ladungen. =
Das Recht zur Betreibung des Prozesses steht jedem Streitgenossen zu; zu allen Terminen sind sämtliche Streitgenossen zu laden: '''(Quellinfo = Buch "ZPO" S. 34 ff.)'''
:::'''Titel 3. Beteiligung Dritter am Rechtsstreit'''
= § 64 Hauptintervention. =
Wer die Sache oder das Recht, worüber zwischen anderen Personen ein Rechtsstreit anhängig geworden ist, ganz oder teilweise für sich in Anspruch nimmt, ist bis zur rechtskräftigen Entscheidung dieses Rechtsstreits berechtigt, seinen Anspruch durch eine gegen beide Parteien gerichtete Klage bei dem Gericht geltend zu machen, vor dem der Rechtsstreit im ersten Rechtszug anhängig wurde. '''(Quellinfo = Buch "ZPO" S. 34 ff.)'''
= § 65 Aussetzung des Hauptprozesses. =
Der Hauptprozess kann auf Antrag einer Partei bis zur rechtskräfigten Entscheidung über die Hauptintervention ausgesetzt werden. '''(Quellinfo = Buch "ZPO" S. 34 ff.)'''
= § 66 Nebenintervention. =
(1) Wer ein rechtliches Interesse daran hat, dass in einem zwischen anderen Personen anhängigen Rechtsstreit die eine Partei obsiege, kann dieser Partei zum Zwecke ihrer Unterstützung beitreten. (2) Die Nebenintervention kann in jeder Lage des Rechtsstreits bis zur rechtskräftigen Entscheidung auch in Verbindung mit der Einlegung eines Rechtsmittels, erfolgen. '''(Quellinfo = Buch "ZPO" S. 34 ff.)'''
= § 67 Rechtsstellung des Nebenintervenienten. =
<sup>1</sup>Der Nebenintervenient muss den Rechtsstreit in der Lage annehmen, in der er sich zur Zeit seinss Beitritts befindet; er ist berechtigt, Angriffs- und Verteidigungsmittel geltend zu machen und alle Prozeesshanduungen wirksam vorzunehmen, insoweit nicht seine Erklärungen und Handlungen mit Erklärungen und Handlungen der Hauptpartei in Widerspruch stehen. <sup>2</sup>Für ihn gelten die §§ 141 und 278 Absatz 3 entsprechend.
= § 68 Wirkung der Nebenintervention. =
Der Nebenintervenient wird im Verhältnis zu der Hauptpartpartei mit der Behauptung nicht gehört, dass der Rechtsstreit, wie er dem Richter vorgelegt habe, unrichtig entscheiden sei; er wird mit der Behauptung, das die Hauptpartei den Rechtsstreit mangelhaft geführt habe, nur insoweit gehört, als er durchh die Lage des Rechtsstreits zur Zeit seines Beitritts oder durch Erklärungen und Handlungen der Hauptpartei verhindert worden ist, Angriffs- oder Verteidigungsmittel geltend zu machen, oder als Angriffs- oder Verteidigungsmittel, die ihm unbekannt waren, von der Hauptpartei absichtlich oder durch grobes Verschulden nicht geltend gemacht sind.
= § 69 Streitgenössische Nebenintervention. =
Insofern nach den Vorschriften des bürgerliches Rechts die Rechtskraft der in dem Hauptprozess erlassenen Entscheidung auf das Rechtsverhältnis des Nebenintervenienten zu dem Gegner von Wirksamkeit ist, gilt der Nebenintervenient im Sinne des § 61 als Streitgenosse de Hauptpartei.
= § 70 Beitritt des Nebenintervenienten. =
(1) <sup>1</sup> Der Beitritt des Nebenintervenienten erfolgt durch Einreichung eines Schriftsatzes bei dem Prozessgericht und, wenn er mit der Einlegung eines Rechtsmitels verbunden wird, durch Einreichung eines Schriftsatzes bei dem Rechtsmittelgericht. <sup>2</sup> Der Schriftsatz ist beiden Parteien zuzustellen und muss enthalten:<br> 1. die Bezeichnung der Parteien und des Rechtssteireits; <br> 2. die bestimmte Angabe des Interesses, das der Nebenintervenient hat; <br>3. die Erklärung des Beitritts.
:(2) Außerdem gelten die allgemeinen Vorschriften über die vorbereitenden Schriftsätze. ''(Quellinfo = Buch "ZPO" S. 35 ff.)'''
= § 71 Zwischenstreit über Nebenintervention. =
(1)<sup>1</sup> Über den Antrag auf Zurückweisung einer Nebenintervention wird nach mündlicher Verhandlung unter den Parteien und dem Nebenintervenienten entschieden.<sup>2</sup> Der Nebenintervenient ist zuzulassen, wenn er sei Interesse glaubhaft macht.<br> (2) Gegen das Zwischenurteil findet sofortige Beschwerde statt.<br> (3) Solange nicht die Unzulässigkeit der Intervention rechtskräftig ausgesprochen ist, wird der Intervenient im Hauptverfahren zugezogen. ''(Quellinfo = Buch "ZPO" S. 35 ff.)'''
= § 72 Zulässigkeit der Streitverkündigung. =
(1) Eine Partei, die für den Fall des ihr ungünstigen Ausganges des Rechtsstreits einen Anspruch auf Gewährleistung oder Schadloshaltung gegen einen Dritten erheben zu können glaubt oder den Anspruch eines Dritten besorgt, kann bis zur rechtskräftigen Entscheidung des Rechtsstreits dem Dritten gerichtlich den Streit verkünden.<br> (2)<sup>1</sup> Das Gericht und ein vom Gericht ernannter Sachverständiger sind nicht Dritter im Sinne dieser Vorschrift. <sup>2</sup>§73 Satz 2 ist nicht anzuwenden.<br> (3) Der Dritte ist zu einer weiteren Streitverkündung berechtigt. '''(Quellinfo = Buch "ZPO" S. 35 ff.)'''
= § 73 Form der Streitverkündigung. =
<sup>1</sup>Zum Zwecke der Streitverkündung hat die Partei einen Schriftsatz einzureichen, in dem der Grund der Streitverkündung und die Lage des Rechtsstreits anzugeben ist. <sup>2</sup>Der Schriftsatz ist dem Dritten zuzustellen und dem Gegner des Streitverkünders in Abschrift mitzuteilen. <sup>3</sup>Die Streitverkündung wird erst mit der Zustellung an den Dritten wirksam.'''(Quellinfo = Buch "ZPO" S. 35 ff.)'''
= § 74 Wirkung der Streitverkündigung. =
(1) Wenn der Dritte dem Streitverkünder beitritt, so bestimmt sich sein Verhältnis zu den Parteien nach den Grundsätzen über die Nebenintervention. <br> (2) Lehnt der Dritte den Beitritt ab oder erklärt er sich nicht, so wird der Rechtsstreit ohne Rücksicht auf ihn fortgesetzt. <br> (3) In allen Fällen dieses Paragraphen sind gegen den Dritten die Vorschriften des § 68 mit der Abweichung anzuwenden, dass statt der Zeit des Beitritts die Zeit entscheidet, zu welcher der Beitritt infolge der Streitverkündung möglich war. '''(Quellinfo = Buch "ZPO" S. 36 ff.)'''
= § 75 Gläubigerstreit. =
<sup>1</sup>Wird von dem verklagten Schuldner einem Dritten, der die geltend gemachte Forderung für sich in Anspruch nimmt, der Streit verkündet und tritt der Dritte in den Streit ein, so ist der Beklagte, wenn er den Betrag der Forderung zugunsten der streitenden Gläubiger unter Verzicht auf das Recht zur Rücknahme hinterlegt, auf seinen Antrag aus dem Rechtsstreit unter Verurteilung in die durch seinen unbegründeten Widerspruch veranlassten Kosten zu entlassen und der Rechtsstreit über die Berechtigung an der Forderung zwischen den streitenden Gläubigern allein fortzusetzen.<sup>2</sup>Dem Obsiegenden ist der hinterlegte Betrag zuzusprechen und der Unterliegende auch zur Erstattung der dem Beklagten entstandenen, nicht durch dessen unbegründeten Widerspruch veranlassten Kosten, einschließlich der Kosten der Hinterlegung zu verurteilen.
= § 76 Urheberbenennung bei Besitz. =
(1)<sup>1</sup>Wer als Besitzer einer Sache verklagt ist, die er auf Grund eines Rechtsverhältnisse der im § 868 des Bürgerlichen Gesetzbuchs bezeichneten Art zu besitzen behauptet, kann vor der Verhandlung zur Hauptsache unter Einreichung eines Schriftsatzes, in dem er den mittelbaren Besitzer benennt, und einer Streiverkündigungsschrift die Ladung des mittelbaren Besitzers zur Erklärung beantragen.<sup>2</sup> Bis zu dieser Erklärung oder bis zum Schluss des Termins, in dem sich der Benannte zu erklären hat, kann der Beklagte die Verhandlung zur Hauptsache verweigern. <br> (2) Bestreitet der Benannte die Behauptung des Beklagten oder erklärt er sich nicht, so ist der Beklagte berechtigt, dem Klageantrage zu genügen. <br> (3)<sup>1</sup>Wird die Behauptung des Beklagten von dem Benannten als richtig anerkannt, so ist dieser berechtigt, mit Zustimmung des Beklagten an dessen Stelle zu übernehmen.<sup>2</sup>Die Zustimmung des Klägers ist nur insoweit erforderlich, als er Ansprüche geltend macht, die unabhängig davon sind, dass der Beklagte auf Grund eines Rechtsverhältnisses der im Absatz 1 bezeichneten Art besitzt.<br>(4)<sup>1</sup>Hat der Benannte den Prozess übernommen, so ist der Beklagte auf seinen Antrag von der Klage zu entbinden.<sup>2</sup>Die Entscheidung ist in Ansehung der Sache selbst auch gegen den Beklagten wirksam und vollstreckbar.
= § 77 Urheberbenennung bei Eingentumsbeeinträchtigung. =
Ist von dem Eigentümer einer Sache oder von demjenigen, dem ein Recht an einer Sache zusteht, wegen einer Beeinträchtigung des Eigentums oder seines Rechts Klage auf Beseitigung der Beeinträchtigung oder auf Unterlassung weiter Beeinträchtigungen erhoben, so sind die Vorschriften des § 76 entsprechend an eines Dritten vorgenommen zu haben behauptet.
= § 78 Anwaltsprozess. =
= § 78a =
(weggefallen)
= § 78b Notanwalt. =
(1) Insoweit eine Vertretung durch Anwälte geboten ist, hat das Prozessgericht einer Partei auf ihren Antrag durch Beschluss für den Rechtszug einen Rechtsanwalt zur Wahrnehmung ihrer Rechte beizuordnen, wenn sie einen zu ihrer Vertretung bereiten Rechtsanwalt nicht findet und die Rechtsverfolgung oder Rechtsverteidigung nicht mutwillig oder aussichtslos erscheint. (2) Gegen den Beschluss, durch den die Beiordnung eines Rechtsanwalts abgelehnt wird, findet die sofortige Beschwerde statt.
= § 78c Auswahl des Rechtsanwalts. =
= § 79 Parteiprozess. =
= § 80 Prozessvollmacht. =
<sup>1</sup>Die Vollmacht ist schriftlich zu den Gerichtsakten einzureichen. <sup>2</sup>Sie kann nachgereicht werden; hierfür kann das Gericht eine Frist bestimmen.
= § 81 Umfang der Prozessvollmacht. =
= § 82 Geltung für Nebenverfahren. =
Die Vollmacht für den Hauptprozess umfasst die Vollmacht für das eine Hautintervention, einen Arrest oder eine einstweilige Verfügung betreffende Verfahren. '''(Quellinfo = Buch "ZPO" S. 39 ff.)'''
= § 83 Beschränkung der Prozessvollmacht. =
= § 84 Mehrere Prozessbevollmächtigte. =
<sup>1</sup>Mehrere Bevollmächtigte sind berechtigt, sowohl gemeinschaftlich als einzeln die Partei zu vertreten. <sup>2</sup>Eine abweichende Bestimmung der Vollmacht hat dem Gegner gegenüber keine rechtliche Wirkung
= § 85 Wirkung der Prozessvollmacht. =
= § 86 Fortbestand der Prozessvollmacht. =
= § 87 Erlöschen der Vollmacht. =
= § 88 Mangel der Vollmacht. =
= § 89 Vollmachtloser Vertreter. =
= § 90 Beistand. =
::::::::::::: '''Titel 5 Prozesskosten'''
= § 91 Grundsatz und Umfang der Kostenpflicht. =
= § 91a Kosten bei Erledigung der Hauptsache. =
= § 92 Kosten bei teilweisem Obsiegen. =
= § 93 Kosten bei sofortigem Anerkenntnis. =
= § 93a =
(aufgehoben)
= § 93b Kosten bei Räumungsklagen. =
= § 93c, 93d =
= § 94 Kosten bei übergegangenem Anspruch. =
= § 95 Kosten bei Säumnis oder Verschulden. =
= § 96 Kosten erfolgloser Angriff- oder Verteidigungsmittel. =
= § 97 Rechtsmittelkosten. =
= § 98 Vergleichtskosten. =
= § 99 Anfechtung von Kostenentscheidungen. =
= § 100 Kosten bei Streitgenossen. =
= § 101 Kosten einer Nebenintervention. =
= § 102 =
(weggefallen)
= § 103 Kostenfestsetzungsgrundlage: Kostenfestsetzungsantrag. =
= § 104 Kostenfestsetzungsverfahren =
= § 105 Vereinfachter Kostenfestsetzungsbeschluss. =
= § 106 Verteilung nach Quoten. =
= § 107 Änderung nach Streitwertfestsetzung. =
(1)<sup>1</sup> Ergeht nach der Kostenfestsezung eine Entscheidung, durch die der Wert des Streitgegenstandes festgesetzt wird, so ist, falls diese Entscheidung von der Wertberechnung abweicht, die der Kostenfestsetzung zugrunde liegt, auf Antrag die Kostengestsetzung entsprechend abzuändern.<sup>2</sup>Über den Antrag entscheidet das Gericht des ersten Rechtszuges. (2) <sup>1</sup> Der Antrag ist binnen der Frist von einem Monat bei der Geschäftsstelle anzubringen. <sup>2</sup>Die Frist beginnt mit der Zustellung und wenn es einer solchen nicht bedarf, mit der Verkündung des den Wert des Streitgegenstandes festsetzenden Beschlusses. (3) Die Vorschriften des § 104 Abs. 3 sind anzuwenden.'''(Quellinfo = Buch "ZPO" S. 45 ff.)'''
= § 108 Art und Höhe der Sicherheit. =
= § 109 Rückgabe der Sicherheit. =
= § 110<sup>1)</sup> Prozesskostensiocherheit. =
= § 111 Nachträgliche Prozesskostensicherheit. =
= § 112 Höhe der Prozesskostensicherheit. =
= § 113 Fristbestimmung für Prouesskostensicherheit. =
(1) <sup>1</sup>Das Gericht hat dem Kläger bei Anordnung der Sicherheitsleistung eine Frist zu bestimmen, binnen der die Sicherheit zu leisten ist. <sup>2</sup>Nach Ablauf der Frist ist auf Antrag des Beklagten, wenn die Sicherheit bis zur Entscheidung nicht geleistet ist. die Klage für zurückgenommen zu erklären oder, wenn über ein Rechtsmittel des Klägers zu verhandeln ist, dieses zu verwerfen.
::::::::::::: '''Titel 7 Prozesskostenhilfe<sup>1</sup> und Prozesskostenvorschuss'''
= § 115 Einsatz von Einkommen und Vermögen. =
(1) <sup>1</sup>Die Partei hat ihr Einkommen einzusetzen. <sup>2</sup>Zum Einkommen gehören alle Einkünfte in Geld oder Geldwert. <sup>3</sup>Von ihm sin abzusetzen: 1. a) die in §82 Abs. 2 des Zwölften Buches Sozialgesetzbuch<sup>2)</sup>bezeichneten Beträge: '''(Quellinfo = Buch "ZPO" S. 46 ff.)'''
=____________________________________________________________________=
<sup>1</sup>Vgl. Art. 220 bis 24 Haager Übereinkommen über den Zivilprozess v. 1.3.1954 (BGB1. 1958 II S 576, 577). Siehe ferner § 11 G über die Rechtsstellung heimatloser Ausländer im Bundesgebiet v. 25.4.1951 (BGB1 I.S. 269), zuletzt geänd. durch G v. 30.7.2004 (BGB1. I S. 1950) und für Mitglieder der in der Bundesrepublik stationierten ausländischen Truppen. vgl. Art. 31 Zusatzabkommen zum NATO-Truppenstatut v. 3.8.1959 (BGB1. 1961 II S. 1218), zuletzt geändert. durch Abk. v. 28.9.1994 (BGB1. II S. 2598).
<sup>2</sup>§ 82 Abs. 2 und 3 des Zwölften Buches Sozialgesetzbuch v. 27.12.2003 (BGB1, I S. 3022, 3023),"(2)<sup>1</sup>Von dem Einkommen sind abzusetzen <br> 1. auf die Einkommen entrichtete Steuern. <br> 2. Pflichtbeiträge zur Sozialversicherung einschließlich der Beiträge zur Arbeitsförderung. →</br>
(Fortsetzung der Anm. von voriger Seite)<br>
3. Beiträge zu öffentlichen oder privaten Versicherungen oder ähnlichen Einrichtungen, soweit diese Beiträge gesetzlich vorgeschrieben oder nach #grund und Höhe angemessen sind, sowie geförderte Altersvorsorgeverträge nach § 82 des Einkommensteuergesetzes, soweit sie den Mindeststeigenbetrag nach § 86 des Einkommensteuergesetzes nicht überschreiten, und <br>4. die mit der Erzielen des Einkommens verbundenen notwendigen Ausgaben.<br><sup>2</sup>Erhält eine leistungsberechtigte Person aus einer Tätigkeit Bezüge oder Einnahmen, die nach § 3 Nummer 12,26, 26a oder 26b des Einkommensteuergesetzes steuerfrei sind oder die als Taschengeld Jugendfreiwilligendienstegesetzes gezahlt werden, ist abweichend von Satz 1 Nummer 2 bis 4 und den Absätzen 3 und 6 ein Betrag von bis zu 250 Euro monatlich nicht als Einkommen zu berücksichtigen.<br><sup>3></sup>Soweit ein Betrag nach Satz 2 in Anspruch genommen wird, gelten die Beträge nach Absatz 3 Satz 1 zweiter Halbsatz und nach Absatz 6 Satz 1 zweiter Halbsatz insoweit als ausgeschöpft. <br>(3)<sup>1</sup>Bei der Hilfe zum Lebensunterhalt und Grundsicherung im Alter und bei Erwerbsminderung ist ferner ein Betrag in Höhe von 30 vom Hundert des Einkommens aus selbständiger und nichtselbständiger Tätigkeit der Leistungsberechtigten abzusetzen, höchstens jedoch 50 vom Hundert der Regelbedarfsstufe 1 nach der Anlage zu § 28. <sup>2</sup>Abweichend von Satz 1 ist bei einer Beschäftigung in einer Werkstatt für behinderte Menschen oder bei einem anderen Leistungsanbieter nach § 60 des Neunten Buches v. 23.12.2016 (BGB1. I S. 3234), zuletzt geändert. durch G. v 16.6.2021 (BGB1. I S. 1810) von dem Entgelt ein Achtel der Regelbedarfsstufe 1 nach der Anlage zu § 28 zuzüglich 50 vom Hundert des diesen Betrag übersteigenden Entgelts abzusetzen. <sup>3</sup>Im Übrigen kann in begründeten Fällen ein anderer als in Satz 1 festgelegter Betrag vom Einkommen abgesetzt werden."
Abschnitt 2. Parteien <br><br>
b) bei Parteien, die ein Einkommen aus Erwerbstätigkeit erzielen, ein Betrag in Höhe von 50 vom Hundert des Regelsatzes für den alleinstehenden oder alleinerziehenden Leistungsberechtigten vom Bund gemäß der Regelbedarfsstufe 1 nach der Anlage zu § 28 des Zwölften Buches Sozialgesetzbuch festgesetzt oder fortgeschrieben worden ist.<br>
2 a.) für die Partei und ihren Ehegatten oder ihren Lebenspartner jeweils ein Betrag in Höhe des um 10 vom Hundert erhöhten Regelsatzes, der für den alleinstehenden oder Alleinerziehenden Leistungsberechtigten vom Bund gemäß der Regelbedarsstufe 1 nach der Anlage zu § 28 des Zwölften Buches Sozialgesetzbuch festgesetzt oder fortgeschrieben worden ist;<br>
b) bei weiteren Unterhaltsleistungen auf Grund gesetzlicher Unterhaltspflicht für jede unterhaltsberechtigte Person jeweils ein Betrag in Höhe des um 10 vom Hundert erhöhten Regelsatzes, der für eine Person ihres Alters vom Bund gemäß den Regelbedarfsstufen 3 bis 6 nach der Anlage zu § 28 des Zwölften Buches Sozialgesetzbuch festgesetzt oder fortgeschrieben worden ist;<br>
3. die Kosten der Unterkunft und Heizung, soweit sie nicht in einem auffälligen Missverhältnis zu den Lebensverhältnissen der Partei stehen;<br>
4. Mehrbedarfe nach § 21 des Zweiten Buches Sozialgesetzbuch und nach § 30 des Zwölften Buches Sozialgesetzbuch; <br>
5. weitere Beträg, soweit dies mit Rücksicht auf besondere Belastungen angemessen ist; § 1610a dass Bürgerlichen Gesetzbuchs gilt entsprechend.<br></br>
<sup>4</sup>Maßgeblich sind die Beträge, die zum Zeitpunkt der Bewilligung der Prozesskostenhilfe gelten.<aup>5</sup>Soweit am Wohnsitz der Partei aufgrund einer Neufestsetzung oder jeder Fortschreibung nach § 20 Absatz 2 bis 4 des Zwölften Buches Sozialgesetzbuch höhere Regelsätze gelten, sind diese heranzuziehen. <sup>6</sup>Das Bundesministerium der Justiz und für Verberbraucherschutz gibt bei jeder Neufestsetzung oder jeder Fortschreibung die maßgebenden Beträge nach Satz 3 Nummer 1 Buchstabe b und Nummer 2 und nach Satz 5 im Bundesgesetzblatt bekannt. <sup>'''1)'''</sup> <sup>7</sup>Diese Beträge sind, soweit sie nicht volle Euro ergeben, bis zu 0,49 Euro abzurunden und von 0,50 Euro an aufzurunden. <sup>8</sup>Die Unterhaltsfreibeträge nach Satz 3 Nr. 2 vermindern sich um eigenes Einkommen der Unterhaltsberechtigten Person.<sup>9</sup>Wird eine Geldrente gezahlt, so ist sie anstelle des Freibetrages abzusetzen, soweit dies angemessen ist.
(2)<sup>1</sup>Von dem nach Abzügen verbleibenden Teil des monatlichen Einkommens (einzusetzendes Einkommen) sind Monatsraten in Höhe der Hälfte des einzusetzenden Einkommens festzusetzen; die Monatsraten sind auf volle Euro abzurunden. <sup>2</sup>Beträgt die Höhe einer Monatsrate weniger als 10 Euro, ist von der Festsetzung der Monatsraten abzusehen.<sup>3</sup>Bei einem einzusetzenden Einkommen von mehr als 600 Euro beträgt die Monatsrate 300 Euro zuzüglich des Teils des einzusetzenden Einkommens, der 600 Euro übersteigt.<sup>4</sup>Unabhängig von der Zahl der Rechtszüge sind höchstens 48 Monatsraten aufzubringen. (3)<sup>1</sup>Die Partei hat ihr Vermögen einzusetzen, soweit dies zumutbar ist. <sup>2</sup>§9 des Zwölften Buches Sozialgesetzbuch gilt entsprechend.(4) Prozesskostenhilfe wird nicht bewilligt, wenn die Kosten der Prozessführung der Partei vier Monatsraten und die aus dem Vermögen aufzubringenden Teilbeträge voraussichtlich nicht übersteigen.
=____________________________________________________________________=
{| class="wikitable" style="text-align: center; color: black;"
|
|Freibetrag <br> Bund <br></br>
|Freibetrag in <br>den Land-<br>kreisen Fürs-<br>tenfeldbruck<br>und<br>Starn-<br>berg</br>
|Freibetrag im <br>Landkreis<br>München<br>
|Freibetrag in <br>der Landes-<br>hauptstadt<br>München<br>
|-
|Parteien, die ein Einkommen aus Er-<br> werbtätigkeit erzielen (§ 115 Absatz 1 <br> Satz 3 Nummer 1 Buchstabe b der <br> Zivilprozessordnung)
|223 Euro
|235 Euro
|235 Euro
|234 Euro
|-
|Partei, Ehegatte oder Lebenspartner<br> (§ 115 Absatz 1 Satz 3 Nummer 2 <br> Buchstabe a der Zivilprozessverordnung) </br>
|491 Euro
|516 Euro
|517 Euro
|515 Euro
|-
|Freibetrag der unterhaltsberechtigte Er-<br> wachsene (§ 115 Absatz 1 Satz 3 Num- <br> mer 2 Buchstabe b der Zivilprozessord-<br> nungRegelbedarfsstufe 3) </br>
|393 Euro
|414 Euro
|414 Euro
|411 Euro
|-
|Freibetrag für unterhaltsberechtigte Ju- <br> endliche vom Beginn des 15. bis zur <br> Vollendung des 18. Lebensjahres (§ 115 <br> Absatz 1 Satz 3 Nummer 2 Buchstabe <br> b der Zivilprozessordnung Regelte- <br> darfstufe 4) </br>
|410 Euro
|430 Euro
|432 Euro
|429 Euro
|-
|Freibetrag für unterhaltsberechtigte <br> Kinder vom Beginn des siebten bis zur <br> Vollendung des 14. Lebensjahres (§ 115 <br> Absatz 1 Satz 3 Nummer 2 Buchstabe<br> b der Zivilprozessordnung Regel- <br> darfstufe 5) </br>
|340 Euro
|353 Euro
|359 Euro
|353 Euro
|-
|Freibetrag für unterhaltsberechtigte <br> Kinder bis zur Vollendung des sechsten <br> Lebensjahres (§ 115 Absatz 1 Satz 3<br>Nummer 2 Buchstabe b der Zivilpro- <br> zessordnung Regelbedarfsstufe 6) </br>
|311 Euro
|325 Euro
|328 Euro
|323 Euro"
|-
|}
= § 116 Partei kraft Amtes: juristische Person; parteifähige Vereinigung. =
<sup>1</sup> Prozesskostenhilfe erhalten auf Antrag 1. eine Partei kraft Amtes, wenn die Kosten aus der verwalteten Vermögensmasse nicht aufgebracht werden können und den am Gegenstand des Rechtsstreite wirtschaftlich Beteiligten nicht zuzumuten ist, die Kosten aufzubringen; 2. eine juristische Person oder parteifähige Vereinigung, die im Inland, in einem anderen Mitgliedstaat der Europäischen Union oder einem anderen Vertragsstaates des Abkommens über den Europäischen Wirtschaftsraum gegründet und dort ansässig ist, wenn die Kosten weder von ihr noch von den am Gegenstand des Rechtsstreits wirtschaftlich Beteiligten aufgebracht werden können und wenn die Unterlassung der Rechtsverfolgung oder Rechtsverteidigung allgemeinen Interessen zuwiderlaufen würde.
<sup>2</sup>§ 114 Absatz 1 Satz 1 letzter Halbsatz und Absatz 2 ist anzuwenden. <sup>3</sup> Können die Kosten nur zum Teil oder nur in Teilbeträgen aufgebracht werden, so sind die entsprechenden Beträge zu zahlen.
= § 117 Antrag. =
(1)<sup>1</sup>Der Antrag auf Bewilligung der Prozesskostenhilfe ist bei dem Prozessgericht zu stellen; er kann vor der Geschäftsstelle zu Protokoll erklärt werden. <sup>2</sup>In dem Antrag ist das Streitverhältnis unter Angabe der Beweismittel darzustellen. <sup>3</sup>Der Antrag auf Bewilligung von Prozesskostenhilfe für die Zwangsvollstreckung ist bei dem für die Zwangsvollstreckung zuständigen Gericht zu stellen.<br>(2)<sup>1</sup>Dem Antrag sind eine Erklärung der Partei über ihre persönlichen und wirtschaftlichen Verhältnisse (Familienverhältnisse, Beruf , Vermögen , Einkommen und Lasten) sowie entsprechende Belege beizufügen. <sup>2</sup>Die Erklärung und die Belege dürfen dem Gegner nur it Zustimmung der Partei zugänglich gemacht werden<sup>1)</sup>es sei denn, der Gegner hat gegen den Antragsteller nach den Vorschriften des bürgerlichen Rechts einen Anspruch auf Auskunft über Einkünfte und Vermögen des Antragstellers.<sup>3</sup>Dem Antragsteller ist vor der Übermittlung seiner Erklärung an den Gegner Gelegenheit zur Stellungnahme zu geben.<sup>4</sup>Er ist über die Übermittlung seiner Erklärung zu unterrichten.<br>(3)<sup>1</sup>Das Bundesministerium der Justiz und für Verbraucherschutz wird ermächtigt, zur Vereinfachung und Vereinheitlichung des Verfahrens durch Rechtsverordnung
<sup>2)</sup>mit Zustimmung des BundesratesFormulare für die Erklärung einzuführen.<sup>2</sup>die Formulare enthalten nach § 120a Absatz 2 Satz 4 erforderliche Belehrung.<br>(4)Soweit Formulare für die Erklärung eingeführt sind, muss sich die Partei ihrer bedienen.</br>
<sup>1)</sup>Zeichensetzung amtlich.<br>
<sup>2)</sup>Siehe die Prozesskostenhilfeformularverordnung - PKHFV v. 6.1.2014 (BGB1. I S. 34).</br>
= § 118 Bewilligungsverfahren. =
::Text folgt noch.
= § 119 Bewilligung. =
= § 120<sup>1</sup> Festsetzung von Zahlungen.=
= § 120a<sup>1</sup> Änderung der Bewilligung.=
= § 121 Beiordnung eines Rechtsanwalts.=
= § 122 Wirkung der Prozesskostenhilfe.=
= § 123 Kostenerstattung. =
Die Bewilligung der Prozesskostenhilfe hat auf die Verpflichtung, die dem Gegner entstandenen Kosten zur erstatten, keinen Einfluß.
= § 124 Aufhebung der Bewilligung.=
= § 125 Einziehung der Kosten. =
(1) Die Gerichtskosten und die Gerichtsvollzieherkosten können von dem Gegner erst eingezogen werden, wenn er rechtskräftig in die Prozesskosten verurteilt ist. (2) Die Gerichtskosten, vo deren Zahlung der Gegner einstweilen befreit ist, sind von ihm einzuziehen, soweit er rechtskräftig in die Prozesskosten verurteilt oder der Rechtsstreit ohne Urteil über die Kosten beendet ist.
= § 126 Beitreibung der Rechtsanwalskosten.=
= § 127 Entscheidungen.=
= § 140 Beanstanstandung von Prozessleitung oder Fragen. =
Wird eine auf die Sachleitung bezügliche Anordnung des Vorsitzenden oder eine von dem Vorsitzenden oder einem Gerichtsmitglied gestellte Frage von einer bei der Verhandlung beteiligten Person als unzulässig beanstandet, so entscheidet das Gericht
= § 141 Anordnung des persönlichen Erscheinens. =
(1) <sup>1</sup>Das Gericht soll das persönliche Erscheinen beider Parteien anordnen, wenn dies zur Aufklärung des Sachverhalts geboten erscheint. <sup>2</sup>Ist einer Partei wegen großer Entfernung oder aus sonstigem wichtigen Grund die persönliche Wahrnehmung des Termins nicht zuzumuten, so sieht das Gericht von der Anordnung ihres Erscheinens ab. (2)<sup>1</sup>Wird das Erscheinen angeordnet, so ist die Partei von Amts wegen zu laden. <sup>2</sup>Die Ladung ist der Partei selbst mitzuteilen, auch wenn sie einen Prozessbevollmächtigte bestellt hat; der Zustellung bedarf die Ladung nicht.(3)<sup>1</sup>Bleibt die Partei im Termin aus, so kann gegen sie Ordnungsgeld wie gegen einen im Vernehmungstermin nicht erschienen Zeugen festgesetzt werden. <sup>2</sup>Dies gilt nicht, wenn die Partei zur Verhandlung einen Vertreter entsendet, der zur Aufklärung des Tatbestandes in der Lage und zur Abgabe der gebotenen Erklärungen, insbesondere zu einem Vergleichsabschluss ermächtigt ist. <sup>3</sup>Die Partei ist auf die Folgen ihres Ausbleibens in der Ladung hinzuweisen
= § 184 Zustellungsbevollmächtigter; Zustellung durch Aufgabe zur Post. =
::Text folgt noch!
= § 185 Öffentliche Zustellung. =
Die Zustellung kann durch öffentliche Bekanntmachung (öffentliche Zustellung) erfolgen, wenn <br>1. der Aufenthaltsort einer Person unbekannt und eine Zustellung an einen Vertreter oder Zustellungsbevollmächtigten nicht möglich ist,</br> 2. bei juristischen Personen, die zur Anmeldung einer inländischen Geschäftsanschrift zum Handelsregister verpflichtet sind, eine Zustellung weder unter der eingetragenen Anschrift noch unter einer im Handelsregister eingetragenen Anschrift einer für Zustellungen empfangsberichtigten Person oder einer hohen Ermittlungen bekannten anderen inländischen Anschrift möglich ist. <br>3. eine Zustellung im Ausland nicht möglich ist oder keinen Erfolg verspricht oder </br>4. die Zustellung nicht erfolgen kann, weil der Ort der Zustellung die Wohnung einer Person ist, die nach den §§ 18 bis 20 des Gerichtsverfassungsgesetzes <sup>2)</sup> der Gerichtsbarkeit nicht unterliegt.
= § 186 Bewilligung und Ausführung der öffentlichen Zustellung. =
(1)<sup>1</sup>Über die Bewilligung der öffentlichen Zustellung entscheidet das Prozessgericht. <sup>2</sup> Die Entscheidung kann ohne mündliche Verhandlung ergehen.<br>(2)<sup>1</sup> Die öffentlichen Zustellung erfolgt durch Aushang einer Benachrichtigung an der Gerichtstafel oder durch Einstellung in ein elektronisches Informationssystem, das im Gericht öffentlich zugänglich ist <sup>2</sup> Die Benachrichtigung kann zusätzlich in einem von dem Gericht für Bekanntmachungen bestimmten elektronischen Informations- und Kommunikationssystem veröffentlicht werden. <sup>3</sup> Die Benachrichtigung muss erkennen lassen<br>1.die Person für die zugestellt wird.</br>3. das Datum, das Aktenzeichen des Schriftstücks und die Bezeichnung des Prozessgegenstandes sowie <br>4. die Stelle, wo das Schriftstück eingesehen werden kann.</br><sup>4</sup>Die Benachrichtigung muss den Hinweis enthalten, dass ein Schriftstück öffentlich zugestellt wird und Fristen in Gang gesetzt werden können, nach deren Ablauf Rechtsverluste drohen können. <sup>5</sup> Bei der Zustellung einer Ladung muss die Benachrichtigung den Hinweis enthalten, dass das Schrifstück eine Ladung zu einem Termin enthält, dessen Versäumung Rechtsnachteile zur Folgen haben kann.<br>(3)In den Akten ist zu vermerken, wann die Benachrichtigung ausgehängt und wann sie abgenommen wurde.
= § 307 Anerkenntnis. =
<sup>1</sup>Erkennt eine Partei den gegen sie geltend gemachten Anspruch ganz oder zum Teil an, so ist sie dem Anerkenntnis gemäß zu verurteilen.<sup>2</sup>Einer mündlichen Verhandlung bedarf es insoweit nicht.
= § 309 Erkennende Richter. =
Das Urteil kann nur von denjenigen Richtern gefällt werden, welche der dem Urteil zugrunde liegenden Verhandlungen beigewohnt haben.
= § 589 (ZPO) Zulässigkeitsprüfung =
= § 590 (ZPO) Neue Verhandlung =
= § 591 (ZPO) Rechtsmittel =
:'''Buch 5. Urkunden- und Wechselprozess'''
= § 592 (ZPO) Zulässigkeit. =
1 Ein Anspruch, welcher die Zahlung einer bestimmten Geldsumme oder die Leistung einer bestimmten Menge anderer vertretbarer Sachen oder Wertpapiere zum Gegenstand hat, kann im Urkundenprozess geltend gemacht werden, wenn die sämtlichen zur Begründung des Anspruchs erfolgreichen Tatsachen durch Urkunden bewiesen werden können. 2 Als ein Anspruch, welcher die Zahlung einer Geldsumme zum Gegenstand hat, gilt auch der Anspruch aus einer Hypothek, einer Grundschuld, einer Rentenschuld oder einer Schiffshypothek. '''(Quellinfo = Buch "ZPO" S. 155 ff.)'''
= § 593 (ZPO) Klageinhalt: Urkunden. =
(1) Die Klage muss die Erklärung enthalten, dass im Urkundenprozess geklagt werde. (2) 1 Die Urkunden müssen in Abschrift der Klage oder einem vorbereitenden Schriftsatz beigefügt werden. 2 Im letzteren Fall muss zwischen der Zustellung des Schriftsätze und dem Termin zur mündlichen Verhandlung ein der Einlassungfrist gleicher Zeitraum liegen. '''(Quellinfo = Buch "ZPO" S. 155 ff.)'''
= § 594 (ZPO) (weggefallen) =
'''(Quellinfo = Buch "ZPO" S. 156 ff.)'''
= § 595 (ZPO) Keine Widerklage; Beweismittel. =
(1) Widerklangen sind nicht statthaft. (2) Als Beweismittel sind bezüglich der Echtheit oder Unechtheit einer Urkunde sowie bezüglich anderer als der im § 592 erwähnten Tatsachen nur Urkunden und Antrag auf Parteivernehmung zulässig. (3) Der Urkundenbeweis kann nur durch Vorlegung der Urkunden angetreten werdenden.
'''(Quellinfo = Buch "ZPO" S. 156 ff.)'''
= § 596 (ZPO) Abstehen vom Urkundenprozess. =
Der Kläger kann, ohne dass es der Einwilligiung des Beklagten bedarf, bis zum Schluss der mündlichen Verhandlung von dem Urkundenprozess in der Weise abstehen, dass der Rechtsstreit im ordentlichen Verfahren anhängig bleibt. '''(Quellinfo = Buch "ZPO" S. 156 ff.)'''
= § 597 (ZPO) Klageabweisung =
(1) Insoweit der in der Klage geltend gemachte Anspruch an sich oder infolge einer Einrede des Beklagten als unbegründet sich darstellt, ist der Kläger mit dem Anspruch abzuweisen. (2) Ist der Urkundenprozess unstatthaft, ist insbesondere ein dem Kläger obliegender Beweis nicht mit den im Urkundenprozess zulässigen Beweismitteln angetreten oder mit solchen Beweismitteln nicht vollständig geführt, so wird die Klage als in der gewählten Prozessart unstatthaft abgewiesen, selbst wenn in dem Termin zur mündlichen Verhandlung der Beklagte nicht erschienen ist oder der Klage nur auf Grund von Einwendungen widersprochen hat, die rechtlich unbegründet oder im Urkundenprozess unstatthaft sind. '''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
= § 598 (ZPO) Zurückweisung von Einwendungen =
Einwendungen des Beklagten sind, wenn der dem Beklagten obliegende Beweis nicht mit den im Urkundenprozess zulässigen Beweismitteln angetreten oder mit solchen Beweismitteln nicht vollständig geführt ist, als im Urkundenprozess unstatthaft zurückzuweisen. '''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
= § 599 (ZPO) Vorbehaltsurteil =
(2) Dem Beklagten, welcher dem geltend gemachten Anspruch widersprochen hat, ist in allen Fällen, in denen er verurteilt wird, die Ausführung seiner Rechte vorzubehalten. (2) Enthält das Urteil keinen Vorbehalt so kann die Ergnuzugn des Urteils nach der Vorschrift des § 321 beantragt werden. (3) Das Urteil, das unter Vorbehalt der Rechte ergeht, ist für die Rechtsmittel und die Zwangsvollstreckung als Endurteil anzusehen. '''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
= § 600 (ZPO) Nachverfahren. =
(1) Wird dem Beklagten die Ausführung seiner Rechte vorbehalten, so bleibt der Rechtsstreit im ordentlichen Verfahren anhängig. (2) Soweit sich in diesem Verfahren ergibt, dass der Anspruch des Klägers unbegründet war, gelten die Vorschriften des § 302 Abs. 4 Satz 2 bis 4. (3) Erscheint in diesem Verfahren eine Partei nicht, so sind die Vorschriften über das Versäumnisurteil entsprechend anzuwenden. '''(Quellinfo = Buch "ZPO" S. 156 ff.)'''
= § 601 (ZPO) (weggefallen) =
'''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
= § 602 (ZPO) Wechselprozess. =
Werden im Urkundenprozess Ansprüche aus Wechseln im Sinne des Wechselgesetztes geltend gemacht (Wechselprozess), so sind die nachfolgenden besonderen Vorschriften anzuwenden. '''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
::::: '''Buch 6. 1) (aufgehoben)'''
::::: '''§§ 606-687 1) (ZPO) (aufgehoben)'''
::::: '''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
= § 603 (ZPO) Gerichtsstand. =
(1) Wechselklagen können sowohl bei dem Gericht des Zahlungsortes als bei dem Gericht angestellt werden, bei dem der Beklagte seinen allgemeinen Gerichtstand hat. (2) Wenn mehrere Wechselverpflichtete gemeinschaftlich verklagt werden, so ist außer dem Gericht des Zahlungsortes das Gericht zuständig, bei dem einer der Beklagten seinen allgemeinen Gerichtstand hat. '''(Quellinfo = Buch "ZPO" S. 17 ff.)'''
= § 604 (ZPO) Klageinhalt: Ladungsfrist. =
(1) Die Klage muss die Erklärung enthalten, dass im Wechselprozess geklagt werde. (2) <sup>1</sup> Die Ladungsfrist beträgt mindestens 24 Stunden , wenn die Ladung an dem Ort, der Sitz des Prozessgerichts ist, zugestellt wird. <sup>2</sup> In Anwaltsprozessen beträgt sie mindestens drei Tage, wenn die Ladung an einem anderen Ort zugestellt wird, der im Bezirk des Prozessgerichts liegt oder von dem ein Teil zu dessen Bezirk gehört. (3) In den höheren Instanzen beträgt die Ladungsfrist mindestens 24 Stunden, wenn die Zustellung der Berufungs- oder Revisionsschrift oder der Ladung an dem Ort erfolgt, der Sitz des höheren Gerichts ist; mindestens drei Tage, wenn die Zustellung an einem anderen Ort erfolgt, der ganz oder zum Teil in dem Landgerichtsbezirk liegt, in dem das höhere Gericht seinen Sitz hat, mindestens eine Woche, wenn die Zustellung sonst im Inland erfolgt. '''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
= § 605 (ZPO) Beweisvorschriften. =
(1) Soweit es zur Erhaltung des wechselmäßigen Anspruch der rechtzeitigen Protesterhebung nicht bedarf, ist als Beweismittel bezüglich der Verlegung des Wechsels der Antrag auf Parteivernehmung zulässig. (2) Zur Berücksichtigung der Nebenforderung genügt, dass sie glaubhaft gemacht ist. '''(Quellinfo = Buch "ZPO" S. 158 ff.)'''
= § 605a (ZPO) Scheckprozess =
Werden im Urkundenprozess Ansprüche aus Schecks im Sinne des Scheckgesetzes geltend gemacht (Scheckprozess), so sind die §§ 602 bis 605 entsprechend anzuwenden. '''(Quellinfo = Buch "ZPO" S. 158 ff.)'''
::::: '''Buch 6.''' 1) (aufgehoben)
= §§ 606-687 1) (ZPO) (aufgehoben) =
::::: '''Buch 7. Mahnverfahren'''
= § 688 (ZPO) Zulässigkeit. =
(1) Wegen eines Anspruchs, der die Zahlung einer bestimmten Geldsumme in Euro zum Gegenstand hat, ist auf Antrag des Antragstellers ein Mahnbescheid zu erlassen. (2) Das Mahnverfahren findet nicht statt: <sup>1.</sup> für Ansprüche eines Unternehmers aus einem Vertrag gemäß den §§ 491 bis 508 des Bürgerlichen Gesetzbuchs, wenn der gemäß § 492 Abs. 2 des Gesetzbuchs anzugebende effektive Jahreszins den bei Vertragsschluss geltenden '''Basiszinssatz nach § 247''' des Bürgerlichen Gesetzbuchs um mehr als zwölf Prozentpunkt übersteigt; 2. wenn die Geltendmachung des Anspruch von einer noch nicht erbrachten Gegenleistung abhängig ist; 3. wenn die Zustellung des Mahnbescheids durch öffentliche Bekanntmachung erfolgen müsste. (3) Müsste der Mahnbescheid im Ausland zugestellt werden, findet das Mahnverfahren nur statt, soweit das Anerkennungs- und Vollstreckungsausführungsgesetz vom 19. Februar 2001 (BGB1. I S. 288) dies vorsieht. (4) 1 Die Vorschriften der Verordnung (EG) Nr. 1896/2006 des Europäischen Parlaments und des Rates vom 12. Dezember 2006 zur Einführung eines Europäischen Mahnverfahrens bleiben unberührt. 2 Für die Durchführung gelten die §§1087 bis 1096 '''(Quellinfo = Buch "ZPO" S. 157 ff.)'''
: '''§ 247 (BGB) 1)2) Basiszinssatz.'''(1) 1 Der Basiszinssatz beträgt 3,62 Prozent3). 2 Er verändert sich zum 1.Januar und 1. Juli eines jeden Jahres um die Prozentpunkte, um welche die Bezugsgröße seit der letzten Veränderung des Basiszinssatzes gestiegen oder gefallen ist. 3 Bezugsgröße ist der Zinssatz für die jüngste Hauptrefinanzierungsoperation der Europäischen Zentralbank vor dem ersten Kalendertag des betreffenden Halbjahrs. '''(Quellinfo = Buch "BGB" S. 47 ff.)'''
: 1) Amtl. Anm.L Diese Vorschrift dient der Umsetzung von Artikel 3 der Richtlinie 2000/35/EG des Europäischen Parlaments und des Rates vom 29. Juni 2000 zur Bekämpfung von Zahlungsverzug im Geschäftsverkehr (AB1. EG Nr. L 200 S. 35). Punkte 1-2)='''(Quellinfo = Buch "BGB S. 47 ff.)'''
: 2) Beachte hierzu Übergangsvorschrift in Art. 229 § 7 EGBGB (Nr. 2).
: - ab 1.1.2002 '''2,57%''' (Bek. v. 28.12.2001, BAnz. 2002 Nr. 3 S. 98);
: - ab 1.7.2002 '''2,47%''' (Bek. v. 25.06.2002, BAnz. Nr. 118 S. 14538);
: - ab 1.1.2003 '''1,97%''' (Bek. v. 30.12.2002, BAnz. 2003 Nr.2. S. 76);
: - ab 1.7.2003 '''1,22%''' (Bek. v. 24.06.2003, BAnz. Nr. 117 S. 13744);
: - ab 1.1.2004 '''1,14%''' (Bek. v. 30.12.2003, BAnz. Nr. 2 S. 69);
: - ab 1.7.2004 '''1,13%''' (Bek. v. 29.06.2004, BAnz. Nr. 122 S. 14246);
: - ab 1.1.2005 '''1,21%''' (Bek. v. 30.12.2004, BAnz. Nr. 1 S. 6);
: - ab 1.7.2005 '''1,17%''' (Bek. v. 28.06.2005, BAnz. Nr. 122 S. 10041);
: - ab 1.1.2006 '''1,37%''' (Bek. v. 29.12.2005, BAnz. Nr. 1 S. 2);
: - ab 1.7.2006 '''1,95%''' (Bek. v. 27.06.2006, BAnz. Nr. 191 S. 4754);
: - ab 1.1.2007 '''2,70%''' (Bek. v. 28.12.2006, BAnz. Nr. 245 S. 7463);
: - ab 1.7.2007 '''3,19%'''(Bek. v. 28.06.2007, BAnz. Nr. 117 S. 6530);
: - ab 1.1.2008 '''3,32%''' (Bek. v. 28.12.2007, BAnz. Nr. 242 S. 8415);
: - ab 1.7.2008 '''3,19%''' (Bek. v. 24.06.2008, BAnz. 94 Nr. 1 S. 2232);
: - ab 1.1.2009 '''1,62%''' (Bek. v. 30.12.2008, BAnz. 2009 Nr. 1 S. 6);
: - ab 1.7.2009 '''0,12%''' (Bek. v. 30.06.2009, BAnz. Nr. 95 S. 2302);
: - ab 1.1.2010 '''0,12%''' (Bek. v. 29.12.2009, BAnz. Nr. 198 S. 4582);
: - ab 1.7.2010 '''0,12%''' (Bek. v. 29.06.2010, BAnz.Nr. 96 S. 2264);
: - ab 1.1.2011 '''0,12%''' (Bek. v. 28.12.2010, BAnz. Nr. 199 S. 4388);
: - ab 1.7.2011 '''0,37%''' (Bek. v. 30.06.2011, BAnz. Nr. 96 S. 2314);
: - ab 1.1.2012 '''0,12%''' (Bek. v. 27.12.2011, BAnz. Nr. 197 S. 4659);
: - ab 1.7.2012 '''0,12%''' (Bek. v. 26.06.2012, BAnz. AT 28.06.2012 B3);
: - ab 1.1.2013 '''-0,13%''' (Bek. v. 28.12.2012, BAnz. AT 31.12.2012 B8);
: - ab 1.7.2013 '''-0,38%''' (Bek. v. 25.06.2013, BAnz. AT 27.06.2013 B4);
: - ab 1.1.2014 '''-0,63%''' (Bek. v. 30.12.2013, BAnz. AT 31.12.2013 B7);
: - ab 1.7.2014 '''-0,73%''' (Bek. v. 24.06.2014, BAnz. AT 26.06.2014 B5);
: - ab 1.1.2015 '''-0,83%''' (Bek. v. 30.12.2014, BAnz. AT 31.12.2014 B12);
: - ab 1.7.2015 '''-0,83%''' (Bek. v. 30.06.2015, BAnz. AT 01.07.2015 B6);
: - ab 1.1.2016 '''-0,83%''' (Bek. v. 29.12.2015, BAnz. AT 30.12.2015 B8);
: - ab 1.7.2016 '''-0,88%''' (Bek. v. 28.06.2016, BAnz. AT 29.06.2016 B4);
: - ab 1.1.2017 '''-0,88%''' (Bek. v. 27.12.2016, BAnz. AT 29.12.2016 B11); '''(Quellinfo der aufgeführten Angaben zu den entsprechenden Basiszinssätzen = Buch "BGB" S. 48 ff.)'''
(2) Die Deutsche Bundesbank gibt den geltenden Basiszinssatz unverzüglich nach den in Absatz 1 Satz 2 genannten Zeitpunkten im Bundesanzeiger bekannt. '''(Quellinfo = Buch "BGB" S. 48 ff.)'''
= § 689 (ZPO) Zuständigkeit; maschinelle Bearbeitung. =
(1) 1 Das Mahnverfahren wird von den Amtsgerichten durchgeführt. 2) 2 Eine maschinelle Bearbeitung ist zulässig. 3 Bei dieser Bearbeitung sollen Eingänge spätestens an dem Arbeitstag erledigt sein, der dem Tag des Eingangs folgt. 3 Die Akten können elektronisch geführt werden (§298 a9)
(2) 1 Ausschließlich zuständig ist das Amtsgericht, bei dem der Antragsteller seinen allgemeinen Gerichtsstand hat. 2 Hat der Antragsteller im Inland keinen allgemeinen Gerichtsstand, sonst das Amtsgericht Wedding in Berlin ausschlie´loch zuständig. 3. Sätze 1 und 2 gelten auch, soweit in anderen Vorschriften eine andere ausschließliche Zuständigkeit bestimmt ist.
(3) 1) 1 Die Landesregierungen wären ermächtigt, durch Rechtsverordnung Mahnverfahren einem Amtsgericht für die Bezirke mehrerer Amtsgerichte zuzuweisen, wenn dies ihrer schnelleren und rationelleren Erledigung dient. 2 Die Zuweisung kann auf Mahnverfahren beschränkt werden, die maschinell bearbeitet werden. 3 Die Landesregierungen können die Ermächtigung durch Rechtsverordnung auf die Landesjustizverwaltungen übertragen. 4 Mehrere Länder können die Zuständigkeit eines Amtsgerichts über die Landesgrenzen hinaus vereinbaren. '''(Quellinfo = Buch "ZPO" S. 158 ff.)'''
= § 690 (ZPO) Mahnantrag. =
(1) Der Antrag muss auf den Erlass eines Mahnbescheids gerichtet sein und enthalten: 1. die Bezeichnung der Parteien, ihrer gesetzlichen Vertreter und der Prozessbevollmächtigten; 2. die Bezeichnung des Gerichts, bei dem der Antrag gestellt wird; 3. die Bezeichnung des Anspruchs unter bestimmter Angabe der verlangten Leistung; Haupt - und Nebenforderungen sind gesondert und einzeln zu bezeichnen. Ansprüche aus Verträgen gemäß den '''§§ 491 bis 508 des Bürgerlichen Gesetzbuchs'''; auch unter Angabe des Datums des Vertragsabschlusses und des gemäß '''§ 492 Abs. 2 des Bürgerlichen Gesetzbuchs''' anzugebenden effektiven Jahreszinses; 4. die Erklärung, dass der Anspruch nicht von einer Gegenleistung abhängt oder dass die Gegenleistung erbracht ist; 5. die Bezeichnung des Gerichts, das für ein streitiges Verfahren zuständig ist. (2) Der Antrag bedarf der handschriftlichen Unterzeichnung. (3) 1 Der Antrag kann in einer nur maschinell lesbaren Form vermittelt werden, wenn diese dem Gericht für seine maschinelle Bearbeitung geeignet erscheint. 2 Wird der Antrag von einem Rechtsanwalt oder einer registrierten Person nach § 10 Abs. 1 Satz 1 Nr. 1 des Rechtsdienstleistungegesetztes gestellt, ist nur diese Form der Antragstellung zulässig. '''[Satz 3 ab 1. 1. 2018:]''' 3 Der Antrag kann unter Nutzung des elektronischen Identitätsnachweises nach § 18 des Personalausweisgesetztes oder § 78 Absatz 5 des Aufenthaltsgesetztes gestellt werden. 3 '''[Satz 3 bis 31. 12. 2017, Satz 4 ab 1. 1. 2018 :] Der handschriftlichen Unterzeichnung bedarf es nicht, wenn in anderer Weise gewährleistet ist, dass der Antrag nicht ohne den Willen des Antragstellers übermittelt wird. (Quellinfo = Buch "ZPO" S. 158 ff.)'''
:Kapitel 2 Besondere Vorschriften für Verbraucherdarlehensverträge (BGB)
: '''§ 491 1) 2) Verbraucherdarlehensvertrag.'''
: (1) 1 Die Vorschriften dieses Kapitels gelten für Verbraucherdarlehensverträge, soweit nichts anderes bestimmt ist. 2 Verbraucherdarlehensverträge sind Allgemein- Verbraucherdarlehensverträge und Immobiliar-Verbraucherdarlehensverträge. (2) 1 Allgemein- Verbraucherdarlehensverträge sind entgeltliche Darlehensverträge zwischen einem Unternehmer als Darlehensgeber und einem Verbraucher als Darlehensnehmer. 2 Keine Allgemein Verbraucherdarlehensverträge sind Verträge, 1 bei denen der Nettodarlehensbetrag (Artikel 247 § 3 Abs 2 des Einführungsgesetzes zum Bürgerlichen Gesetzbuche 1) weniger als 200 Euro beträgt. 2 ei denen sich die Haftung des Darlehensnehmers auf eine dem Darlehensgeber zum Pfand übergebene Sache Beschränkt, 3 .bei denen der Darlehensnehmer das Darlehen binnen drei Monaten zurückzuzahlen hat und nur geringe Kosten vereinbart sind. 4. die von Arbeitgebern mit ihren Arbeitnehmers als Nebenleistung zum Arbeitsvertrag zu einem niedrigeren als dem marktüblichen effektiven Jahreszins (§ 6 der Preisangabenverordnung) abgeschlossen werden und anderen Personen nicht angeboten werden. 5. die nur mit einem begrenzten Personenkreis auf Grund von Rechtsvorschriften in öffentlichem Interesse abgeschlossen werden, wenn im Vertrag für den Darlehensnehmer günstigere als marktübliche Bedingungen und höchstens der marktübliche Sollzinssatz vereinbart sind. 6. bei denen es sich um Immobil- Verbraucherdarlehensverträge gemäß Absatz 3 handelt.
: (3) 1 Immobiliar-Verbraucherdarlehendverträge sind entgeltliche Darlehensverträge wischen einem Unternehmer als Darlehensgeber und einem Verbraucher als Darlehensnehmer, die 1. durch ein Grundpfandrecht oder eine Reallast gesichert sind oder 2. für den Erwerb oder die Erhaltung des Eigentumsrechts an Grundstücken, an bestehenden oder zu errichtenden Gebäuden oder für den Erwerb oder die Erhaltung von grundstücksgleichen Rechten bestimmt sind. 2 Keine Immobiliar-Berbraucherdarlehensverträge sind Verträge gemäß Absatz 2 Satz 2 Nummer 4. 3 Auf Immobiliar-Berbruacherdarlehensverträge gemäß Absatz 2 Satz 2 Nummer 4 ist nur '''§ 491 a Absatz 4''' anwendbar. (4) '''§ 358 Abs. 2''' und 4 sowie die '''§§ 491 a bis 495''' und '''505a bis 505 d''' sind nicht auf Darlehensverträge anzuwenden, die in ein nach den Vorschriften der Zivilprozessordnung errichtetes gerichtliches Protokoll aufgenommen oder durch einen gerichtlichen Beschluss über das Zustandekommen und den Inhalt eines zweichen den Parteien geschlossenen Vergleichs festgestellt sind, wenn in das Protokoll oder den Beschluss der Sollzinssatz, die bei Abschluss des Vertrags in Rechnung gestellten Kosten des Darlehens sowie die Voraussetzungen aufgenommen worden sind unter denen der Sollzinssatz oder die Kosten angepasst werden können. '''(Quellinfo = Buch "BGB" S. 117 ff.)'''
= § 691 (ZPO) Zurückweisung des Mahnantrags. =
(1) 1 Der Antrag wird zurückgewiesen: 1. wenn er den Vorschriften der §§ 688, 689,690, 703 c Abs. 2 nicht entspricht; 2. wenn der Mahnbescheid nur wegen eines Teiles des Anspruchs nicht erlassen werden kann. 2 Vor der Zurückweisung ist der Antragsteller zu hören. (2) Sollte durch die Zustellung des Mahnbescheids eine Frist gewahrt werden oder die Verjährung neu beginnen oder nach § 204 des Bürgerlichen Gesetzbuchs gehemmt werden, so tritt die Wirkung mit der Einreichung oder Anbringung des Antrags auf Erlass des Mahnbescheids ein,wenn innerhalb eines Monats seit der Zustellung der Zurückweisung des Antrags Klage eingereicht und diese demnächst zugestellt wird. (3) 1 Gegen die Zurückweisung findet die sofortige Beschwerde statt, wenn der Antrag in einer nur maschinell lesbaren Form übermittelt und mit der Begründung zurückgewiesen worden ist, dass diese Form dem Gericht für seine maschinelle Bearbeitung nicht geeignet erscheine. 2 Im Übrigen sind Entscheidungen nach Absatz 1 unanfechtbar. '''(Quellinfo = Buch "ZPO" S. 159 ff.)'''
= § 692 (ZPO) Mahnbescheid. =
(1) Der Mahnbescheid enthält: 1. die in § 690 Abs. 1 Nr . 1 bis 5 bezeichneten Erfordernisse des Antrags; 2. den Hinweis, dass das Gericht nicht geprüft hat. ob dem Antragsteller der geltend gemachte Anspruch zusteht; 3. die Aufforderung innerhalb von zwei Wochen seit der Zustellung des Mahnbescheids, soweit der geltend gemachte Anspruch als begründet angesehen wird, die behauptete Schuld nebst den geforderten Zinsen und der dem Betrag nach bezeichneten Kosten zu begleichen oder dem Gericht mitzuteilen, ob und in welchem Umfang dem geltend gemachten Anspruch widersprochen wird. 4 den Hinweis, dass ein dem Mahnbescheid entsprechender Vollstreckungsbescheid ergehen kann, aus dem der Antragsteller die Zwangsvollstreckung betreiben kann falls der Antragsgegner nicht bis zum Fristablauf Widerspruch mit jenem Formular der beigefügten Art erhoben hat; 5. für den Fall, dass Formulare eingeführt sind, den Hinweis, dass der Wirderspruch mit jenem Formular der beigefügten Art erhoben werden soll, das auch bei jedem Amtsgericht erhältlich ist und ausgefüllt werden kann; 6. für den Fall des Widerspruchs, die Ankündigung, an welches Gericht die Sache abgegeben wird, mit dem Hinweis, dass diesem Gericht die Prüfung seiner Zuständigkeit vorbehalten bleibt. (2) An Stelle einer handschriftlichen Unterzeichnung genügt ein entsprechender Stempelabdruck oder eine elektronische Signatur. '''(Quellinfo = Buch "ZPO" S. 158 ff.)'''
= § 693 (ZPO) Zustellung des Mahnbescheids. =
(1) Der Mahnbescheid wird dem Antragsgegner zugestellt. (2) Die Geschäftsstelle setzt den Antragsteller on der Zustellung des Mahnbescheids in Kenntnis. '''(Quellinfo = Buch "ZPO" S. 160 ff.)'''
= § 694 (ZPO) Widerspruch gegen den Mahnbescheid. =
(1) Der Antragsgegner kann gegen den Anspruch oder einen Teil des Anspruchs bei dem Gericht, das den Mahnbescheid erlassen hat, schriftlich Widerspruch erheben, solange der Vollstreckungsbescheid nicht verfügt ist. (2) 1 Ein verspäteter Widerspruch wird als Einspruch behandelt. 2 Dies ist dem Antragsgegner, den den Widerspruch erhoben hat, mitzuteilen. '''(Quellinfo = Buch "ZPO" S. 160 ff.)'''
= § 695 (ZPO) Mitteilung des Widerspruchs; Abschriften. =
1 Das Gericht hat den Antragsteller von dem Widerspruch und dem Zeitpunkt seiner Erhebung in Kenntnis zu setzen. 2 Wird das Mahnverfahren nicht maschinell bearbeitet, so soll der Antragsgegner die erforderliche Zahl von Abschriften mit dem Widerspruch einreichen. '''(Quellinfo = Buch "ZPO" S. 160 ff.)'''
= § 696 (ZPO) Verfahren nach Widerspruch. =
(1) 1 Wird rechtzeitig Widerspruch erhoben und beantragt eine Partei die Durchführung des streitigen Verfahrens, so gibt das Gericht, das den Mahnbescheid erlasen hat, den Rechtsstreit von Amts wegen an das Gericht ab, das in dem Mahnbescheid gemäß § 692 Abs. 1 Nr 1 bezeichnet worden ist, wenn die Parteien übereinstimmend die Abgabe an ein anderes Gericht verlangen, an diese. 2 Der Antrag kann in den Antrag auf Erlass des Mahnbescheids aufgenommen werden. 3 Die Abgabe ist den Parteien mitzuteilen; sie ist nicht anfechtbar. 4 Mit Eingang der Akten bei dem Gericht, an das er abgegeben wird, gilt der Rechtstreit als dort anhängig. 5 § 281 Ab. 2 Satz 1 gilt entsprechend. (2) 1 Ist das Mahnverfahren maschinell bearbeitet worden, so tritt, sofern die Akte nicht elektronisch übermittelt wird, an die Stelle der Akten ein maschinell erstellter Aktenausdruck. 2 Für diesen gelten die Vorschriften über die Beweiskraft öffentlicher Urkunden entsprechend. 3 § 298 findet keine Anwendung. (3) Die Streitsache gilt als mit Zustellung des Mahnbescheid rechtshängig geworden, wenn sie alsbald nach de Erhebung des Widerspruch abgegeben wird. (4) 1 Der Antrag auf Durchführung des streitigen Verfahrens kann bis zum Beginn der mündlichen Verhandlung des Antragsgegners zur Hauptsache zurückgenommen werden. 2 Die Zurücknahme kann vor der Geschäftsstelle nicht rechtshängig geworden anzusehen. (5) Das Gericht, an das der Rechtsstreit abgegeben ist, ist hierzu in seiner Zuständigkeit nicht gebunden. '''(Quellinfo = Buch "ZPO" S. 161 ff.)'''
= § 697 (ZPO) Einleitung des Streitverfahrens. =
(1) 1 Die Geschäftsstelle des Gerichts an das die Streitsache abgegeben wird, hat dem Antragsteller unverzüglich aufzugeben, seinem Anspruch binnen zwei Wochen in einer der Klageschrift entsprechende Form zu dd. 2 § 270 Satz 2 gilt entsprechend. (2) 1 Bei Eingang der Anspruchsbegründung ist wie nach Eingang einer Klage weiter zu verfahren. 2 Zur schriftlichen Klageerwiderungen Verfahren. nach § 276 kann auch eine mit der Zustellung der Anspruchsbegründung beginnende Frist gesetzt werden. (3) 1 Geht die Anspruchsbegründung nicht rechtzeitig ein,so wird bis zu ihrem Eingang Termin zur mündlichen mündlichen Verhandlung nur auf Antrag des Antragsgegner bestimmt . 2 Mit der Terminbestimmung setzt der Vorsitzende dem Antragsteller Eine Frist zur Begründung des Anspruchs; § 296 Abs. 1, 4 gilt entsprechend. (4) 1 Der Antragsgegner kann den Widerspruch bis zum Beginn seiner mündlichen Verhandlung zur Hauptsache zurücknehmen, jedoch nicht nach erlass eines Versäumnisurteil s gegen ihn. 2 Die Zurücknahme kann zu Protokoll der Geschäftsstelle erklärt werden. (5) 1 Zur Herstellung eines Urteils in abgekürzter Form nach § 313 b Ansatz 2, § 317 Absatz 6 kann der Mahnbecheid an Stelle der Klageschrift benutzt werden . 2 Ist das Mahnverfahren maschinell bearbeitet worden, so tritt an die Stelle der Klageschrift der maschinell erstellte Aktenausdruck. '''(Quellinfo = Buch "ZPO" S. 130 ff.)'''
= § 698 (ZPO) Abgabe des Verfahrens am selben Gericht. =
Die Vorschriften über die Abgabe des Verfahrens gelten sinngemäß, wenn Mahnverfahren und streitiges Verfahren bei demselben Gericht durchgeführt werden. '''(Quellinfo = Buch "ZPO" S. 130 ff.)'''
= § 699 (ZPO) Vollstreckungsbescheid. =
(1) 1 Auf der Grundlage des Mahnbescheids erlässt das Gericht auf Antrag einen Vollstreckungsbescheid, wenn der Antragsgegner nicht rechtzeitig Widerspruch erhoben hat. 2 Der Antrag kann nicht vor Ablauf der Widerspruchsfrist gestellt werden; er hat die Erklärung zu enthalten, ob und welche Zahlungen auf den Bescheid geleistet worden sind; '''[bis 31. 12. 2017:''' § 690 Abs. 3 Satz 1 und 3''']''' '''[ab 1. 1. 2018:''' § 690 Abs. 3''']''' gilt entsprechend 3 Ist der Rechtsstreit bereits an ein anderes Gericht abgegeben, so erlässt dieses den Vollstreckungsbescheid. (2) Soweit das Mahnverfahren nicht maschinell bearbeitet wird kann der Vollstreckungsbescheid auf den Mahnbescheid gesetzt werden. (3) 1 In den Vollstreckungsbescheid sind die bisher entstandenen Kosten des Verfahrens aufzunehmen. 2 Der Antragsteller braucht die Kosten nur zu berechnen,, wenn das Mahnverfahren nicht maschinell bearbeitet wird; im Übrigen genügen die zur maschinellen Berechnung erforderlichen Angaben. (4) 1 Der Vollstreckungsbescheid wird dem Antragsgegner von Amts wegen zugestellt, wenn nicht der Antragsteller die Übermittlung an sich zur Zustellung im Parteibetrieb beantragt hat. 2 In diesen Fällen wird der Vollstreckungsbescheid dem Antragsteller zur Zustellung übermittelt; die Geschäftsstelle des Gerichts vermittelt diese Zustellung nicht. 3 Bewilligt das mit dem Mahnverfahren befasste Gericht die öffentliche Zustellung, so wird die Benachrichtigung nach § 186 Abs 2 Satz 2 und an die Gerichtstagel des Gerichts angeheftet oder in das Informationssystem des Gerichts eingestellt, das in dem Mahnbescheid gemäß § 692 Abs 1 Nr. 1 bezeichnet worden ist. (5) Die Belehrung gemäß § 232 ist dem Antragsgegner zusammen mit der Zustellung des Vollsreckungsbescheids schriftlich mitzuteilen. '''(Quellinfo = Buch "ZPO" S. 161 ff.)'''
= § 700 (ZPO) Einspruch gegen den Vollstreckungsbescheid. =
(1) Der Vollstreckungsbescheid steht einem für vorläufig vollstreckbar erklärten Versäumnisurteil gleich. (2) Die Streitsache gilt als mit der Zustellung des Mahnbescheids rechtshängig geworden. (3) 1 Wird Einspruch eingelegt, so gibt das Gericht, das den Vollstreckungsbescheid erlassen hat, den Rechtsstreit von Amts wegen an das Gericht ab, das in dem Mahnbescheid gemäß § 692 Abs. 1 Nr. 1 bezeichnet worden ist, wenn die Parteien übereinstimmend die Abgabe an ein anderes Gericht verlangen, an dieses. 2. §696 Abs. 1 Satz 3 bis 5, Abs2, 5 § 697 Abs. 1, 4, § 698 gelten entsprechend. 3 § 340 Abs. 3 ist nicht anzuwenden. (4) 1 Bei Eingang Teer Anspruchsbegründung ist wie nach Eingang einer Klage weiter zu verfahren wenn der Einspruch nicht als unzulässig verworfen wird. 2 § 276 Abs. 1 Satz 1 3 , Abs. 2 ist nicht anzuwenden. (5) Geht die Anspruchsbegründung innerhalb der von der Geschäftsstelle gesetzten Frist nicht ein und wird der Einspruch auch nicht als unzulässig verworfen, bestimmt der Vorsitzende unverzüglich Termin; § 697 Abs. 3 Satz 2 gilt entsprechend. (6) Der Einspruch darf nach § 345 nur verworfen werden, soweit der Voraussetzungen des § 331 Abs 1,2 erster Halbsatz fr ein Versäumnisurteil vorliegen, wird der Vollstreckungsbescheid aufgeben. '''(Quellinfo = Buch "ZPO" S. 162 ff.)'''
= § 701 (ZPO) Wegfall der Wirkung des Mahnbescheids. =
1 Ist Widerspruch nicht erhoben und beantragt der Antragsteller den Erlass des Vollstreckungsbescheids nicht binnen einer sechsmonatigen Frist, die mit der Zustellung des Mahnbescheids beginnt, so fällt die Wirkung des Mahnbescheids weg. 2 Dasselbe gilt, wenn der Vollstreckungsbescheid rechtzeitig beantragt ist, der Antrag aber zurückgewiesen wird. '''(Quellinfo = Buch "ZPO" S. 163 ff.)'''
= § 702 (ZPO) Form von Anträgen und Erklärungen. =
(1) 1 Im Mahnverfahren können die Anträge und Erklärungen vor dem Urkundsbeamten der Geschäftsstelle abgegeben werden. 2 Soweit Formulare eingeführt sind, werden diese ausgefüllt; der Urkundsbeamte vermerkt unter Angabe des Gerichts und des Datums, dass er den Antrag oder die Erklärung aufgenommen hat. 3 Auch soweit Formulare nicht eingeführt sind, ist für den Antrag auf Erlass eines Mahnbescheids oder eines Vollsstreckungsbescheids bei dem für das Mahnverfahren zuständigen Gericht die Aufnahme eines Protokolls nicht erforderlich. (2) Der Antrag auf Erlass eines Mahnbesheids oder eines Vollstreckungsbescheids wir dem Antragsgegner nicht mitgeteilt. '''(Quellinfo = Buch "ZPO" S. 163 ff.)'''
= § 703 (ZPO) Kein Nachweis der Vollmacht. =
1 Im Mahnverfahren bedarf es des Nachweises einer Vollmacht nicht. 2 Wer als Bevollmächtigter einen Antrag einreicht oder einen Rechtsbehelf einlegt, hat seine ordnungsgemäße Bevollmächtigung zu versichern. '''(Quellinfo = Buch "ZPO" S. 163 ff.)'''
= § 703 a (ZPO) Urkunden-, Wechsel- und Scheckmahnverfahren. =
(1) Ist der Antrag des Antragstellers auf den Erlass eines Urkunden- Wechsel- oder Scheckmahnbescheids gerichtet, so wird der Mahnbescheid als Urkunden-, Wechsel- oder Scheckmahnbescheid bezeichnet. (2) Für das Urkunden-, Wechsel- und Scheckmahnverfahren gelten folgende besondere Vorschriften: 1. die Bezeichnung als Urkunden-, Wechsel- oder Scheckmahnbescheid hat die Wirkung, dass die Streitsache, wenn rechtzeitig Widerspruch erhoben wird, im Urkunden-, Wechsel- oder Scheckprozess anhängig wird, 2. die Urkunden sollen in dem Antrag auf Erlass des Mahnbescheids und in dem Mahnbescheid bezeichnet werden; ist die Sache an das Streitgericht abzugeben, so müssen die Urkunden in Urschrift oder in Abschrift der Anspruchsbegründung beigefügt werden; 3. im Mahnverfahren ist nicht zu prüfen, ob die gewählte Prozessart statthaft ist. 4. beschränkt sich der Widerspruch auf den Antrag, dem Beklagten die Ausführung seiner Rechte vorzubehalten, so ist der Vollstreckungsbescheid unter diesen Vorbehalt zu erlassen. Auf das weitere Verfahren ist die Vorschrift des § 600 entsprechend anzuwenden. '''(Quellinfo = Buch "ZPO" S. 163 ff.)'''
= § 703 b (ZPO) Sonderregelungen für maschinelle Bearbeitung. =
(1) Bei maschineller Bearbeitung werden Beschlüsse, Verfügungen, Ausfertigungen und Vollstreckungsklauseln mit dem Gerichtssiegel versehen; einer Unterschrift bedarf es nicht. (2) Das Bundesministerium der Justiz und für Verbraucherschutz wird ermächtigt, durch Rechtsverordnung mit Zustimmung des Bundesrates den Verfahrensablauf zu regeln, soweit dies für eine einheitliche maschinelle Bearbeitung der Mahnverfahren erforderlich ist (Verfahrensablaufplan) '''(Quellinfo = Buch "ZPO" S. 163 ff.)'''
= § 703 c (ZPO) Formulare; Einführung der maschinellen Bearbeitung. =
(1) 1 Das Bundesministerium der Justiz und für Verbraucherschutz wird ermächtigt, durch Rechtsverordnung 1) mit Zustimmung des Bundesrates zur Vereinfachung des Mahnverfahrens und zum Schutze der in Anspruch genommenen Partei Formulare einzuführen. 2 Für 1. Mahnverfahren bei Gerichten, die die Verfahren maschinell bearbeiten. 2. Mahnverfahren bei Gerichten, die die Verfahren nicht maschinell bearbeiten. 3. Mahnerfahren, in denen der Mahnbescheid im Ausland zuzustellen ist. 4. Mahnverfahren, in denen der Mahnbescheid nach Artikel 32 des Zusatzabkommen zum NATO-Truppenstatut vom 3. August 1959 (BGB1, 1961 II S. 1183, 1218) zuzustellen ist, können unterschiedliche Formulare eingeführt werden. (2) Soweit nach Absatz 1 Formulare für Anträge und Erklärungen der Parteien eingeführt sind, müssen sich die Parteien ihrer bedienen. (3) Die Landesregierungen bestimmen durch Rechtsverordnung den Zeitpunkt, in dem bei einem Amtsgericht maschinelle Bearbeitung der Mahnverfahren eingeführt wird; sie können die Ermächtigung durch Rechtsverordnung auf die Landesjustizverwaltungen übertragen. '''(Quellinfo = Buch "ZPO" S. 164 ff.)'''
= § 703 d (ZPO) Antragsgegner ohne allgemeinen inländischen Gerichtsstand. =
(1) Hat der Antragsgegner keinen allgemeinen Gerichtsstand im Inland, so gelten die nachfolgenden besonderen Vorschriften. (2) 1 Zuständig für das Mahnverfahren ist das Amtsgericht, das für das streitige Verfahren zuständig sein würde, wenn die Amtsgerichte im ersten Rechtszug sachlich unbeschränkt zuständig wären. 2 § 689 Abs. 2 gilt entsprechend. '''(Quellinfo = Buch "ZPO" S. 164 ff.)'''
::'''Buch 8. Zwangsvollstreckung'''
: '''Abschnitt 1. Allgemeine Vorschriften'''
= § 704 (ZPO) Vollstreckbare Endurteile. =
Die Zwangsvollstreckung findet statt aus Endurteilen, die rechtskräftig oder für vorläufig vollstreckbar erklärt sind. '''(Quellinfo = Buch "ZPO" S. 164 ff.)'''
= § 705 (ZPO) Formelle Rechtskraft. =
1 Die Rechtskraft der Urteile tritt vor Ablauf der für die Einlegung des zulässigen Rechtsmittels oder des zulässigen Einspruchs bestimmten Frist nicht ein. 2 Der Einritt der Rechtskraft wird durch rechtzeitige Einlegung des Rechtsmittels oder des Einspruchs gehemmt. '''(Quellinfo = Buch "ZPO" S. 165 ff.)'''
= § 706 (ZPO) Rechtskraft- und Notfristzeugnis. =
(1) Zeugnisse über die Rechtskraft der Urteile sind auf Grund der Prozessakten von der Geschäftsstelle des Gerichts des ersten Rechtszuges und, solange der Rechtsstreit in einem höheren Rechtszug anhängig ist, von der Geschäftsstelle des Gerichts dieses Rechtszuges zu erteilen. (2) 1 Soweit die Erteilung des Zeugnisses davon abhängt, dass gegen das Urteil ein Rechtsmittel nicht eingelegt ist, holt die Geschäftsstelle des Gerichts des ersten Rechtszuges bei der Geschäftsstelle des für das Rechtsmittel zuständigen Gerichts eine Mitteilung in Textform ein, dass bis zum Ablauf der Notfrist eine Rechtsmittelschrift nicht eingereicht sei. 2 Einer Mitteilung durch die Geschäftsstelle des Revisonsgerichts, dass ein Antrag auf Zulassung der Revision nach § 566 nicht eingereicht sei, bedarf es nicht. '''(Quellinfo = Buch "ZPO" S. 165 ff.)'''
= § 707 (ZPO) Einstweilige Einstellung der Zwangsvollstreckung. =
(1) 1 Wird die Wiedereinsetzung in den vorigen Stand oder eine Wiederaufnahme des Verfahrens beantragt oder die Rüge nach § 321 a erhoben oder wird der Rechtsstreit nach der Verkündung eines Vorbehaltsurteils fortgesetzt , so kann das Gericht auf Antrag anordnen, dass die Zwangsvollstreckung gegen oder ohne Sicherheitsleistung einstweilen eingestellt werde oder nur gegen Sicherheitsleistung stattfinde und dass die Vollstreckungsmaßregeln gegen Sicherheitsleistung aufzuheben seien. 2 Die Einstellung der Zwangsvollstreckung ohne Sicherheitsleistung ist nur zulässig, wenn glaubhaft gemacht wird, dass der Schuldner zur Sicherheitsleistung nicht in der Lage ist und die Vollstreckung einen nicht zu ersetzenden Nachteil bringen würde. (2) 1 Die Entscheidung ergeht durch Beschluss. 2 Eine Anfechtung des Beschlusses findet nicht statt. '''(Quellinfo = Buch "ZPO" S. 165 ff.)'''
= § 708 (ZPO) Vorläufige Vollstreckbarkeit ohne Sicherheitsleistung. =
Für vorläufig vollstreckbar ohne Sicherheitsleistung sind zu erklären: 1. Urteile, die auf Grund eines Anerkenntnissen oder eines Verzichts ergehen; 2. Versäumnisurteile und Urteile nach Lage der Akten gegen die säumige Partei gemäß § 331 a; 3. Urteile, durch die gemäß § 341 der Einspruch als unzulässig verworfen wird; 4. Urteile, die im Urkunden-, Wechsel- oder Scheckprozess erlassen werden; 5. Urteile, die ein Vorbehaltsurteil, das im Urkunden-, Wechsel- oder Scheckprozess erlassen wurde, für vorbehaltlos erklären; 6. Urteile, durch die Arreste oder einstweilige Verfügungen abgelehnt oder aufgehoben werden 7. Urteile in Streitigkeiten zwischen dem Vermieter und dem Mieter oder Untermieter von Wohnräumen oder anderen Räumen oder zwischen dem Mieder und dem Untermieter solcher Räume wegen Überlassung, Benutzung oder Räumung, wegen Fortsetzung des Mietverhältnisses über Wohnraum auf Grund der §§ 574 bis 574 b des Bürgerlichen Gesetzbuchs sowie wegen Zurückhaltung der von dem Mieter oder dem Untermieter in die Mieträume eingebrachten Sachen; 8. Urteile, die die Verpflichtung aussprechen, Unterhalt, Renten wegen Entziehung einer Unterhaltsforderung oder Renten wegen einer Verletzung des Körpers oder der Gesundheit zu entrichten soweit sich die Verpflichtung auf die Zeit nach der Klageerhebung und auf das ihr vorausgehende letzte Vierteljahr erzieht; 9. Urteile nach §§ 861, 862 des Bürgerlichen Gesetzbuchs auf Wiedereinräumung des Besitzes oder auf Beseitigung oder Unterlassung einer Besitzstörung; 10. Berufungsurteile in vermögensrechtlichen Streitigkeiten. Wird die Berufung durch Urteil oder Beschluss gemäß § 522 Absatz 2 zurückgewiesen., ist auszusprechen dass das angefochtene Urteil ohne Sicherheitsleistung vorläufig vollstreckbar ist; 11. andere Urteile in vermögensrechtlichen Streitigkeiten, wenn der Gegenstand der Verurteilung in der Hauptsache 1250 Euro nicht übersteigt oder wenn nur die Entscheidung über die Kosten vollstreckbar ist und eine Vollstreckung im Wert von nicht mehr als 1500 Euro ermöglicht. '''(Quellinfo = Buch "ZPO" S. 165 ff.)'''
= § 709 (ZPO) Vorläufige Vollstreckbarkeit gegen Sicherheitsleistung. =
1 Andere Urteile sind gegen eine der Höhe nach zu bestimmende Sicherheit für vorläufig vollstreckbar zu erklären. 2 Soweit wegen einer Geldforderung zu vollstrecken ist, genügt es, wenn die Höhe der Sicherheitsleistung in einem bestimmten Verhältnis zur Höhe des jeweils zu vollstreckenden Betrages angegeben wird. 3 Handelt es sich um ein Urteil, das ein Versäumnisurteil aufrechterhält, so ist auszusprechen, dass die Vollstreckung aus dem Versäumnisurteil nur gegen Leistung oder Sicherheit fortgesetzt werden darf. '''(Quellinfo = Buch "ZPO" S. 166 ff.)'''
= § 710 (ZPO) Ausnahmen von der Sicherheitsleistung des Gläubigers. =
Kann der Gläubiger die Sicherheit nach § 709 nicht oder nur unter erheblichen Schwierigkeiten leisten, so ist das Urteil auf Antrag auch ohne Sicherheitsleistung für vorläufig vollstreckbar zu erklären, wenn die Aussetzung der Vollstreckung dem Gläubiger einen schwer zu ersetzenden oder schwer abzusehenden Nachteil bringen würde oder aus einem sonstigen Grund für den Gläubiger unbillig wäre, insbesondere weil der die Leistung für seine Lebenshaltung oder seine Erwerbstätigkeit dringend benötigt. '''(Quellinfo = Buch "ZPO" S. 166 ff.)'''
= § 711 (ZPO) Abwendungsbefugnis. =
1 In den Fällen des § 708 Nr. 4 bis 11 hat das Gericht auszusprechen, dass der Schuldner die Vollstreckung durch Sicherheitsleistung oder Hinterlegung abwenden darf, wenn nicht der Gläubiger vor der Vollstreckung Sicherheit leistet. 2 § 709 Satz 2 gilt entsprechend, für den Schuldner jedoch mit der Maßgabe dass Sicherheit in einem bestimmten Verhältnis zur Höhe des auf Grund des Urteils vollstreckbaren Betrages zu leisten ist. 3 Für den Gläubiger gilt § 710 entsprechend. '''(Quellinfo = Buch "ZPO" S. 166 ff.)'''
= § 712 (ZPO) Schutzantrag des Schuldners. =
(1) 1 Würde die Vollstreckung dem Schuldner einen nicht zu ersetzenden Nachteil bringen, so hat ihm das Gericht auf Antrag zu gestatten, die Vollstreckung durch Sicherheitsleistung oder Hinterlegung ohne Rücksicht auf eine Sicherheitsleistung des Gläubigers abzuwenden; § 709 Satz 2 gilt in den Fällen des § 709 Satz 1 entsprechend. 2 Ist der Schuldner dazu nicht in der Lage, so ist das Urteil nicht für vorläufig vollstreckbar zu erklären oder die Vollstreckung auf die in § 720a Abs. 1, 2 bezeichneten Maßregeln zu beschränken. (2) 1 Dem Antrag des Schuldners ist nicht zu entsprechen wenn ein überwiegendes Interesse des Gläubigers entgegensteht. 2 In den Fällen des § 708 kann das Gericht anordnen, dass das Urteil nur gegen Sicherheitsleistung vorläufig vollstreckbar ist. '''(Quellinfo = Buch "ZPO" S. 167 ff.)'''
= § 713 (ZPO) Unterbleiben von Schuldnerschutzanordnungen. =
Die in den §§ 711, 712 zugunsten des Schuldners zugelassenen Anordnungen sollen nicht ergehen, wen die Voraussetzungen, unter denen ein Rechtsmittel gegen das Urteil stattfindet, unzweifelhaft nicht vorliegen. '''(Quellinfo = Buch "ZPO" S. 168 ff.)'''
= § 714 (ZPO) Anträge zur vorläufigen Vollstreckbarkeit. =
(1) Anträge nach den §§ 710, 711 Satz 3, § 712 sind vor Schluss der mündlichen Verhandlung zu stellen, auf die das Urteil ergeht. (2) Die tatsächlichen Voraussetzungen sind glaubhaft zu machen. '''(Quellinfo = Buch "ZPO" S. 168 ff.)'''
= § 715 (ZPO) Rückgabe der Sicherheit. =
(1) 1 Das Gericht, das eine Sicherheitsleistung des Gläubigers angeordnet oder zugelassen hat, ordnet auf Antrag die Rückgabe der Sicherheit an, wenn ein Zeugnis über die Rechtskraft des für vorläufig vollstreckbar erklärten Urteils vorgelegt wird. 2 Ist die Sicherheit durch eine Bürgschaft bewirkt worden, so ordnet das Gericht das Erlöschen der Bürgschaft an. (2) § 109 Abs. 3 gilt entsprechend. '''(Quellinfo = Buch "ZPO" S. 168 ff.)'''
= § 716 (ZPO) Ergänzung des Urteils. =
Ist über die vorläufige Vollstrecktbarkeit nicht entschieden, so sind wegen Ergänzung des Urteils die Vorschriften des § 321 anzuwenden. '''(Quellinfo = Buch "ZPO" S. 168 ff.)'''
= § 717 (ZPO) Wirkungen eines aufhebenden oder abändernden Urteils =
(1) Die vorläufige Vollstreckbarkeit tritt mit der Verkündung eines Urteils, das die Entscheidung In der Hauptsache oder die Vollsteckbarkeitserklärung aufhebt oder abändert, insoweit außer Kraft, als die Aufhebung oder Abänderung ergeht. (2) 1 Wird ein für vorläufig vollstreckbar erklärtes Urteil aufgehoben oder abgeändert, so ist der Kläger zum Ersatz des Schadens verpflichtet, der dem Beklagten durch die Vollstreckung des Urteils oder durch eine zur Abwendung der Vollstreckung gemachte Leistung entstanden ist. 2 Der Beklagte kann den Anspruch auf Schadensersatz in dem anhängigen Rechtsstreit geltend machen, wird der Anspruch geltend gemacht, so ist er als zur Zeit der Zahlung oder Leistung rechtshängig geworden anzusehen. (3) 1 Die Vorschriften des Absatzes 2 sind auf die im § 708 Nr. 10 bezeichneten Berufungsurteile mit Ausnahme der Versäumnisurteile, nicht anzuwenden. 2 Soweit ein solches Urteil aufgehoben oder abgeändert wird, ist der Kläger auf Antrag des Beklagten zur Erstattung des von diesem auf Grund des Urteils Gezahlten oder Geleisteten zu verurteilen. 3 Die Erstattungspflicht des Klägers bestimmt sich nach den Vorschriften über die Herausgabe einer ungerechtfertigten Bereicherung. 4. Wird der Antrag gestellt, so ist der Anspruch auf Erstattung als zur Zeit der Zahlung oder Leistung rechtshängig geworden anzusehen: die mit der Rechtsabhängigkeit nach den Vorschriften des bürgerlichen Rechts verbundenen Wirkungen treten mit der Zahlung oder Leistung auch dann ein, wenn der Antrag nicht gestellt wird.'''(Quellinfo = Buch "ZPO" S. 168 ff.)'''
= § 718 (ZPO) Vorabentscheidung über vorläufige Vollstreckbarkeit =
(1) In der Berufungsinstanz ist über die vorläufige Vollstreckbarkeit auf Antrag vorab zu verhandeln und zu entscheiden, (2) Eine Anfechtung der in der Berufungsinstanz über die vorläufige Vollstreckbarkeit erlassenen Entscheidung findet nicht statt. '''(Quellinfo = Buch "ZPO" S. 169 ff.)'''
= § 719 (ZPO) Einstweilige Einstellung bei Rechtsmittel und Einspruch. =
(1) 1 Wird gegen ein für vorläufig vollstreckbar erklärtes Urteil der Einspruch oder die Berufung eingelegt, so gelten die Vorschriften des § 707 entsprechend. 2 Die Zwangsvollstreckung aus einem Versäumnisurteil darf nur gegen Sicherheitsleistung eingestellt werden, es sei denn, dass das Versäumnisurteil nicht in gesetzlicher Weise ergangen ist oder sie säumige Partei glaubhaft macht, dass ihr Säumnis unverschuldet war.
(2) 1 Wird Revision gegen ein für vorläufig vollstreckbar erklärtes Urteil eingelegt, so ordnet das Revisionsgericht auf Antrag an, dass die Zwangsvollstreckung einstweilen eingestellt wird, wenn die Vollstreckung dem Schuldner einen nicht zu ersetzenden Nachteil bringen würde und nicht ein überwiegendes Interesse des Gläubigers entgegensteht. 2 Die Parteien haben die tatsächlichen Voraussetzungen glaubhaft zu machen.
(3) Die Entscheidung ergeht per Beschluss. '''(Quellinfo = Buch "ZPO" S. 169 ff.)'''
= § 720 (ZPO) Hinterlegung bei Abwendung der Vollstreckung. =
Darf der Schuldner nach § 711 Abs. 1 Satz 1 die Vollstreckung durch Sicherheitsleistung oder Hinterlegung abwenden, so ist gepfändetes Geld oder der Erlös gepfändeter Gegenstände zu hinterlegen.
= § 721 (ZPO) Räumungsfrist. =
.....Text folgt noch!
= § 722 (ZPO) Vollstreckbarkeit ausländischer Urteile. =
.....Text folgt noch!
= § 723 (ZPO) Vollstreckungsurteil. =
.....Text folgt noch!
= § 724 (ZPO) Vollstreckbare Ausfertigung. =
.....Text folgt noch!
= § 725 (ZPO) Vollstreckungsklausel. =
.....Text folgt noch!
= § 726 (ZPO) Vollstreckbare Ausfertigung bei bedingten Leistungen. =
.....Text folgt noch!
= § 727 (ZPO) Vollstreckbare Ausfertigung für und gegen Rechtsnachfolger. =
.....Text folgt noch!
= § 728 (ZPO) Vollstreckbare Ausfertigung bei Nacherbe oder Testamentsvollstrecker. =
.....Text folgt noch!
= § 729 (ZPO) Vollstreckbare Ausfertigung gegen Vermögens- und Firmenübernehmer. =
.....Text folgt noch!
= § 730 (ZPO) Anhörung des Schuldners. =
.....Text folgt noch!
= § 731 (ZPO) Klage auf Erteilung der Vollstreckungsklausel. =
.....Text folgt noch!
= § 755<sup>1)</sup>Ermittlung des Aufenthaltsorts des Schuldners. =
(1) <sup>1</sup> Ist der Wohnsitz oder gewöhnliche Aufenhaltsort des Schuldners nicht bekannt, darf der Gerichtsvollzieher auf Grund des Vollstreckungsauftrags und der Übergabe der vollstreckbaren Ausfertigung zur Ermittlung des Aufenthaltsorts des Schuldners bei der Meldebehörde die gegenwärtigen Anschriften sowie Angaben zur Haupt- und Nebenwohnung des Schuldners erheben.
<sup>2</sup>Der Gerichtsvollzieher darf auch beauftragt werden, die gegenwärtigen Anschriften, den Ort der Hauptniederlassung oder den Sitz des Schuldners zu erheben. Ort der Hauptniederlassung öden den Sitz des Schuldners zu erheben. <br> 1. durch Einsicht in das Handels-, Genossenschaft-, Partnerschafts-, Unternehmens- oder Vereinsregister oder <br> 2. durch Einholung einer Auskunft bei den nach Landesrecht für die Durchführung der Aufgaben nach § 14 Absatz 1 der Gewerbeordnung zuständigen Behörden.
(2)<sup>1</sup>Soweit der Aufenthaltsort des Schuldners nach Absatz 1 nicht zu ermitteln ist, darf der Gerichtsvollzieher <br> 1. zunächst beim Ausländerzentralregisteer die Angaben zur aktenführenden Ausländerbehörde sowie zum Zuzug oder Fortzug des Schuldners und anschließend bei der gemäß der Auskunft aus dem Ausländerzentralregister aktenführenden Ausländerbehörde den Aufenthaltsort des Schuldners. <br> 2. bei den Trägern der gesetzlichen Rentenversicherung '''''[ab 1.1.2022: '' '''''und bei einer berufsständischen Versorgungseinrichtung im Sinne des § 6 Absatz 1 Satz 1 Nummer 1 des Sechsten Buches Sozialgesetzbuch]'' die dort bekannte derzeitige Anschrift, den derzeitigen oder zukünftigen Aufenthaltsort des Schulders sowie''' <br> '''3. bei dem Kraftfahrt-Bundesamt die Halterdaten nach § 33 Abs. 1 Satz 1 Nr. 2 des Straßenverkehrsgesetzes erheben.''' <sup>2</sup>'''Ist der Schuldner Unionsbürger, darf der Gerichtsvollzieher die Daten nach Satz 1 Nummer 1 nur erheben, wenn ihm tatsächliche Anhaltspunkte für die Vermutung der Feststellung des Nichtbestehens oder des Verlusts des Freizügigkeitsrechts vorliegen'''. <sup>3</sup>'''Eine Übermittlungen Daten nach Satz 1 Nummer 1 an den Gerichtsvollzieher ist ausgeschlossen, wenn der Schuldner Unionsbürger ist, für den eine Feststellung des Nichtbestehens oder des Verlusts des Freizügigkeitsrechts nicht vorliegt. '''''[Satz 4 ab 1.1.2022:]''''' <sup>4</sup>Die ''Erhebung nach Satz 1 Nummer 2 bei einer berufsständischen Versorgungseinrichtung darf der Gerichtsvollzieher nurdurchführen, wenn der Gläubiger die berufsständische Versorgungseinrichtung bezeichnet und tatsächliche Anhaltspunkte nennt, die nahelegen, dass der Schuldner Mitglied dieser berufsständischen Versorgungseinrichtung ist.'' <br> (3) Nach Absatz 1 oder Absatz 2 erhobene Daten, die innerhalb der letzten drei Monate bei dem Gerichtsvollzieher eingegangensind, darf dieser auch in einem Zwangsvollstreckungsverfahren eines weiteren Gläubigers gegen denselben Schuldner verarbeiten, wenn die Voraussetzungen für die Datenerhebung auch bei diesem Gläubiger vorliegen.
= § 758 (ZPO) Durchsuchung: Gewaltanwendung. =
(1) Der Gerichtsvollzieher ist befugt, die Wohnung und die Behältnisse des Schuldners zu durchsuchen, soweit der Zweck der Vollstreckung dies erfordert. (2) Er ist befugt, die verschlossenen Haustüren, Zimmertüren und Behältnisse öffnen zu lassen. (3) Er ist, wenn er Widerstand findet, zur Anwendung von Gewalt befugt und kann zu diesem Zweck die Unterstützung der polizeilichen Vollzugsorgane nachsuchen. '''(Quellinfo = Buch "ZPO" S. 177 ff.)'''
= § 758a (ZPO) Richterliche Durchsuchungsanordnung: Vollstreckung zur Unzeit =
(1) 1 Die Wohnung des Schuldners darf ohne dessen Einwilligung nur auf Grund einer Anordnung des Richters bei dem Amtsgericht durchsucht werden, in dessen Bezirk die Durchsuchung erfolgen soll. 2 Dies gilt nicht, wenn die Einholung der Anordnung den Erfolg der Durchsuchung gefährden würde.
(2) Auf die Vollstreckung eines Titels auf Räumung oder Herausgabe von Räumen und auf die Vollstreckung eines Haftbefehls nach § 802g ist Absatz 1 nicht anzuwenden. (3) 1 Willigt der Schuldner in die Durchsuchung ein oder ist eine Anordnung gegen ihn nach Absatz 1 Satz 1 ergangen oder nach Absatz 1 Satz 2 entbehrlich, so haben Personen die Mitgewahrsam an der Wohnung des Schuldner haben, die Durchsuchung zu dulden. 2 Unbillige Härten gegenüber Mitgewahrsamsinhabern sind zu vermeiden. (4) 1 Der Gerichtsvollzieher nimmt eine Vollstreckungshandlung zur Nachtzeit und an Sonn- und Feiertagen nicht vor, wenn dies für den Schuldner und die Mitgewahrsamtsinhaber eine unbillige Härte darstellt oder der zu erwartende Erfolg in einem Missverhältnis zu dem Eingriff steht, in Wohnungen nur auf Grund einer besondreren Anordnung des Richters bei dem Amtsgericht. 2 Die Nachtzeit umfasst die Stunden von 21 bis 6 Uhr. (5) Die Anordnung nach Absatz 1 ist bei der Zwangsvollstreckung vorzuzeigen. (6) 1 Das Bundesministerium der Justiz und für Verbraucherschutz wird ermächtigt durch Rechtsverordnung mit Zustimmung des Bundesrates Formulare für den Antrag auf Erlass einer richterlichen Durchsungsanordnung nach Absatz 1 einzuführen. 2 Soweit nach Satz 1 Formulare eingeführt sind, muss sich der Antragsteller ihrer bedienen. 3 Für Verfahren bei Gerichten die die Verfahren elektronisch bearbeiten und für Verfahren bei Gerichten, die die Verfahren nichtelektronisch bearbeiten, können unterschiedlichen Formulare eingeführt werden. '''(Quellinfo = Buch "ZPO" S. 177 ff.)'''
= § 759 (ZPO) Zuziehung von Zeugen =
Wird bei einer Vollstreckungshandlung Widerstand geleistet oder ist bei einer in der Wohnung des Schuldners vorzunehmenden Vollstreckungshandlung weder der Schuldner noch ein erwachsener Familienangehöriger, eine in der Familie beschäftigte Person oder ein erwachsener ständiger Mitbewohner anwesend, so hat der Gerichtsvollzieher zwei erwachsener Personen oder einen Gemeinde- oder Polizeibeamten als Zeugen zuzuziehen. '''(Quellinfo = Buch "ZPO" S. 177 ff.)'''
= § 760 (ZPO) Akteneinsicht: Aktenabschrift =
1 Jeder Person, die bei dem Vollstreckungsverfahren beteiligt ist, muss auf Begehren Einsicht der Akten des Gerichtsvollziehers gestattet und Abschrift einzelner Aktenstücke erteilt werden. 2 Werden die Akten des Gerichtsvollziehers elektronisch geführt, erfolgt die Gewährung von Akteneinsicht durch Erteilung von Ausdrucken, durch Übermittlung von elektronischen Dokumenten oder durch Wiedergabe auf einem Bildschirm; dies gilt auch für die nach §§ 885 a Absatz 2 Satz 2 elektronisch gespeicherten Dateien, '''(Quellinfo = Buch "ZPO" S. 178 ff.)'''
= § 761 (ZPO) - (weggefallen) =
'''(Quellinfo = Buch "ZPO" S. 178 ff.)'''
= § 762 (ZPO) Protokoll über Vollstreckungshandlungen =
(1) DerGerichtsvollzieher hat über jede Vollstreckungshandlung ein Protokoll aufzunehmen. (2) Das Protokoll muss enthalten: 1. Ort und Zeit der Aufnahmen: 2. den Gegenstand der Vollstreckungshandlung unter kurzer Erwähnung der wesentlichen Vorgänge. 3. die Namen der Personen, mit denen verhandelt ist; 4. die Unterschrift dieser Personen und den Vermerk, dass die Unterzeichnung nach Vorlesung oder Vorlegung zur Durchsicht und nach Genehmigung erfolgt sei: 5. die Unterschrift des Gerichtsvollziehers. (3) Hat einem der unter Nummer 4 bezeichneten Erfordernisse nicht genügt werden können, so ist der Grund anzugeben. '''(Quellinfo = Buch "ZPO" S. 178 ff.)'''
= § 763 (ZPO) Aufforderungen und Mitteilungen =
(1) 1 Die Aufforderungen und sonstigen Mitteilungen, die zu den Vollstreckungshandlungen gehören, sind von dem Gerichtsvollzieher mündlich zu erlassen und vollständig in das Protokoll aufzunehmen. (2) 1 Kann dies mündlich nicht ausgeführt werden, so hat der Gerichtsvollzieher eine Abschrift des Protokolls zuzustellen oder durch die Post zu übersenden. 2 Es muss im Protokoll vermerkt werden, dass diese Vorschrift befolgt ist. 3 Eine öffentliche Zustellung findet nicht statt. '''(Quellinfo = Buch "ZPO" S. 178 ff.)'''
= § 764 (ZPO) Vollstreckungsgericht =
(1) Die den Gerichten zugewiesene Anordnung von Vollstreckungshandlungen und Mitwirkung bei solchen gehört zur Zuständigkeit der Amtsgerichte als Vollstreckungsgerichte. (2) Als Vollstreckungsgericht ist, sofern nicht das Gesetz ein anderes Amtsgericht bezeichnet, das Amtsgericht anzusehen, in dessen Bezirk das Vollstreckungsverfahren stattfinden soll oder stattgefunden hat. (3) Die Entscheidungen des Vollstreckungsgerichts ergehen durch Beschluss. '''(Quellinfo = Buch "ZPO" S. 178 ff.)'''
= § 765 (ZPO) Vollstreckungsgerichtliche Anordnungen bei Leistung Zug um Zug. =
1 Hängt die Vollstreckung von einer Zug um Zug zu bewirkenden Leistung des Gläubigers an den Schuldner ab, so darf das Vollstreckungsgericht eine Vollstreckungsmaßregel nur anordnen, wenn 1. der Beweis, dass der Schuldner befriedigt oder im Verzug der Annahme ist, durch öffentliche oder öffentlich beglaubigte Urkunden geführt wird und ein Abschrift dieser Urkunden bereits zugestellt ist; der Zustellung bedarf es nicht, wenn bereits der Gerichtsvollzieher die Zwangsvollstreckung nach § 756 Abs. 1 begonnen hatte und der Beweis durch das Protokoll des Gerichtsvollziehers geführt wird; oder
2. der Gerichtsvollzieher eine Vollstreckungsmaßnahme nach § 756 Abs. 2 durchgeführt hat und diese durch das Protokoll des Gerichtsvollziehers nachgewiesen ist. '''(Quellinfo = Buch "ZPO" S. 178 ff.)'''
= § 765 a (ZPO) Vollstreckungsschutz. =
(1) 1 Auf Antrag des Schuldners kann das Vollstreckungsgericht eine Maßnahme der Zwangsvollstreckung ganz oder teilweise aufheben, untersagen oder einstweilen einstellen, wenn die Maßnahme unter voller Würdigung des Schutzbedürfnisses des Gläubigers eggen ganz besonderer Umstände eine Härte bedeutet, die mit den guten Sitten nicht vereinbar ist. 2 Es ist befugt, die in § 732 Ab. 2 bezeichneten Anordnungen zu erlassen. 3 Betrifft die Maßnahme ein Tier, so hat das Vollstreckungsgericht bei der von ihm vorzunehmenden Abwägung die Verantwortung ges Menschen für das Tier zu berücksichtigen. (2) Eine Maßnahme zur Erwirkung der Herausgabe von Sachen kann der Gerichtsvollzieher bis zur Entscheidung des Vollstreckungsgerichts, jedoch nicht länger als eine Woche aufschieben, wenn ihm die Voraussetzungen des Absatzes 1 Satz 1 glaubhaft gemacht werden und dem Schulter die rechtzeitige Anrufung Tees Vollstreckungsgerichts nicht möglich war. (3) In Räumungssachen ist der Antrag nach Absatz 1 spätestens zwei Wochen vor dem festgesetzten Räumungstermin zu stellen, es sei denn dass die Gründe , auf denen der Antrag beruht, erst nach diesem Zeitpunkt entstanden sind oder der Schuldner ohne sein Verschulden an einer rechtzeitigen Antragstellung gehindert war. (4) Das Vollstreckungsgericht hebt seinen Beschluss auf Antrag auf oder ändert ihn, wenn dies mit Rücksicht auf eine Änderung der Sachlage geboten ist. (5) Die Aufhebung von Vollsrteckungsmaßregeln erfolgt in den Fällen des Absatzes 1 Satz 1 und des Absatzes 4 erst nach Rechtskraft des Beschlusses. '''(Quellinfo = Buch "ZPO" S. 179 ff.)'''
= § 766 (ZPO) Erinnerung gegen Art und Weise der Zwangsvollstreckung. =
(1) 1 Über Anträge, Einwendungen und Erinnerungen, welche die Art und Weise der Zwangsvollstreckung oder das vom Gerichtsvollzieher bei ihr zu beobachtende Verfahren betreffen, entscheidet das Vollstreckungsgericht. 2 Es ist befugt, die im § 732 Abs. 2 bezeichenden Anordnungen zu erlassen. (2) Dem Vollstreckungsgericht steht auch die Entscheidung zu, wenn ein Gerichtsvollzieher sich weigert, einen Vollstreckungsauftrag zu übernehmen oder eine Vollstreckungshandlung dem Auftrag gemäß auszuführen, oder wenn wegen der von dem Gerichtsvollzieher in Ansatz gebrachten Kosten Erinnerungen erhoben werden. '''(Quellinfo = Buch "ZPO" S. 179 ff.)'''
= § 767 (ZPO) Vollstreckungsabwehrklage. =
(1) Einwendungen, die den durch das Urteil festgestellten Anspruch selbst betreffen, sind von dem Schuldner im Wege der Klage bei dem Prozessgericht des ersten Rechtszuges geltend zu machen. (2) sie sind nur insoweit zulässig, als die Gründe auf denen sie beruhen, erst nach dem Schluss der mündlichen Verhandlung, in der Einwendungen nach den Vorschriften dieses Gesetzes spätestens hätten geltend gemacht werden müssen, entstanden sind und durch Einspruch nicht mehr geltend gemacht werden können. (3) Der Schuidner muss in der von ihm zu erhebenden Klage alle Einwendungen geltend machen, die er zur Zeit der Erhebung der Klage geltend zu machen imstande war. '''(Quellinfo = Buch "ZPO" S. 180 ff.)'''
= § 768 (ZPO) Klage gegen Vollstreckungsklausel. =
Die Vorschriften des § 767 Abs. 1, 3 gelten entsprechend, wenn in den Fällen des § 726 Abs. 1, der §§ 727 bis 729, 738. 742, 744, des § 749 der Schuldner den bei der Erteilung der Vollstreckungsklausel als beweisen angenommenen Eintritt der Voraussetzung für die Erteilung der Vollstreckungsklausel bestreitet, unbeschadet der Befugnis des Schuldners, in diesen Fällen Einwendungen gegen die Zulässigkeit der Vollstreckungsklausel nach § 732 zu erheben. '''(Quellinfo = Buch "ZPO" S. 180 ff.)'''
= § 769 (ZPO) Einstweilige Anordnungen. =
(1) 1 Das Prozessgericht kann auf Antrag anordnen, dass bis zum Erlass des Urteils über die in den §§ 767, 768 bezeichneten Einwendungen die Zwangsvollstreckung gegen oder ohne Sicherheitsleistung eingestellt per nur gegen Sicherheitsleistung fortgesetzt werde und das Vollstreckungsmaßregeln gegen Sicherheitsleistung aufzuheben seien. 2 Es setzt eine Sicherheitsleistung für die Einstellung der Zwangsvollstreckung nicht fest, wenn der Schuldner zur Sicherheitsleistung nicht in der Lage ist und die Rechtsverfolgung durch ihn hinreichende Aussicht auf Erfolg bietet. 3 Die tatsächlichen Behauptungen, die den Antrag begründen, Erfolg bietet. 3 Die tatsächlichen Behauptungen, die den Antrag begründen sind glaubhaft zu machen. (2) 1 In dringenden Fällen kann das Vollstreckungsgericht eine solche Anordnung erlassen, unter Bestimmung einer Frist innerhalb der die Entscheidung des Prozessgerichts beizubringen sei. 2 Nach fruchtlosem Ablauf der Frist wird die Zwangsvollstreckung fortgesetzt. (3) Die Entscheidung über diese Anträge ergeht durch Beschluss. (4) Im Fall der Anhängigkeit einer auf Herabsetzung gerichteten Abänderungsklage gelten die Absätze 1 bis 3 entsprechend. '''(Quellinfo = Buch "ZPO" S. 180 ff.)'''
= § 770 (ZPO) Einstweilige Anordnungen im Urteil. =
<sup>1</sup>Das Prozessgericht kann in dem Urteil, durch das über die Einwendungen entschieden wird, die in dem vorstehendem Paragraphen bezeichneten Anordnungen erlassen oder die bereits erlassenen Anordnungen aufheben, abändern oder bestätigen. <sup>2</sup> Für die Anfechtungen einer solchen Entscheidung gelten die Vorschriften des § 718 entsprechend. '''(Quellinfo = Buch "ZPO" S. 184 ff.)'''
= § 771 (ZPO) Drittwiderspruchsklage. =
(1) Behauptet ein Dritter, dass ihm an dem Ggenstnd der Zwangsvollstreckung ein die Veräußerung hinderndes Recht zustehe, so ist der Widerspruch gegen die Zwangsvollstreckung im Wege der Klage bei dem Gericht geltend zu machen, in dessen Bezirk die Zwangsvollstreckung erfolgt. (2) Wird die Klage gegen den gläubiger und den Schuldner gerichtet, so sind diese als Streitgenossen anzusehen. (3)<sup>1</sup> Auf die Einstellung der Zwangsvollstreckung und die Aufhebung der bereits getroffenen Vollstreckungmapregeln sin die Vorschriften der §§ 769, 770 entsprechend anzuwenden. <sup>2</sup> Die Aufhebung einer Vollstreckungsmaßregel ist auch ohne Sicherheitsleistung zulässig. '''(Quellinfo = Buch "ZPO" S. 184 ff.)'''
= § 772 (ZPO) Drittwiderspruchsklage bei Veräußerungsverbot. =
<sup>1</sup>Solange ein Veräußerungsverbot der in den §§ 135,136 des Bürgerlichen Gesetzbuchs bezeichneten Art besteht, soll der Gegenstand auf den es sich bezieht, wegen eines persönlichen Anspruchs oder auf Grund eines infolge des Verbots unwirksamen Rechts nicht im Wege der Zwangsvollstreckung veräußert oder überwiesen werden. <sup>2</sup>Auf Grund des Veräußerungsverbots kann nach Maßgabe des § 771 Widerspruch erhoben werden.
= § 773 (ZPO) Drittwiderspruchsklage des Nacherben. =
= § 774 (ZPO) Drittwiderspruchsklage des Ehegatten oder Lebenspartners. =
= § 775 (ZPO) Einstellung oder Beschränkung der Zwangsvollstreckung. =
= § 776 (ZPO) Aufhebung von Vollstreckungsmaßregeln. =
= § 777 (ZPO) Erinnerung bei genügender Sicherung des Gläubigers. =
= § 778 (ZPO) Zwangsvollstreckung vor Erbschaftsnahme. =
= § 779 (ZPO) Fortsetzung der Zwangsvollstreckung nach dem Tod des Schuldners. =
= § 780 (ZPO) Vorbehalt der beschränkten Erbenhaftung. =
::'''Titel 2. Zwangsvollstreckung in das bewegliche Vermögen'''
: '''Untertitel 1. Allgemeine Vorschriften'''
= § 802 <sup>1</sup>(ZPO) Auskunftsrechte des Gerichtsvollziehers. =
= § 803 (ZPO) Pfändung. =
(1) 1 Die Zwangsvollstreckung in das bewegliche Vermögen erfolgt durch Pfändung. 2 Sie darf nicht weiter ausgedehnt werden,als es zur Befriedigung des Gläubigers und zur Deckung der Kosten der Zwangsvollstreckung erforderlich ist. (2) Die Pfändung hat zu unterbleiben, wenn sich von der Verwertung der zu pfändenden Gegenstände ein Überschuss über die Kosten der Zwangsvollstreckung nicht erwarten lässt. '''(Quellinfo = Buch "ZPO" S. 200 ff.)'''
= § 804 (ZPO) Pfändungsrecht. =
(1) Durch die Pfändung erwirbt der Gläubiger ein Pfandrecht an dem gepfändeten Gegenstande. (2) Das Pfandrecht gewährt dem Gläubiger im Verhältnis zu anderen Gläubigern dieselben Rechte wie ein durch Vertrag erworbenes Faustpfandrecht; es geht Pfand- und Vorzugsrechten vor, die für den Fall eines Insolvenzverfahrens den Faustpfandrechten nicht gleichgestellt sind. 1) (3) Das durch eine frühere Pfändung begründete Pfandrecht geht demjenigen vor, das durch eine spätere Pfändung begründet wird. '''(Quellinfo = Buch "ZPO" S. 200 ff.)'''
= § 829 a (ZPO) Vereinfachter Vollstreckungsantrag bei Vollstreckungsbescheiden. =
Text folgt noch!
= § 830 (ZPO) Pfändung einer Hypothekenforderung. =
Text folgt noch!
= § 830 a (ZPO) Pfändung einer Schiffshypothekenforderung. =
Text folgt noch!
= § 831 a (ZPO) Pfändung indossabler Papiere. =
Text folgt noch!
= § 832 (ZPO) Pfändungsumfang bei fortlaufenden Bezügen. =
Text folgt noch!
= § 833 (ZPO) Pfändungsumfang bei Arbeits- und Diensteinkommen . =
Text folgt noch!
= § 833 a (ZPO) Pfändungsumfang bei Kontoguthaben. =
Text folgt noch!
= § 834 (ZPO) Keine Anhörung des Schuldners. =
Text folgt noch!
= § 835 a (ZPO) Überweisung einer Geldforderung. =
Text folgt noch!
= § 836 <sup>1</sup> (ZPO) Wirkung der Überweisung. =
Text folgt noch!
= § 837 (ZPO) Überweisung einer Hypothekenforderung. =
Text folgt noch!
= § 837 a (ZPO) Überweisung einer Schiffshypothekenforderung. =
Text folgt noch!
= § 838 (ZPO) Einrede des Schuldners bei Faustpfand. =
Text folgt noch!
= § 839 (ZPO) Überweisung bei Abwendungsbefugnis. =
Text folgt noch!
= § 840 (ZPO) Erklärungspflicht des Drittschuldners. =
Text folgt noch!
= § 841 (ZPO) Pflicht zur Streitverkündung. =
Text folgt noch!
= § 842 (ZPO) Schadenersatz bei verzögerter Beitreibung. =
Text folgt noch!
= § 843 (ZPO) Verzicht des Pfandgläubigers. =
Text folgt noch!
= § 844 (ZPO) Andere Verwertungsart. =
Text folgt noch!
= § 845 <sup>1</sup> (ZPO) Vorpfändung. =
Text folgt noch!
= § 846 (ZPO) Zwangsvollstreckung in Herausgabeansprüche. =
Text folgt noch!
= § 847 (ZPO) Herausgabeanspruch auf eine bewegliche Sache. =
Text folgt noch!
= § 847 a (ZPO) Herausgabeanspruch auf ein Schiff. =
Text folgt noch!
= § 848 (ZPO) Herausgabeanspruch auf eine unbewegliche Sache. =
Text folgt noch!
= § 849 (ZPO) Keine Überweisung an Zahlungs statt. =
Text folgt noch!
= § 850 (ZPO) Pfändungsschutz für Arbeitseinkommen. =
(1) Arbeitseinkommen, das in Geld zahlbar ist, kann nur nach Maßgabe der §§ 850a bis 850i gepfändet werden. (2) Arbeitseinkommen im Sinne dieser Vorschrift sin die Dienst- und Versorgungsbezüge der Beamten, Arbeits- und Dienstlöhne. Ruhegelder und ähnliche nach dem einstweiligen oder dauernden Ausscheiden aus dem Dienst- oder Arbeitsverhältnis gewährte fortlaufende Einkünfte, ferner Hinterblebenenbezüge, soweit sonstige Vergütungen für Dienstleistungen aller Art, die die Erwerbstätigkeit des Schuldners vollständig oder zu einem wesentlichen Teil in Anspruch nehmen. (3) Abeitseinkommen und auchdiefeolgenden Bezüge, soweit sie in Geld zahlbar sind:
:: a) Bezüge, die ein Arbeitnehmer zum Ausgleich für Wettbewerbsbeschränkungen fpr die Zeit nach Beendigung eines inestverhältnisses beanspruchen kann:
:: b) Renten, die auf Grund von Versicherungsunternehmen oder seiner unterhaltsberechtigten Angehörigen eingegangen sind.
(4) Die Pfändung des in Geld zahlbaren Arbeitskommens erfasst alle Vergütungen, die dem Schuldner aus der Arbeits- oder Dienstleistung zustehen, ohne Rücksicht auf ihre Benennung oder Berechnungsart. '''(Quellinfo = Buch "ZPO" S. 216 ff.)'''
= § 850 a (ZPO) Unpfändbare Bezüge. =
Unpfändbar sind
1. zur Hälfte die für die Leistung von Mehrarbeitsstunden gezahlten Teile des Arbeitsseinkommens; 2. die für die Dauer eines Urlaubs über das Arbeitseinkommen hinaus gewährten Bezüge, Zuwendungen aus Anlass eines besonderen Betriebsereignisses und Treugelder, soweit sie den Rahmen des Üblichen nicht übersteigen; 3. Aufwandsentschädigungen, Auslösungsgelder und sonstige soziale Zulagen für auswärtige Beschäftigungen, das Entgelt für selbstgestelltes Arbeitsmaterial. Gefahrenzulagen, sowie Schmutz und Erschwerniszulagen, soweit diese Bezüge den Rahmen des Üblichen nicht übersteigen; 4. Weihnachtsvergütungen bis zum Betrag der Hälfte des monatlichen Arbeitseinkommens, höchstens aber bis zum Betrag von 500 Euro; 5. Geburtsbeihilfen sowie Beihilfen aus Anlass der Eingehung einer Ehe oder Begründung einer Lebenspartnerschaft, sofern die Vollstreckung wegen anderer als der aus Anlass der Geburt, der Eingebung einer Ehe oder der Begründung einer Lebenspartnerschaft entstandenen Ansprüche betrieben wird; 6. Erziehungsgelder, Studienbeihilfen und ähnliche Bezüge; 7. Sterbe- und Gnadenbezüge aus Arbeits- und Dienstverhältnissen; 8. Blindenzulagen. '''(Quellinfo = Buch "ZPO" S. 217 ff.)'''
= § 850 b (ZPO) Bedingt pfändbare Bezüge. =
Text folgt noch!
= § 850 c<sup>1</sup> (ZPO) Pfändungsgrenzen für Arbeitseinkommen. =
Text folgt noch!
= § 850 d (ZPO) Pfändbarkeit bei Unterhaltsansprüchen. =
Text folgt noch!
= § 850 e<sup>1</sup> (ZPO) Berechnung des pfändbaren Arbeitseinkommens. =
Text folgt noch!
= § 850f (ZPO) Änderung des unpfändbaren Betrages. =
Text folgt noch!
= § 850g (ZPO) Änderung der Unpfändbarkeitsvoraussetzungen. =
Text folgt noch!
= § 886 (ZPO) Herausgabe bei Gewahrsam eines Dritten. =
Befindet sich eine herauszugebende Sache im Gewahrsam eines Dritten, so ist dem Gläubiger auf dessen Antrag der Anspruch des Schuldners auf Herausgabe der Sache nach den Vorschriften zu überweisen, welche die Pfändung und Überweisung einer Geldforderung betreffen. '''(Quellinfo = Buch "ZPO" S. 242 ff.)'''
:::::::'''Abschnitt 6. Schiedsspruch und Beendigung des Verfahrens'''
= § 1051 (ZPO) Anwendbares Recht.=
(1) <sup>1</sup> Das Schiedsgericht hat die Streitigkeit in Übereinstimmung mit den Rechtsvorschriften zu entscheiden, die von den Parteien als auf den Inhalt des Rechtsstreits anwendbar bezeichnet worden sind. <sup>2</sup> Die Bezeichnung des Rechts oder der Rechtsordnung eines bestimmten Staats ist, sofern die Parteien nicht ausdrücklich etwas anderes vereinbart haben, als unmittelbare Verweisung auf die Sachvorschriften dieses Staates und nicht auf sein Kollisionsrecht zu verstehen. (2) Haben die Parteien die anwendbaren Rechtsvorschriften nicht bestimmt, so hat das Schiedsgericht das Recht des Staates anzuwenden, mit dem der Gegenstand des Verfahrens die engsten Verbindungen aufweist. (3) <sup>1</sup> Das Schiedsgericht hat dann nach Billigkeit zu entscheiden, wenn die Parteien es ausdrücklich dazu ermächtigt haben. <sup>2</sup> Die Ermächtigung kann bis zur Entscheidung des Schiedsgerichts erteilt werden. (4) In allen Fällen hat das Schiedsgericht in Übereinstimmung mit den Bestimmungen des Vertrages zu entscheiden und dabei bestehende Landesbräuche zu berücksichtigen.
= § 1052 (ZPO) Entscheidung durch ein Schiedsrichterkollegium.=
= § 1053 (ZPO) Vergleich.=
= § 1054 (ZPO) Form und Inhalt des Schiedsspruchs.=
= § 1055 (ZPO) Wirkungen des Schiedsspruchs.=
= § 1056 (ZPO) Beendigung des schiedsrichterlichen Verfahrens.=
bbuc6fplbmbh3wv7y55f7af28nayd3v
Traktorenlexikon: Bucher D 4000
0
116703
1090833
1041369
2026-09-14T12:45:14Z
~2026-49967-62
116880
/* Steuergeräte */
1090833
wikitext
text/x-wiki
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Bucher |HERSTELLER= Bucher}}
{{:Traktorenlexikon: Modell-Infobox
| HERSTELLER = BUCHER-GUYER
| MODELLREIHE = D
| MODELL = 4000
| BILD = Bucher D4000.jpg
| BILDBESCHREIBUNG = Bucher D 4000
| BAUWEISE = Blockbauweise
| PRODUKTIONSBEGINN = 1959
| PRODUKTIONSENDE = 1967
| STÜCKZAHL = ca. 1.000
| EIGENGEWICHT = 1.495
| LÄNGE = 2.870
| BREITE = 1.580
| HÖHE = 1.440
| RADSTAND = 1.908
| BODENFREIHEIT = 430
| SPURWEITE = 1.320 / 1.420
| SPURWEITE VORNE =
| SPURWEITE HINTEN =
| WENDERADIUS MIT LENKBREMSE = 2.825
| WENDERADIUS OHNE LENKBREMSE = 3.150
| BEREIFUNG VORNE = 6.00-16 ASF
| BEREIFUNG HINTEN = 10-28 AS
| LEISTUNG KW = 27,9
| LEISTUNG PS = 38
| NENNDREHZAHL = 2.800
| ZYLINDER = 4
| HUBRAUM = 2.010
| DREHMOMENTANSTIEG =
| KRAFTSTOFF = Diesel
| KÜHLSYSTEM = Luftkühlung
| ANTRIEBSTYP = Heckantrieb
| GETRIEBE = 5 V/1 R oder 6 V/1 R
| HÖCHSTGESCHWINDIGKEIT = 20
| KATEGORIESORTIERUNG =
}}
Der D 4000 war ein Modell aus der erfolgreichsten Generation der Bucher Traktoren. Der luftgekühlte MWM-Motor wurde von den Verkäufern mit "Luft siedet nicht, Luft gefriert nicht." beworben. Beim Triebwerk waren offensichtlich 5 Vorwärts- und 1 Rückwärtsgang, aber auch 6 Vorwärts- und 1 Rückwärtsgang möglich. Bei beiden Varianten konnte die Ganganzahl mittels Reduktionsgetriebe verdoppelt werden.
==Motor==
* MWM, Typ: AKD-10 V, stehender luftgekühlter Viertakt-Vierzylinder-Reihen-Dieselmotor mit Vorkammerverfahren, BOSCH-Einspritzpumpe, Druckumlaufschmierung mittels Zahnradpumpe, hängende Ventile, untenliegende Nockenwelle, hand- und fußverstellbarer Drehzahlregler, fünffach-gelagerte Kurbelwelle, Ölbadluftfilter, Fünfring-Leichtmetallkolben, Spaltfilter und Axialgebläse.
* Nennleistung = 38 Brems-PS bei 2.800 U/min.
* Steuer-PS = 10,24
* Bohrung = 80 mm, Hub = 100 mm
* Verdichtungsverhältnis = 20:1
* Öldruck = 3,43 bis 3,92 bar
* Max. Einspritzdruck = 125 atü
* BOSCH-Einspritzdüse, Typ: DN 0 SD 126
==Kupplung==
* Pedal-betätigte, trockene Einscheibenkupplung
==Getriebe==
* Im Ölbad laufendes BUCHER-GUYER-Triebwerk
* Optional mit sechstem Gang, als Kriechgang ausgebildet
* Auf Wunsch mit Reduktionsgetriebe zur Verdoppelung der Ganganzahl (4,75:1)
5 Vorwärts- und 1 Rückwärtsgang bzw. 10 Vorwärts- und 2 Rückwärtsgänge
"Oder mit Kriechgang:"
6 Vorwärts- und 1 Rückwärtsgang bzw. 12 Vorwärts- und 2 Rückwärtsgänge
==Geschwindigkeiten vor- und rückwärts==
"Geschwindigkeiten mit Bereifung 10-28 AS"
{| class="wikitable"
|-
! bei Motordrehzahl (U/min) !! 2.800
|-
| 1.Gang || 4,10 km/h
|-
| 2.Gang || 7,28 km/h
|-
| 3.Gang || 10,60 km/h
|-
| 4.Gang || 16,30 km/h
|-
| 5.Gang || 20,00 km/h
|-
| Rückwärtsgang || 3,5 km/h
|-
|}
==Zapfwelle==
* Mechanisch-betätigte, kupplungsabhängige Getriebezapfwelle, als Wegzapfwelle schaltbar
* Stummel = 1 3/8"
* Einfach schaltbar, 540 U/min.
* 540 U/min. bei 2.845 U/min.- Motordrehzahl
* Seitlicher Mähantrieb
Drehzahl = 1.082 U/min.
==Bremsen==
* Pedal-betätigte Scheibenbremse auf die Ritzelwelle wirkend, als Einzelradbremse ausgebildet
* Feststellbare Handbremse auf die Ritzelwelle wirkend
==Achsen==
* Pendelnd-gelagerte Vorderachse
Zwei Spurweiten mittels Radumschlag = 1.320 und 1.420 mm
* Starre Hinterachse mit Kegelradgetriebe, Ritzel, Tellerrad und Stirnraduntersetzung
* Mechanisch-betätigte Differentialsperre
Zwei Spurweiten mittels Radumschlag = 1.320 und 1.420 mm
* Vordere Achslast = 545 kg
* Hintere Achslast = 950 kg
==Lenkung==
* Mechanisch-betätigte Einzelradlenkung
==Hydrauliksystem und Kraftheber==
* Optional mit hydraulischem Kraftheber mit Dreipunktaufhängung
==Steuergeräte==
Nachrüstbar
==Elektrische Ausrüstung==
* 12 Volt-Einrichtung
* Batterie, Lichtmaschine, Anlasser, Vorglühanlage, Scheinwerfer mit Dauerabblendung sowie Parklicht, hinten links und rechts Schlusslicht, Horn
==Maße und Abmessungen==
* Länge über alles = 2.870 mm
* Breite je nach Spurweite = 1.580 oder 1.700 mm
* Höhe über Lenkrad = 1.440 mm
* Höhe über Mähbalken = 2.130 mm
* Radstand = 1.904 mm
* Bodenfreiheit unter der Vorderachse = 430 mm
* Betriebsgewicht = 1.495 kg, mit Hydraulik = 1.595 kg
==Bereifung==
"Standardbereifung"
* Vorne = 6.00-16 AS Front
* Hinten = 10-28 AS (Hochradvariante = 8-32 AS)
==Füllmengen==
==Verbrauch==
==Kabine==
* Fahrerstand mit gefederter Sitzschale, Lade- und Öldruckanzeige, Traktormeter, Temperaturanzeige und beidseitigem Kotflügelsitz
* Optional mit Sitzkissen für Fahrer und Beifahrer und Leichtverdeck
==Sonderausrüstung==
* Mähbalken
* Hydraulischer Kraftheber
* Dreipunktaufhängung
* Zusatzgewicht (75 kg)
* Leichtverdeck
==Literatur& Weblinks==
* {{Literatur | Autor=Sascha Jussen | Titel=Der Stolz der Eidgenossen – Bucher D 4000
| Sammelwerk=Traktor Classic| Nummer=6/2023 Oktober November | Verlag=GeraMond Verlag GmbH | Ort=München | Seiten=70-74}}
* buchertraktoren.ch [http://www.buchertraktoren.ch/d4000_01.php Bucher D4000]
* typenscheine.ch [https://typenscheine.ch/de/Info/2984-BUCHERD4000 2984-Bucher D4000 1959]
* typenscheine.ch [https://typenscheine.ch/de/Info/3904-BUCHERD4000 3904-Bucher D4000 1962]
<references />
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Bucher |HERSTELLER= Bucher}}
25k3giopi9roq7rjx78mcdh5cxf04ay
Programmieren in C/C++: Grundlagen
0
118048
1090839
1090831
2026-09-15T05:58:28Z
D. Justen
102048
Gelöschte Navigation wieder eingefügt
1090839
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Toolchain/Entwicklungsumgebung
|zurücktext=Toolchain/Entwicklungsumgebung
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: Datentypen
|vortext=Datentypen}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C/C++ beinhaltet mehrere Sprachen/ Syntaxen:
* C-Syntax
* Präprozessor-Syntax
* Printf/Scanf Formatstring Syntax
* Terminal Emulation
* Compiler/Linker Anweisungen
Letztere beiden werden nur rudimentär in dieser Vorlesung/diesem Skript behandelt. Alle anderen sind Bestandteil dieser Vorlesung.
In diesem Kapitel sollen zunächst allgemeine Eigenschaften der Sprache, der grundlegende Syntax und die Kontrollstrukturen erklärt werden. Bei vielen Erklärungen sind Code-Beispiele vorhanden. Da man aus Fehlern am meisten lernt, sind zum Teil auch negative Beispiele enthalten. Für ein besseres Verständnis empfiehlt es sich, Code-Beispiele selbst nachzuvollziehen.<br />
Sofern sich die Eigenschaften auf eine bestimmte C-/C++- oder Compiler-Version beziehen, wird dies gesondert vermerkt.
== Zeichensatz ==
Der Syntax von C nutzt die unteren 128 Zeichen des ASCII Zeichensatzes. Da UTF-8 in den ersten 128 Zeichen deckungsgleich zu ASCII ist, kann auch dieser zur Erstellung des Source Codes genutzt werden.
Zeichen außerhalb dieses gültigen Zeichensatzes können folglich nur in Strings oder Kommentaren vorkommen. Werden Zeichen außerhalb der unteren 128 Zeichen in Strings genutzt, so gilt Folgendes zu berücksichtigen:
* Die String-Funktionalitäten der Standard-C Library gehen von dem regulären ASCII Zeichensatz aus, so dass z.B. die Suche, der Vergleich oder die Konvertierung fehlschlagen kann
* Strings werden oftmals in Verbindung mit printf() genutzt, d.h. auf der Standardausgabe ausgegeben. Der verwendete Zeichensatz sollte hier identisch zum verwendeten Zeichensatz der Terminal-Emulation sein!
== Kommentarzeichen ==
Kommentare dienen dazu, den Source Code mit zusätzlichen Hinweisen zu versehen, so dass die Intension der Anweisungen sichtbar wird. Kommentarzeichen werden durch den Compiler vor dem eigentlichen Übersetzungsdurchlauf entfernt und durch ein Leerzeichen ersetzt [C11 6.4.9]. Innerhalb von Strings wird nicht nach Kommentarzeichen gesucht.
<code>
Syntax: /* */
</code>
Blockkommentar zum Kommentieren eines Bereiches, auch über mehrere Zeilen hinweg. Dieses Kommentarzeichen kann nicht verschachtelt werden, d.h. '*/' beendet die Kommentierung, unabhängig von der Anzahl der zuvor geöffneten Kommentierungen!
<code>
Syntax: //
</code>
Zeilenkommentar zum Kommentieren bis zum Zeilenende (wurde in der Programmiersprache BCPL definiert, aber nicht von C, sondern erst von C++ übernommen).
Sollen größere Bereiche auskommentiert werden, so empfiehlt sich die Nutzung der Präprozessoranweisung #if 0 ... #endif.
Beispiele:
<syntaxhighlight lang="C">
/* Blockkommentar mit zwei öffnenden Klammern /*
über mehrere Zeilen, nicht verschachtelt */
//Zeilenkommentar
/* Kleiner Bereich zum auskommentieren */
#if 0
Großer Bereich zum auskommentieren
#endif
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
/* Blockkommentar mit zwei öffnenden Klammern /*
über mehrere Zeilen, nicht verschachtelt
Compiler-Warning nur aufgrund des Compiler-Schalters -Wall! */
//Zeilenkommentar
/* Kleiner Bereich zum auskommentieren */
#if 0
Großer Bereich zum auskommentieren
#endif
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Namenskonventionen ==
Folgende Regeln gelten bzgl. der Benennung von Variablen und Funktionen:
* Variablen und Funktionsnamen können aus Buchstaben, Zahlen und dem Unterstrich bestehen. Sie müssen mit einem Buchstaben oder einem Unterstrich beginnen
* Seit C95 können weitere Zeichen aus dem Universal Coded Character Set (UCS) genutzt werden [C11 D.1]
* C ist Case sensitiv, d.h. es wird zwischen Groß- und Kleinbuchstaben unterschieden
* Schlüsselwörter können nicht für Variablen/Funktionsnamen/Datentypen genutzt werden
Namenskonventionen von Libraryfunktionen:
* In C (und C++) sind Schlüsselwörter und Standardlibraryfunktionen zumeist in Kleinbuchstaben geschrieben. In der C-Standardlibrary werden oftmals verkürzte Ausdrücke (z.B. isalnum() (zum Testen ob ein Zeichen ein Buchstaben oder ein Digit ist) und in C++ der Unterstrich als Worttrenner (z.b. out_of_range) genutzt
* Makros (siehe Kap.[[Programmieren in C/C++: Präprozessor | Präprozessor]]) werden per Konvention in GROSSBUCHSTABEN und ggf. mit Unterstrich als Worttrenner geschrieben.
* Namen beginnend mit doppelten Unterstrich oder beginnend mit einem Unterstrich gefolgt von einem Großbuchstaben (z.B. __LINE__ _Reserved) sind für den Compiler und der Standard-C-Library vorbehalten und sollten im eigenen Programm nicht benutzt werden.
== Zeilenfortsetzung ==
Mit dem Backslash Operator (gefolgt von einem Zeilenende) kann eine Zeile in der nächsten Zeile fortgesetzt werden. Der Compiler löscht das \-Zeichen mit anschließendem Zeilenende und ersetzt dies durch nichts. Dies ist insbesondere bei Anweisungen notwendig, die am Ende der Zeile abgeschlossen sein müssen (z.B. Strings, Makros).
Beispiele:
<syntaxhighlight lang="c">
char str1[]="Strings müssen am Ende abgeschlossen sein
so dass dies ein Fehler ist";
char str2[]="Dies\
ist ein Test"; //Vorsicht, führende Leerzeichen vor 'ist'
//bleiben erhalten!
/*mehrzeiliges Makro*/
#define MAX(a,b) (a>b?\
b: \
a)
//Dies ist ein Zeilenkommentar \
welcher in dieser Zeile fortgesetzt wird
/\
* dies ist ein Blockkommentar*\
/
//hinter der Zeilenfortsetzung darf nur ein CR/LF folgen
#define MAX2(a,b) \ //so dass hier kein Kommentar folgen darf
a>b?a:b
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
char str1[]="Strings müssen am Ende abgeschlossen sein
so dass dies ein Fehler ist";
char str2[]="Dies\
ist ein Test"; //Vorsicht, führende Leerzeichen vor 'ist'
//bleiben erhalten!
/*mehrzeiliges Makro*/
#define MAX(a,b) (a>b?\
b: \
a)
//Dies ist ein Zeilenkommentar \
welcher in dieser Zeile fortgesetzt wird
/\
* dies ist ein Blockkommentar*\
/
//hinter der Zeilenfortsetzung darf nur ein CR/LF folgen
#define MAX2(a,b) \ //so dass hier kein Kommentar folgen darf
a>b?a:b
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Innerhalb von Char-Literatoren und Strings wird '\' als Escape-Operator genutzt, welche das '\' und ein oder mehrere folgende Zeichen ersetzt (siehe Kap.[[Programmieren in C/C++: Grundlagen#Literale/Konstanten | Grundlagen:Literale/Konstanten]]). Daher darf hinter Backslash als Zeilenfortsetzungszeichen kein weiteres Zeichen folgen.
== Gültigkeit/Sichtbarkeit von Variablen ==
Vorrangig in der objektorientierten Programmierung werden mit Namensräumen Objekte und deren Methoden/Attribute in einer Art Baumstruktur strukturiert. Dies ermöglicht eine eindeutige Ansprache von Variablen/Objekte, aber auch eine doppelte Verwendung von Methoden-/Attributnamen in unterschiedlichen Namensräumen. Ergänzend zu den Namensräumen kann mit public/private/proteced eine Zugriffsbeschränkung von Methoden/Attributen definiert werden.
Die Programmiersprache C unterstützt keinen Namensraum. Zugriffsmodifikatoren werden indirekt über Header-Dateien getätigt. Hinsichtlich der Gültigkeit/Sichtbarkeit unterscheidet C folgende Bereiche [C11 6.2.1]:
* Funktionen (Function Scope)
* Datei (File Scope)
* Block (Block Scope)
* Funktionsparameter in Prototypen (Function Prototype Scope)
Innerhalb eines Gültigkeitsbereiches dürfen Variablen-/Funktions-/Datentypnamen nicht doppelt genutzt werden.<br />
In der Programmiersprache C++ sind weitere Scope wie z.B. Class Scope, Enumationation Scope und ergänzend das Konzept von Namensräumen vorhanden (Beschreibung folgt).
=== Funktionsweite Sichtbarkeit ===
Eine Label-Definition (als Sprungmarke für die goto-Anweisungen) erfolgt immer mit funktionsweiter Sichtbarkeit/Gültigkeit. Die genaue Beschreibung dieses Sichtbarkeitstyps erfolgt im Rahmen des Kapitels [[Programmieren in C/C++: Grundlagen #Label + Goto|Grundlagen:Label+Goto]].
=== Dateiweite Sichtbarkeit ===
Erfolgt eine Funktion-/Variablen-/Datentyp-Definition außerhalb eines Block-Scopes oder von Funktionsparameter, so sind diese innerhalb der gesamten Datei und bei Funktionen/Variablen ergänzend Projektweit (für alle Objektdateien) sichtbar/gültig (= global) (In der C-Spec unter dem Stichwort 'Linkage' beschrieben, siehe Kapitel [[Programmieren in C/C++: DatentypeSpecifier#Internal/External Linkage| DatentypeSpecifier:Internal/External Linkage]]). Alle globalen Funktionen/Variablen können von allen Dateien aus genutzt/zugegriffen werden (sofern sie zuvor deklariert wurden).<br />
Beispiel:
{| class="wikitable"
|-
! Datei1.c !! Datei2.c
|-
| <syntaxhighlight lang="C">
//Deklaration von func(),
//welche in Datei2.c definiert wird
extern void func(void);
//Definition der Variablen global
int global=0;
int main(void) {
func();
global++;
return 0;
}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
//Deklaration von global,
//welche in Datei1.c definiert wird
extern int global;
//Definition der Funktion func()
void func(void) {
global++;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//Deklaration von func(),
//welche in Datei2.c definiert wird
extern void func(void);
//Definition der Variablen global
int global=0;
int main(void) {
func();
global++;
printf("global=%d\n",global);
return 0;
} | datei2_c=#include <stdio.h>
//Deklaration von global,
//welche in example.c definiert wird
extern int global;
//Definition der Funktion func()
void func(void) {
global++;
printf("func() called\n");
} | execCompilerOptions=-Wall datei2.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird das Schlüsselwort 'static' der Variablen/Funktionsdefinition vorangestellt, so wird die Sichtbarkeit/Gültigkeit auf Dateiweit eingeschränkt. Variablen/Funktionen können nur innerhalb der (Objekt-) Datei genutzt werden und sind für anderen (Objekt-)Dateien unsichtbar. (Siehe Kap. [[Programmieren in C/C++: DatentypeSpecifier#Internal/External Linkage|DatentypeSpecifier:Internal/External Linkage]] Internal/External Linkage)
{| class="wikitable"
|-
! Datei1.c !! Datei2.c
|-
| <syntaxhighlight lang="C">
//Dateiweite Sichtbarkeit von var1
static int var1;
int main(void) {
var1++;
return 0;
}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
//Dateiweite Sichtbarkeit von var1
static int var1;
void func(void) {
static int var2; //Vorsicht, static
// hat hier eine andere Bedeutung
var1++;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//Dateiweite Sichtbarkeit von var1
static int var1;
int main(void) {
var1++;
printf("example.c:var1=%d\n",var1);
void func(void); //Prototyp für func()
func();
return 0;
} | datei2_c=#include <stdio.h>
//Dateiweite Sichtbarkeit von var1
static int var1;
void func(void) {
static int var2; //Vorsicht, static
// hat hier eine andere Bedeutung
var1++;
printf("datei2.c:var1=%d\n",var1);
} | execCompilerOptions=datei2.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Projektweite Gültigkeit bedeutet insbesondere, dass keine doppelten Benennung von Variablen/Funktionen/Datentypen innerhalb des gesamten Projektes erlaubt sind, d.h. alle Variablen/Funktionennamen über alle Dateien/Librarys eindeutig sein müssen.<br>
Beispiel 1:
{| class="wikitable"
|-
! Datei1.c !! Datei.2
|-
| <syntaxhighlight lang="C">
#include <stdio.h>
int a=1;
int main(int argc,char *argv[])
{
printf("Hello World %d",a);
void dummy(void); //Deklaration von Dummy
dummy();
return 0;
}</syntaxhighlight>
|| <syntaxhighlight lang="C">
#include <stdio.h>
int a=7;
void dummy(void)
{
printf("Hello Again %d\n",a);
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int a=1;
int main(int argc,char *argv[])
{
printf("Hello World %d",a);
void dummy(void); //Deklaration von Dummy
dummy();
return 0;
} | datei2_c=#include <stdio.h>
#include <stdio.h>
int a=7;
void dummy(void)
{
printf("Hello Again %d\n",a);
} | execCompilerOptions=datei2.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Linker meldet beim Zusammenfügen der Objekt-Dateien, dass die Variable a bereits woanders definiert sei (multiple definition of `a';)!
Beispiel 2:
<syntaxhighlight lang="C">
#include <stdio.h> //fuer printf() size_t stderr
int printf=7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int printf=7;
int main(int argc,char *argv[])
{
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hier meldet der Compiler eine Fehlermeldung, da das Symbol printf zu einen als Variable und zum anderen als Funktion (innerhalb der inkludierten Datei stdio.h beschrieben) genutzt wird ('printf' redeclared as different kind of symbol).
=== Blockweite Sichtbarkeit ===
Erfolgt eine Funktion-/Variablen-/Datentyp Definition innerhalb einer Funktion, als Funktionsparameter oder eines Blockes, so sind diese nur innerhalb des Blockes sichtbar/gültig (=Lokale Variable). Blöcke können verschachtelt sein, so dass das bei identischer Namensgebung innere Definitionen Vorrang haben. Ebenso haben Blockdefinitionen Vorrang vor Datei-/Projektdefinitionen (überdecken diese):
{| class="wikitable"
|-
! Datei1.c !! Datei2.c
|-
| <syntaxhighlight lang="C">
int main(void) {
int var2; //var2 ist nur innerhalb
//von main() sichtbar
struct xyz //Datentyp ist nur innerhalb
{int x,y,z;};//von main()
//sichtbar/gültig
extern void func(void); //Deklaration
//ist nur innerhalb von
//main() sichtbar/gültig
func();
}
void foo(void) {
struct xyz var_xyz; //Fehler, da
//Datentypedefinition hier nicht mehr
//gültig ist!
func(); //Fehler, da Deklaration
//hier nicht mehr gültig ist
}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
#include <stdio.h>
void func(void) {
int var2=1; //var2 ist
//nur innerhalb von
//func() sichtbar
{
int var2=2;
//var2 ist nur innerhalb
//dieses Blockes sichtbar
printf("%d\n",var2);
}
printf("%d\n",var2);
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(void) {
int var2; //var2 ist nur innerhalb
//von main() sichtbar
struct xyz //Datentyp ist nur innerhalb
{int x,y,z;};//von main()
//sichtbar/gültig
extern void func(void); //Deklaration
//ist nur innerhalb von
//main() sichtbar/gültig
func();
}
void foo(void) {
struct xyz var_xyz; //Fehler, da
//Datentypedefinition hier nicht mehr
//gültig ist!
func(); //Fehler, da Deklaration
//hier nicht mehr gültig ist
} | datei2_c=#include <stdio.h>
void func(void) {
int var2=1; //var2 ist
//nur innerhalb von
//func() sichtbar
{
int var2=2;
//var2 ist nur innerhalb
//dieses Blockes sichtbar
printf("%d\n",var2);
}
printf("%d\n",var2);
} | execCompilerOptions=-Wall datei2.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Sichtbarkeit von Funktionsparameter in Protypen ===
Soll eine Funktion aufgerufen werden, die zuvor nicht definiert wurde, so ist ein Prototyp/(Forward)deklaration der Funktion notwendig (siehe nachfolgendes Kapitel). Die Parameterliste dieses Prototyps hat seinen eigenen Gültigkeitsbereich.<br/>
Beispiel:
<syntaxhighlight lang="C">
int a; //a im File Scope
int func(int a, int b); //a und b im Function Prototyp scope
</syntaxhighlight>
Hinweis:
* Bei Prototypen ist die Angabe von Variablenname nicht notwendig. Die alleinige Angabe des Datentyps ist ausreichend
=== Zuordnung der Gültigkeitsbereiche zu globalen/lokalen Variablen ===
Zum einfacheren Verständnis wird im Skript von folgenden Begrifflichkeiten gesprochen:
* '''Globale''' Variablen-/Funktionen-/Datentypdefinitionen → Projektweite Sichtbarkeit/Gültigkeit
* '''Statisch globale''' Variable/Funktionen → Dateiweite Sichtbarkeit/Gültigkeit
* '''Lokale''' Variablen/Funktionen/Funktionsparameter/Datentypen → Nur innerhalb des zugehörigen Blockes sichtbare/gültig
* '''Statisch lokale''' Variablen → Nur innerhalb der Funktion sichtbar/gültig, mit der Besonderheit, dass die Gültigkeit über der Laufzeit der Funktion gilt (siehe Kap. [[Programmieren in C/C++: DatentypeSpecifier#Static Storage Class Specifier|DatentypeSpecifier:Static Storage Class Specifier]])
=== Speicherzuweisung ===
Für die einzelnen Gültigkeitsbereiche werden im Speicher (und auch in der Objekt-Datei) unterschiedliche Speicherbereiche (Segmente) vorgehalten, d.h. der Compiler teilt den Speicher in unterschiedliche Bereiche auf und weist den Variablen/Funktionen in Abhängigkeit der Gültigkeit/Sichtbarkeit unterschiedliche Speicherbereiche zu!
[[File:Zuordnung von Inhalten eines C-Programms zu Speicherbereichen (Segmenten).png|thumb|Zuordnung von Inhalten eines C-Programms zu Speicherbereichen (Segmenten)]]
Zur Ermöglichung von Rekursion werden lokale Variable auf dem Stack gehandelt. Mit Aufruf einer Funktion oder öffnen eines neuen Block-Scopes wird Speicher auf dem Stack reserviert, der bei Beenden des Scopes wieder freigegeben wird. Die Speicheradresse von lokalen Variablen ist somit nicht Fix, sondern hängt von der Aufrufhierarchie ab!
Globale und statisch globale Variablen werden nicht auf dem Stack gehalten, sondern bekommen einen 'festen' Speicherbereich (hier DATA/BSS/RODATA) während der gesamten Laufzeit des Programms zugewiesen. Die Adresse dieser Variablen sind somit konstant. Das genutzte Speichersegment von globalen Variablen hängen von der Art der Variablen ab. Initialisierte Variablen werden im DATA-Segment gesammelt, welcher mit dem Initialisierungswert der Variablen initialisiert wird. Nicht initialisierte globale Variablen landen im BSS-Segment, so dass diese mit Programmstart durch Füllen dieses Blockes mit 0 auf 0 gesetzt werden.
Konstante globale Variablen werden im RODATA-Segment gehalten. Über das Betriebssystem kann dieser Speicherbereich auf nur Lesbar gesetzt werden.
Dynamische Speicheranforderungen, resp. Speicher, dessen Gültigkeit über die Laufzeit einer Funktion hinausgeht, wird im Heap gesammelt. Für die Verwaltung dieses Speichers ist der Programmierer zuständig.
Entsprechend globalen Variablen wird für Funktionen ebenfalls ein eigener Speicherbereich (TEXT Segment) vorgesehen. Im Gegensatz zu Variablen, wo im Speicher der dazugehörige Inhalt gespeichert ist, ist der Speicherinhalt von Funktionen die Maschinenanweisungen. Die Speicheradresse der Funktionen sind konstant.
Hinweis:
* Die Speicheradresse von sowohl globalen und statisch globalen Variablen als auch von Funktionen ist konstant und ändert sich während der Laufzeit des Programms nicht. Die Adressvergabe dieser Variablen und Funktionen erfolgt somit nicht zur Laufzeit sondern durch die Toolchain (hier der Linker).
* Dieses Konzept ist allgemeingültig, gilt nicht nur für die Programmiersprache C/C++
== Definition/Deklaration(Prototyp) ==
Der C-Compiler ist ein Single-Pass Compiler (siehe Kap [[Programmieren in C/C++: Einführung/Literatur#Arbeitsweise eines Compilers | Einführung/Literatur:Arbeitsweise eines Compilers ]]), d.h. für den Übersetzungsvorgang wird der Quellcode einmalig eingelesen und von vorne nach hinten abgearbeitet. Dies bedingt, dass keine Vorwärtsbezüge im Quelltext enthalten sein dürfen:
* keine Variable genutzt werden kann, die erst später definiert wird (da der Compiler in Abhängigkeit des Datentyps (den er dann noch nicht kennt) keine entsprechende Maschinensprachebefehle erzeugen kann)
* keine Funktion aufgerufen werden kann, die erst später definiert wird (da der Compiler nicht weiß, welcher Datentyp die Übergabewerte haben und folglich keine Maschinensprachebefehle zur Konvertierung und Übergabe der Variablen erzeugen kann)
* kein Datentyp genutzt werden kann (struct, union, enum, typedef), welcher erst später definiert wird (da der Compiler nicht weiß, wieviel Speicher er für die Variable reservieren muss)
Eine Lösungsvariante dieser Problematik ist, im Quellcode alle Variablen/Funktionen/Datentypen/Makros zu definieren, bevor diese erstmalig genutzt werden (Funktion main() steht dann folglich am Ende des Quellcodes):
<syntaxhighlight lang="C">
void foo(void) { //foo() wird vor dem ersten Aufruf definiert
//Hier kein Zugriff auf var möglich!
//Hier kein Zugriff auf Datentyp uchar möglich!
}
int var; //var wird vor dem ersten Aufruf definiert
typedef unsigned char uchar; //Definition des Datentyps uchar
int main(void) {
foo(); //da zuvor definiert kann diese Funktion hier aufgerufen werden
var++; //dito
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void foo(void) { //foo() wird vor dem ersten Aufruf definiert
var++; //Hier kein Zugriff auf var möglich!
uchar xyz;//Hier kein Zugriff auf Datentyp uchar möglich!
}
int var; //var wird vor dem ersten Aufruf definiert
typedef unsigned char uchar; //Definition des Datentyps uchar
int main(int argc, char *argv[]) {
foo(); //da zuvor definiert kann diese Funktion hier aufgerufen werden
var++; //dito
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Sollen globale Funktionen/Variablen in Datei1.c genutzt werden, die in Datei2.c definiert sind, so schlägt diese Vorgehensweise fehl. Um auch dieses zu ermöglichen, bietet C die Möglichkeiten von Prototypen/Deklarationen an. Diese teilt dem Compiler mit, wie im späteren Ablauf die Variable, die Funktion definiert wird, bzw. dass es diesen Datentyp geben wird:
{| class="wikitable"
|-
! Datei1.c !! Datei2.c
|-
| <syntaxhighlight lang="C">
//Prototyp für Variable var
extern int var;
//Prototyp für Funktion foo
void foo(void);
int main(int argc, char *argv[]) {
foo(); //Compiler kann aufgrund
var++; //der Prototypen diese
//Aufruf in Maschinen-
//sprachebefehle umsetzen
}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
//Definition der Variablen var
int var;
//Definition der Funktion foo
void foo(void) {
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//Prototyp für Variable var
extern int var;
//Prototyp für Funktion foo
void foo(void);
int main(int argc, char *argv[]) {
foo(); //Compiler kann aufgrund
var++; //der Prototypen diese
//Aufruf in Maschinen-
//sprachebefehle umsetzen
} | datei2_c=#include <stdio.h>
//Definition der Variablen var
int var;
//Definition der Funktion foo
void foo(void) {
} | execCompilerOptions=-Wall datei2.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der C-Spezifikation werden für den Umgang mit dieser Problematik die Begriffe 'Declaration' und 'Definition' genutzt. Da diese Begriffe jedoch nicht klar abgegrenzt werden und auch für viele weitere Aspekte genutzt werden, sollen in diesem Skript in Anlehnung an den Wikipedia Artikel {{w|Deklaration (Programmierung)|Deklaration (Programmierung)}} (im Absatz zur Programmiersprache C/C++) die Begriffe Definition/Deklaration wie folgt genutzt werden:
;Definition: entspricht der Belegung/Reservierung von Speicherplatz
:* Bei der Definition einer Variablen wird hiermit Speicherplatz entsprechend dem Datentyp der Variable belegt:
:<syntaxhighlight lang="C">
int var1; //entsprechend der Größe des Datentyps int wird
//Speicherplatz für die Variable var1 reserviert
int var2=4711; //Dito, ergänzend wird dieser Speicherplatz mit dem
//Wert 4711 initialisiert
</syntaxhighlight>
:* Bei einer Funktion wird Speicherplatz zur Aufnahme der Maschinenbefehle belegt:
:<syntaxhighlight lang="C">
void foo(void) { //Die Anweisungen in den geschweiften Klammern
//werden in Maschinenbefehle übersetzt. D.h. die
//Funktion foo() belegt Speicher, dessen Inhalt
//die Maschinensprachebefehle sind
}
</syntaxhighlight>
:* Ergänzend wird der Begriff Definition auch in Verbindung mit der Definition von neuen Datentypen genutzt!
;Deklaration/Prototyp: ist die Mitteilung an den Compiler, wie diese Variable/Funktion an einer späteren Stelle im Source-Code oder in einer anderen Source-Datei definiert wird. Auf Grundlage dieser 'vorab' Information kann der Compiler die passenden Maschinensprachebefehle für den Zugriff/Aufruf auf die Variablen/Funktion einsetzen:
:<syntaxhighlight lang="C">
extern int var1; //Deklaration von var1
extern void foo(void); //Deklaration von foo()
void foo(void); //Deklaration von foo()
</syntaxhighlight><br />
Insbesondere bei dem Umgang mit der Deklaration gilt es Folgendes zu berücksichtigen:
* Deklarationen werden entweder:
:* am Anfang einer C-Datei geschrieben, so dass Funktionen/Variablen im Zugriff stehen, die erst später in der C-Datei definiert werden (entspricht dann der Private Anweisung in anderen Sprachen)
:* in Header-Dateien geschrieben, so dass diese Variable/Funktionen für alle sichtbar sind, welche diese Header-Datei einbinden (entspricht der Public Anweisung in anderen Sprachen)
* Deklarationen von Funktionen werden in der C-Spec als (function) Prototyp bezeichnet und sind dadurch gekennzeichnet, dass diese mit einem Semikolon abgeschlossen sind. Der Specifier 'extern' ist hier optional und sagt eigentlich aus, dass diese Funktion external Linkage besitzt (siehe [[Programmieren in C/C++:_DatentypeSpecifier#Internal/External Linkage | DatentypeSpecifier:Internal/External Linkage]]). Die Benennung der Parametervariablen sind gleichermaßen optional:
:<syntaxhighlight lang="C">
extern int foo(int var1, float var2); //Deklaration
extern int foo(int , float ); //Deklaration
int foo(int var1, float var2); //Deklaration + external Linkage
int foo(int , float ); //Deklaration + external Linkage
</syntaxhighlight>
* Für globale Variablen gibt es keine (Variablen) Prototype. Stattdessen muss zur Bekanntgabe des Datentyps der Specifier 'extern' vorangestellt werden, mit welchen ergänzend zum Ausdruck gebracht wird, das diese Variable external Linkage und damit globale Gültigkeit hat (siehe Kap [[Programmieren in C/C++: DatentypeSpecifier# Extern - Storage Class Specifier| DatentypeSpecifier:Extern - Storage Class Specifier]]). Da die Deklaration einzig zur Bestimmung der Zugriffsmethoden auf Maschinenspracheebene genutzt wird, können diese keine Initialisierungswerte enthalten:
:<syntaxhighlight lang="C">
extern int var1;
extern int var2=7; //KO Deklarationen können keine
//Initialisierungswerte haben
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
extern int foo;
extern int foo=7;
int main(int argc, char *argv[]) {
return foo;
}
int foo=7;| execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Deklarationen von statisch globalen, lokalen und statisch lokalen Variablen nicht möglich sind:
:<syntaxhighlight lang="C">
extern static int glob; //keine Deklaration von statisch globalen
//Variablen möglich
int main(int argc, char *argv[]) {
extern int var; //Deklaration bezieht sich auf eine globale
//Variable, die nicht definiert ist
extern static int lok;
printf("%d %d\n",var,lok);
int var;
static int lok;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
extern static int glob; //keine Deklaration von statisch globalen
//Variablen möglich
int main(int argc, char *argv[]) {
extern int var; //Deklaration bezieht sicht auf eine globale
//Variable, die nicht definiert ist
extern static int lok;
printf("%d %d\n",var,lok);
int var;
static int lok;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Deklarationen für identische Variablen/Funktionen können beliebig oft erfolgen, sofern der Datentyp identisch ist:
:<syntaxhighlight lang="C">
extern int var;
extern int var; //OK, doppelt Deklaration mit identischen Datentyp
extern unsigned int var; //KO, Doppelte Deklaration mit unterschiedlichen
// Datentyp
</syntaxhighlight>
* Sofern eine Deklaration und eine Definition in der identischen Datei erfolgen überprüft der Compiler, ob Deklaration und Definition identisch sind. Es empfiehlt sich, die eigene Header-Datei (in welcher die Deklaration normalerweise enthalten ist) zu inkludieren:
:{| class="wikitable"
|-
! Datei1.c !! Datei1.h
|-
| <syntaxhighlight lang="C">
//Include der eigenen Header-Datei
#include "datei1.h"
int var1; //Definition von var1
short var2; //Definition von var2
int var3; //Private Variable
//da kein Prototyp
//im Header vorhanden
void func(void) {
}
</syntaxhighlight> ||
<syntaxhighlight lang="C">
extern int var1; //Deklaration
extern char var2; //KO, da Deklaration
//von Definition
//abweicht
void func(int); //KO, da Deklaration
//von Definition
//abweicht
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//Include der eigenen Header-Datei
#include "example.h"
int var1; //Definition von var1
short var2; //Definition von var2
int var3; //Private Variable
//da kein Prototyp
//im Header vorhanden
void func(void) {
}
int main(int argc, char *argv[]) {
return 0;
} | example_h=
extern int var1; //Deklaration
extern char var2; //KO, da Deklaration
//von Definition
//abweicht
void func(int); //KO, da Deklaration
//von Definition
//abweicht
| execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Innerhalb einer Datei kann eine Variable identischen Datentyps mehrmals definiert werden (bei identischen Initialisierungswert). Diese Definitionen werden vom Compiler als eine Definition angesehen. Wenn jedoch eine identische Variable in unterschiedlichen Dateien definiert wird, so legt jede Datei eine eigene unabhängige Variable an, welche dann beim Zusammenführen der Objektdateien durch den Linker zu Fehler führt. Da Header-Datei zumeist in mehrere C-Dateien inkludiert werden, sind Definitionen in Header-Dateien 'verboten'.
* Deklarationen innerhalb eines Block-Scopes oder eines Function Prototyp Scopes sind nur in diesen Bereich gültig.
== Grundlegende Datentypen und Typsicherheit ==
Die Programmiersprache C kennt folgende grundlegende Datentypen (siehe Kap. [[Programmieren in C/C++: Datentypen | Datentypen]]). Von jedem Datentyp kann ein Zeiger angelegt werden:
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| Ganzzahl ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| Gleitkommazahl ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| Arrays ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| Strukturen/Unions ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| Aufzählungstyp ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| Boolescher Datentyp ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| Komplexe Zahlen ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
C/C++ unterscheidet zwischen vorzeichenbehafteten <code>signed</code> und vorzeichenlosen <code>unsigned</code> ganzzahligen Datentypen. Vorzeichenlose Datentypen können nur positive Zahlen incl. der 0 aufnehmen (Anwendungsbereich bspw. Speicheradressen/Arrayindexe, welche nicht negativ sein können). Deren max. Zahlenwert ergibt sich aus der Datenbreite N des Datentyps 2<sup>N</sup>-1. Ein Vergleich eines vorzeichenlosen Datentyps mit ≥ 0 ist somit immer TRUE:
<syntaxhighlight lang="C">
unsigned char var=0;
if(var >= 0) //Bedingung ist immer erfüllt, so dass
printf("Bedingung erfüllt"); //dieser ggf. vom Compiler wegoptimiert wird!
for(var=10; var>=0; var--); //Endlosschleife! 0 dekrementiert ergibt 255
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
unsigned char var=0;
if(var >= 0) //Bedingung ist immer erfüllt, so dass
printf("Bedingung erfüllt\n"); //dieser ggf. vom Compiler wegoptimiert wird!
//Beim Öfffnen des Compiler-Fensters ist die IF-Anweisung nicht farblich
//hervorgehoben. Dies bedeutet, dass diese Zeile wegoptimiert wurde und folglich
//kein Maschinencode für diese Anweisung erzeugt wurde
for(var=10; var>=0; var--) //Endlosschleife! 0 dekrementiert ergibt 255
printf("%u ",var),fflush(stdout);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Vorzeichenlose Datentypen halbieren den verfügbaren Zahlenbereich und 'weisen' dem oberen Wertebereich den negativen Zahlen zu.<br>
Wird ein ganzzahliger Datentyp ohne Angabe des Vorzeichentyps (signedness) definiert, so ist diese vorzeichenbehaftet. Bei vorzeichenlosen Variablen muss explizit <code>unsigned</code> vorangestellt werden. Die Voranstellung von <code>signed</code> ist optional. Einzige Ausnahme stellt der Datentyp char dar. Hier gibt die Spezifikation keine default signedness vor, so dass bei Nutzung dieses Datentyps zur Aufnahme von Zahlen immer signed oder unsigned vorangestellt werden sollte!<br>
Innerhalb des Formatstrings bei den printf()/scanf() Anweisungen '''muss''' die signedness vom Programmierer händisch berücksichtigt werden. Die Formatanweisung %d und %i interpretieren die übergebenen Zahl als vorzeichenbehaftete Zahl. Soll eine vorzeichenlose Zahl ausgegeben werden, so muss %u verwendet werden:
<syntaxhighlight lang="C">
signed int vari=-10;
unsigned int varu=3000000000;
printf("vari=%d varu=%u",vari,varu); //Korrekt
printf("vari=%u varu=%i",vari,varu); //Falsche Werteausgaben!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
signed int vari=-10;
unsigned int varu=3000000000;
printf("vari=%12d varu=%12u\n",vari,varu); //Korrekt
printf("vari=%12u varu=%12i\n",vari,varu); //Falsche Werteausgaben!
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit der Definition (dem Anlegen) einer Variablen eines Datentyps wird Speicher entsprechend der Größe des Datentyps reserviert. Optional kann dieser Speicher initialisiert werden. Über den Datentyp wird ausgesagt, wie der Inhalt des Speichers zu interpretieren ist:
<syntaxhighlight lang="C">
char var1; //Speicherplatzreservierung von 1 Byte
//Inhalt der Speicherstelle wird als Zahl interpretiert
//(Hinweis: ASCII-Zeichen sind Zahlen)
double var2=47.11; //Speicherplatzreservierung von 8 Byte
//Inhalt der Speicherstellen wird als Gleitkommazahl
//interpretiert (bestehend aus je einer Ganzzahl für
//Mantisse und Exponent)
short arr[10]; //Speicherplatzreservierung von 10*2 Byte
//Inhalt der 10 Speicherstellen werden als Ganzzahl
//interpretiert
</syntaxhighlight>
Die Funktionalität der Operatoren hängt vom Datentyp der Operanden ab. Der Plus-Operator angewendet auf ganzzahlige Operanden führt eine Ganzzahl Addition aus, angewendet auf gleitkomma Operanden eine Gleitkomma Addition. Ist einer der Operanden ein Zeiger, so wird eine Zeigeraddition angewendet. Für andere Datentypen ist der Plus-Operator nicht definiert, so dass der Compiler einen Fehler wirft. '''Bei der Betrachtung eines Ausdruckes sollte dem genutzten Datentypen folglich eine besondere Aufmerksamkeit zuteil werden''':
<syntaxhighlight lang="C">
int vari=47;
vari+12; //(int) + (int) → Ganzzahladdition
float varf=12.3;
3.1415F+varf; //(float) + (float) → Gleitkommaaddition
int *ptr=&vari;
ptr+3; //(int *) + (int) → Zeigeraddition
int arr[3];
arr+3; //(int (*)) + (int) → Zeigeraddition
</syntaxhighlight>
Das Ergebnis einer Operation hat ebenfalls einen Datentyp. Eine Ganzzahl Addition gibt bspw. als Ergebnis einen Ganzahl Datentyp zurück, eine Gleitkomma Addtition einen Gleitkomma Datentyp und ein Vergleichsoperator den Datentyp _Bool:
<syntaxhighlight lang="C">
int vari1=47;
int vari2=11;
vari1 + 12 + vari2; //((int)+(int)+(int))→((int)+(int))→(int)
40 < vari1 < 50; //((int)<(int)<(int))→((_Bool=int)<(int))→(_Bool=int)
</syntaxhighlight>
Wie Operatoren haben auch Funktionen Operanden (in Form von Übergabeparameter). Das Ergebnis eines Funktionsaufrufes wird ebenfalls in Form eines Datentyps zurückgegeben:
<syntaxhighlight lang="C">
float add(int par1,par2) {return par1+par2;}
int vari1=47;
int vari2=11;
vari1 + add(var2,12); //(int)+((int),(int)→(float))→(int)+(float)→(float)
</syntaxhighlight>
Wird auf einen Operator gleichermaßen ein vorzeichenbehafteter und ein vorzeichenloser Operand angewendet, so kann es zu unerwarteten Konvertierungsproblemen führen:
<syntaxhighlight lang="C">
unsigned char varu=12;
signed char vars=-12;
float varf;
varf = varu + vars;
if(vars < varu)
</syntaxhighlight>
Sind die Datentypen der Operanden nicht 'kompatibel', so 'passt' der Compiler die Datentypen im Falle von Ganzahl und Gleitkomadatentypen per impliziter Regel an (siehe Kap. [[Programmieren in C/C++: Datentypen#Implizite Typumwandlung | Datentypen:Implizite Typumwandlung]]). Über explizite Typumwandlung (siehe Kap.[[Programmieren in C/C++: Datentypen# Explizite Typumwandlung|Datentypen:Explizite Typumwandlung]]) kann ein Datentyp z.T. in einen anderen Datentyp gewandelt werden.
In allen anderen Fällen ist C Typsicher, d.h. der Compiler gibt zumindest eine Warning aus, wenn die Datentypen nicht identisch sind und der Compiler keine implizite Regel anwenden kann.
Tipp:
* Compiler gibt bei Fehlermeldung oftmals die erwarteten und die vorhandenen Datentyp an. Wenn solch eine Fehlermeldung kommt, sollten sie sich a) überlegen, was wollten sie syntaktisch geschrieben haben und b) was haben sie in der Tat geschrieben. Ein Google nach einer Lösung des Compilerproblems löst zumeist nicht das Problem, sondern umgeht es!
Hinweis:
* Ein guter Programmierer sollte die Datentypen so wählen, dass:
:* die Datentypen zum Inhalt und zum Wertebereiches passen
:* keine Datentypkonvertierungen notwendig sind
: andernfalls besteht die Gefahr, dass hiermit Laufzeitfehler einprogrammiert werden.
* Wenn Datentypkonvertierungen notwendig sind, sollte die explizite Konvertierung genutzt werden
== Abhängigkeiten bzgl. Rechnerarchitektur ==
Kenngrößen von Prozessoren sind unter anderem die Anzahl der Bits für den Datentransport und für Arithmetisch-/Logische-Operationen (→ Datenbreite) und die Anzahl der Bits für die Adressierung des Speichers (→ Adressierungsbreite). Die Datenbreite sagt dabei aus, welche max. Datenbreite ein Maschinenbefehl (zumeist in einem Taktzyklus) transportieren/berechnen kann. Werden programmtechnisch größere Datenbreiten benötigt, bedingt dies, dass hierzu mehrere Maschinenbefehle notwendig sind. Wenn kleinere Datenbreiten notwendig sind, so wird oftmals das Ergebnis abgeschnitten (sofern der Prozessor keine Befehle für den Umgang mit kleineren Datentyp beherrscht):
{| class="wikitable"
|-
! 32-Bit Datentransport/Operation<br /> bei 32-Bit Datenbreite
! 64-Bit Datentransport/Operation<br /> bei 32-Bit Datenbreite
! 16-Bit Datentransport/Operation<br /> bei 32-Bit Datenbreite
|-
| <syntaxhighlight lang="C">
int32_t a32,b32;
</syntaxhighlight>
|| <syntaxhighlight lang="C">
int64_t a64,b64;
</syntaxhighlight>
|| <syntaxhighlight lang="C">
int16_t a16,b16;
</syntaxhighlight>
|-
| <syntaxhighlight lang="asm">
// a32=b32;
mov eax,b32
mov a32,eax
</syntaxhighlight>
|| <syntaxhighlight lang="asm">
// a64=b64;
mov eax ,b64
mov edx ,b64+4
mov a64 ,eax
mov a64+4,edx
</syntaxhighlight>
|| <syntaxhighlight lang="asm">
//a16=b16;
movz eax,b16
mov a16,ax
</syntaxhighlight>
|-
| <syntaxhighlight lang="asm">
// a32=a32+b32;
mov edx, a32
mov eax, b32
add eax, edx
mov a32, eax
</syntaxhighlight>
|| <syntaxhighlight lang="asm">
// a64=a64+b64;
mov ecx , a64
mov ebx , a64+4
mov eax , b64
mov edx , b64+4
add eax , ecx
adc edx , ebx
mov a64 , eax
mov a64+4, edx
</syntaxhighlight>
|| <syntaxhighlight lang="asm">
// a16=16+b16;
movzx eax, a16
mov edx, eax
movzx eax, b16
add eax, edx
mov a16, ax
</syntaxhighlight>
|}
Die Adressierungsbreite gibt an, mit welcher Bitbreite der Speicher adressiert werden kann:
* Bei einem 32-Bit System können 2<sup>32</sup>=4.294.967.295=4Gi Bytes/Speicherstellen adressiert werden
* Bei einem 16-Bit System können 2<sup>16</sup>=65.536=64Ki Bytes/Speicherstellen adressiert werden
* Bei einem 64-Bit System können 2<sup>64</sup>=18.446.744.073.709.551.616 =16Ei ~18Exa Bytes/Speicherstellen adressiert werden
Waren die Datenbreite und die Adressierungsbreite bei den ersten Prozessoren noch unterschiedlich, so sind diese heutzutage zumeist identisch. Bei einem 32-Bit Prozessor bedeutet dies, dass dieser max. 4Gi Bytes Speicherstellenstellen adressieren kann und Maschinenbefehle für den Datentransport und die Berechnung von 32-Bit Datenworten beinhaltet.
Die Datenbreite und auch die Adressierungsbereite haben direkten Einfluss auf die Programmiersprache:
* Wird defaultmäßig mit größerer Datenbreite gerechnet, als der Prozessor 'von Hause' aus unterstützt, so werden die erzeugten Maschinenprogramme größer und langsamer (Umgedreht bedeutet dies jedoch nicht, dass die Maschinenprogramme kleiner und schneller werden)
* Die max. Größe von Verbunddatentypen und Arrays ergibt sich aus der Adressierungsbreite des Prozessors
Die Intention der Programmiersprache C/C++ ist, die Prozessorarchitektur optimal zu nutzen. Dementsprechend sind diverse Eigenschaften der Sprache nicht fest spezifiziert, sondern von der Rechnerarchitektur abhängig.
=== Integer Datentyp ===
Intention von C/C++ ist, dass der Umgang mit dem Grunddatentyp 'int' möglichst direkt in einen Maschinensprachebefehl umgesetzt werden kann.<br />
Bei einem 16-Bit Prozessor hat der Datentyp int daher eine Breite von 16-Bit und bei einem 32-Bit Prozessor eine Breite von 32-Bit (siehe Kap [[Programmieren in C/C++: Datentypen # Ganzzahlige Datentypen|Datentypen:Ganzahl Datentypen]]). Über vorangestellte Qualifier kann dieser Grunddatentyp verkleinert/vergrößert werden.
=== Integer Arithmetik ===
Ganzzahlen haben nur einen begrenzten Wertebereich. Wird dieser bspw. durch eine Addition überschritten (d.h. das Rechenergebnis benötigt zur Darstellung mehr Stellen, als der Datentyp 'hergibt'), so gibt es zwei Vorgehensweisen:
* Arithmetischer Überlauf (siehe {{w|arithmetischer Überlauf}}): Die nicht speicherfähigen Stellen werden verworfen, so dass i.d.R. ein falsches Ergebnis erzeugt wird!
:Beispiel:
:<syntaxhighlight lang="C">
unsigned char a=254,b=3,c;
c=a+b; //c ist (254+3)%256=1
c=a*b; //c ist (254*3)%256=250
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
unsigned char a=254,b=3,c1,c2;
c1=a+b; //c ist (254+3)%256=1
c2=a*b; //c ist (254*3)%256=250
printf("c1=%hhu c2=%hhu\n",c1,c2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Sättigungsarithmetik (siehe {{w|Sättigungsarithmetik}}): Alle Operationen laufen innerhalb eines festen Intervalls ab, so dass Überläufe und Unterläufe auf dieses Intervall begrenzt werden:
:Beispiel:
:<syntaxhighlight lang="C">
unsigned char a=254,b=3,c;
c=a+b; //c ist MAX((254+3),255)=255
c=a*b; //c ist MAX((254*3),255)=255
</syntaxhighlight>
Die Spezifikation von C macht bezüglich der zu nutzenden Methodik keine Vorgaben, so dass das Handling von der ALU des Prozessors abhängt. Aus Komplexitäts- und Geschwindigkeitsgründen ist dies zumeist der arithmetische Überlauf. Nur bei Spezialprozessoren (z.B. DSP Digital Signal Processor) kommt z.T. die Sättigungsarithmetik zum Einsatz.
=== Gleitkomma Datentyp und Arithmetik ===
Für den Umgang mit Gleitkommazahlen bieten einige Prozessoren spezielle Recheneinheiten ({{w|Gleitkommaeinheit}} Floating Point Units FPU) an. Sowohl die Darstellung von Gleitkommazahlen als auch das Verhalten bei Überlauf/Unterlauf ist damit Herstellerabhängig. Um auch diese Einheiten effektiv nutzen zu können, ist die C/C++ Spezifikation in diesem Bereich ebenfalls sehr offen.
=== Max. Speicherbedarf von Variablen ===
Die maximale Größe von Arrays/Strukturen/Unions ist in C/C++ von der zugrundeliegenden Rechnerarchitektur abhängig:
<syntaxhighlight lang="C">
char a[100000]; //Speicherbedarf=100.000*1Byte=100.000 Bytes
//Bei 16-Bit Architektur KO
//Ab 32-Bit Architektur OK
struct size_16 {
char a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_256 {
struct size_16 a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_4096 {
struct size_256 a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_65536 {
struct size_4096 a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_65536 var65536; //Speicherbedarf=65536 Bytes
//Bei 16-Architektur KO
//Ab 32-Architektur OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//Zur Darstellung bitte Compiler-Fenster öffnen
//und dort den CC65-Compiler für den 6502 Prozessor auswählen
char a[100000]; //Speicherbedarf=100.000*1Byte=100.000 Bytes
//Bei 16-Bit Architektur KO
//Ab 32-Bit Architektur OK
struct size_16 {
char a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_256 {
struct size_16 a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_4096 {
struct size_256 a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_65536 {
struct size_4096 a,b,c,d,e,f,g,h,
i,j,k,l,m,n,o,p;
};
struct size_65536 var65536; //Speicherbedarf=65536 Bytes
//Bei 16-Architektur KO
//Ab 32-Architektur OK
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Im Falle von globalen Variablen erzeugt der Compiler/Linker eine Fehlermeldung. Werden von diesen Datentypen Variablen als lokale Variablen angelegt, so erzeugt dies zur Laufzeit einen Stackoverflow.
=== Zeigervariable ===
Eine Zeigervariable ist eine Variable, die eine Speicheradresse speichert. Die Größe dieses Datentyps hängt von der Adressierungsbreite des Prozessors ab. Unabhängig von dem Datentyp, auf den die Zeigervariable zeigt, ergibt sich folgende Breite:
* 4-Byte bei einer 32-Bit Rechnerarchitektur
* 8-Byte bei einer 64-Bit Rechnerarchitektur
* 2-Byte bei einer 16-Bit Rechnerarchitektur
=== Datentyp size_t ===
Die maximale Größe von Arrays/Strukturen/Unions ist in C von der zugrundeliegenden Rechnerarchitektur abhängig. Sie ergibt sich aus der Adressierungsbreite. Da die Datenbreite des Datentyps int zumeist kleiner als die Adressierungsbreite ist, existiert in C/C++ der vorzeichenlose Datentyp size_t.<br />
Alle Funktionen, welche den Speicherbedarf übergeben bekommen, bzw. zurückgeben (bspw. strlen(), memcpy(), sizeof()) , nutzen den Datentyp size_t:
<syntaxhighlight lang="C">
//Prototypen
size_t strlen(char *str); //Die max. Stringlänge ist durch den
//adressierbaren Speicher vorgegeben
void *malloc(size_t size);
void *memcpy(void *dest, const void *src, size_t n);
</syntaxhighlight>
Der Datentyp size_t ist in der Header-Datei stddef.h der Standard-C-Library per typedef gesetzt. Im Normalfall muss diese Header-Datei nicht explizit inkludiert werden, da bei Nutzung von z.B. strlen() diese bereits durch die Header-Datei string.h inkludiert wird:
<syntaxhighlight lang="C">
typedef unsigned long long size_t; //Bei einer 64-Bit Rechnerarchitektur
</syntaxhighlight>
Hinweis:
* Der Datentyp size_t ist immer ein vorzeichenloser Datentyp (es gibt keine negativen Speicheradressen).
* Mit dem Datentype ssize_t wird eine vorzeichenbehaftete Variante zur Verfügung gestellt, welche hilfreich ist, wenn Speicheradresse subtrahiert werden sollen.
* Soll der Wert vom Datentyp size_t mittels printf() ausgegeben werden, so ist der 'Length Modifier' z und der 'Conversion Specifier' u zu nutzen:
:<syntaxhighlight lang="C">
size_t var=strlen("String");
printf("%zu",var);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[]) {
size_t var=strlen("String");
printf("%zu",var);
printf("%d",var); //Hier sollte es eine Compiler-Warning geben!
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Boolescher-Datentype/Operatoren ==
Ursprünglich gab es den booleschen Datentyp in der Programmiersprache C nicht. Mit C99 wurde zwar der Datentyp <code>_Bool</code> eingeführt, dies änderte jedoch nicht den Umgang mit Anweisungen und Operatoren, die einen booleschen Datentyp erwarten/zurückgeben!
An allen Stellen, an denen ein boolescher Datentyp erwartet wird (z.B. IF-Abfrage, bei booleschen Operationen) wird der Datentyp Ganzzahl, Gleitkommazahl oder Zeiger erwartet (= Scalar-Type) und ausgewertet. Der hierin gespeicherte Zahlenwert sagt aus, ob diese Zahl als True oder False zu interpretieren ist:
* False, wenn Ganzzahl gleich 0 oder Gleitkommazahl gleich 0.0 oder Zeiger gleich NULL
* True, wenn Ganzzahl ungleich 0 oder Gleitkommazahl ungleich 0.0 oder Zeiger ungleich NULL
Beispiel:
<syntaxhighlight lang="C">
int a=3;
double b=0.0;
int *ptr=&a;
while(1);
if(a) {}
for( ; b && ptr ; );
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a=3;
double b=0.0;
int *ptr=&a;
while(0);
if(a) {}
for( ; b && ptr ; ) {}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Operatoren, welchen einen booleschen Wert zurückliefern (Vergleichs-Operatoren und Boolesche-Operatoren), liefern ein Integer-Datentyp zurück:
* (int)0 für False
* (int)1 für True
Beispiel:
<syntaxhighlight lang="C">
int a=3;
int b= (a==3); //b=1
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a=3;
int b= (a==3); //b=1
printf("%d",b);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
In den if()/for()/while() Anweisungen ist folglich kein explizites Konvertieren eines Ganzzahl-/Gleitkomma-/Zeigerwertes mittels des Vergleichs-Operators in einen Booleschen Wert notwendig:
<syntaxhighlight lang="C">
int a;
double b;
if(a) //entspricht if(a!=0)
if(!b) //entspricht if(b==0.0)
while(1) //entspricht while(True)
for(int lauf=1; lauf ; lauf--);
</syntaxhighlight>
Umgedreht kann ein boolescher Wert oder auch das Ergebnis einer booleschen Operation direkt mit einer Ganzzahl- oder Gleitkommazahl verknüpft werden:
<syntaxhighlight lang="C">
int a=3,b=2;
a=a+1 && 7 << 3 & a==3;
if( a==1 & b==2)
if(3 < a < 9) //Vorsicht, die Schreibweise lässt ein
//anderes Verhalten erwarten!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a=3,b=2;
a=a+1 && 7 << 3 & a==3;
printf("%d\n",a);
if(a==1 & b==2)
printf("true\n");
else
printf("false\n");
if(3 < a < 9)
if( (a==1) & (b==2))
printf("true\n");
else
printf("false\n");
return 0;
} | execCompilerOptions=|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit C99 wurde der Datentyp <code>_Bool</code> eingeführt. Dieser entspricht weiterhin einem Integerdatentyp mit der Besonderheit, dass beim Zuweisen eines Wertes dieses auf true oder false geprüft wird und Variablen dieses Datentyps nur die Werte 0 oder 1 annehmen können:
<syntaxhighlight lang="C">
_Bool var1=12;
printf("var1=%d\n",var1); //→ 1
float var2=13.2;
var1=var2;
printf("var1=%d\n",var1); //→ 1
var1--; //Post/Pre Inkrement/Dekrement in C++ nicht auf Datentyp bool! möglich
printf("var1=%s\n",var1?"true(1)":"false(0)"); //→ false
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
_Bool var1=12;
printf("var1=%d\n",var1); //→ 1
float var2=13.2;
var1=var2;
printf("var1=%d\n",var1); //→ 1
var1--; //Post/Pre Inkrement/Dekrement in C++ nicht auf Datentyp bool!
printf("var1=%s\n",var1?"true(1)":"false(0)"); //→ false
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Für den einfacheren Umgang mit dem 'neuen' Datentyp wurde in der Header-Datei <code>stdbool.h</code> die Makros <code>true</code> (als Austauschwert für die Ganzzahl 1) und <code>false</code> (als Austauschwert für die Ganzahl 0) definiert. Ergänzend wird hier der Datentyp <code>bool</code> als Alias auf <code>_Bool</code> gesetzt.
<syntaxhighlight lang="C">
#include <stdbool.h>
bool foo(int par,int min,int max) {
if((par >= min) && (par <= max))
return true;
else
return false;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdbool.h>
bool foo(int par,int min,int max) {
if((par >= min) && (par <= max))
return true;
else
return false;
}
int main(int argc,char *argv[]) {
foo(4,3,6);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* In C++ gibt es anstatt des Datentypes <code>_Bool</code> den Datentyp <code>bool</code>. Auch sind die beiden Konstanten <code>true</code> und <code>false</code> ohne zusätzliches Einbinden der Header-Datei vorhanden. Der weitere Umgang ist jedoch identisch zu C.
== Literale/Konstanten ==
In Computerprogramm werden an diversen Stellen Konstanten in Source Code genutzt. Sei es als Initialisierungswert für Variablen, als Vergleichswert für Abfragen, zur Definition von Schleifendurchläufe oder als Strings für die Kommunikation. Der Syntax der Programmiersprache bietet dazu verschiedene Möglichkeiten, wie Zahlen zu beschreiben sind und wie der Datentyp vorgeben wird.</br>
Ungeachtet der Schreibweise werden im Computer alle Zahlen identisch als binäre Zalen gespeichert. Beispiele, wie die Zahlen intern gespeichert werden:
<syntaxhighlight lang="C">
int var=17; //0000 0000 0000 0000 0000 0000 0001 0001
short var=0x307;// 0000 0011 0000 0111
char var=017; // 0000 1111
int var=-1; //1111 1111 1111 1111 1111 1111 1111 1111
float var=0.0; //0000 0000 0000 0000 0000 0000 0000 0000
float var=1.0; //0011 1111 1000 0000 0000 0000 0000 0000
</syntaxhighlight>
=== Ganzzahl-Konstanten ===
Im Allgemeinen ordnet der Compiler einer numerischen, ganzzahligen Konstanten den kleinstmöglichen Datentyp beginnend vom Datentyp integer zu. Sobald der Wert der Konstanten den Wertebereich von integer übersteigt, wird der nächst größere passende Datentyp gewählt. Ergänzend gilt, dass alle Ganzzahl-Konstanten als vorzeichenbehaftete Ganzzahl-Konstanten angesehen werden!<br />
Beispiele für integer Konstanten:
<pre>
123
+123
-123 → Formal wird das Minus als Operator angesehen
und die positive Zahl 123 negiert
0x123 → Konstante ist in hexadezimaler Schreibweise notiert
0123 → Konstante ist in oktaler Schreibweise notiert
0b011 → Konstante ist in binärer Schreibweise notiert
nicht offizieller C-Syntax, wird aber von vielen Compiler unterstützt
ab C23-Spezifikation offiziell im C-Syntax enthalten!
6'432'108 → Tausendertrenner (ab C23 und in C++)
6'4'3'2'10 → Tausendertrenner
0x12'23'5 → Tausendertrenner
0b1001'001 → Tausendertrenner
5123123123 → Wertebereich größer als 2^31 so dass automatisch
zum nächst größeren Datentyp konvertiert wird
</pre>
Mit den Suffixen L/l und LL/ll kann der Datentyp long und long long erzwungen werden:
<pre>
12L → Konstante wird in eine long Integer Konstante konvertiert
4711LL → Konstante wird in eine Long Long Konstante konvertiert
</pre>
Mit dem Suffix U/u kann die Konstante explizit auf unsigned gesetzt werden:
<pre>
12U → Konstante wird als vorzeichenlose Zahl gesepeichert
4711ULL → Konstante wird in eine vorzeichenlose
Long Long Konstante konvertiert
</pre>
=== Char-Konstanten ===
In einfachen Anführungsstrichen geschriebene ASCII Zeichen werden entsprechend der {{w|American Standard Code for Information Interchange | ASCII-Tabelle}} als Zahlenwert (Datentyp int) dargestellt:
<pre>
'A' → Integerkonstante 65
'a' → Integerkonstante 97
…
</pre>
Über den {{w|Escape-Sequenz|Escape-Operator}} (Zeichen Backslash '\') wird das/die dem ESCAPE Operator folgende Zeichen gesondert interpretiert. Die im Source-Code erhaltene Zeichenfolge wird im Computerprogramm als ein Zahlenwert (Datentyp int) gespeichert. Dies ist u.A. zur Darstellung von ' und " aber auch zur Darstellung der unteren 32 Zeichen der ASCII Tabelle notwendig (Siehe auch {{w|Steuerzeichen}})
<pre>
ESCAPE Integer- → Bedeutung / (Terminal)funktionalität
Sequence konstante
'\0' = 0 → 0 Character = Stringendezeichen
'\a' = 7 → Bell (erzeugt auf dem Terminal einen Ton)
'\b' = 8 → Backspace (Bewegt den Cursor um eine Position nach links)
'\t' = 9 → Horizontal Tab (Bewegt den Curso auf die nächste horizontale
Tabulatorposition, Abstand ist Terminalspezifisch)
'\n' = 10 → NewLine (Zeilenvorschub)
'\v' = 11 → Vertial Tab
'\r' = 13 → Carriage Return (Wagenrücklauf, Bewegt den Cursor an den
Zeilenanfang)
'\"' = 34 → Double Quote
'\'' = 39 → Single Quote
'\?' = 63 → Question mark
'\\' = 92 → Backslash
'\f' = 12 → FormFeed (Erzeugt auf dem Terminal/Drucker
einen Seitenvorschub)
'\ooo' = 0ooo → Oktal, wobei o Digits von 0..7 sein müssen
'\xdd' = 0xdd → Hexadezimal, wobei d Digits von 0..9 A..F sein müssen
'\udddd' Unicode mit 4 Digits
'\Udddddddd' Unicode mit 8 Digits
</pre>
Beispiel
<syntaxhighlight lang="C">
'A' == 65 == '\101' == '\x41' == '\u0041' == '\U00000041'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
//Programmiersprache wurde auf C++ gesetzt
if('A' == 65) printf("'A' == 65\n");
if('A' == '\101') printf("'A' == '\\101'\n");
if('A' == '\x41') printf("'A' == '\\x41'\n");
if('A' == '\u0041') printf("'A' == '\\u0041'\n");
if('A' == '\U00000041') printf("'A' == '\\U00000041'\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
Über Prefixe können alternative Zieldatentypen/Konvertierungen erzwungen werden:
<pre>
u'b' → unicode 16 (nur C++)
U'b' → unicode 32 (nur C++)
L'b' → wchar_t
</pre>
Hinweis
* Die ASCII-Tabelle basiert auf einer 7-Bit Zeichenkodierung, so dass bspw. die Umlaute 'ä', 'ö' und 'ü' dort nicht kodiert sind. Sollen auch diese Zeichen genutzt werden, so empfiehlt sich der Datentyp wchar_t
=== Gleitkommakonstanten ===
Alle Gleitkommakonstanten sind ohne weitere Angaben vom Datentyp double!
<pre>
555.12
555. → 555.0
.1 → 0.1
4e2 → 400.0
1'234.678'9 → Tausendertrenner (ab C23 und in C++)
0x22.11p13 → Konstante in Hexadezimalen Schreibweise (ab C99)
</pre>
Über Suffixe kann ein alternativer Datentyp erzwungen werden:
<pre>
3.0F → Datentyp float
3.0l → Datentyp long double
</pre>
Hinweis:
* Aufgrund der unterschiedlichen Basis zwischen dem menschlichen Zehner-System und dem computerinternen Binär-System entstehen insbesondere bei den Nachkommastellen Rundungsfehler. Die Konstante 0.1f wird durch die Wandlung intern als 1.00000001490116119384765625e-1 dargestellt (siehe [[Programmieren in C/C++: Datentypen#Gleitkomma Datentypen | Datentypen:Gleitkomma Datentypen]])
* Die C-Spec verlangt, dass die binäre Repräsentation von Gleitkommazahlen zur Laufzeit (z.B. durch die Funktion atof() strtod() scanf("%f")) identisch zur der zur Compilezeit ist. Beispiel:
:<syntaxhighlight lang="C">
if(3.14==atof("3.14")) printf("muss erfüllt sein");
//3.14 wird vom Compiler in ein Binärwert gewandelt
//Der String "3.14" wird zur Laufzeit mittels atof in ein Binärwert gewandelt
//Beide Wandlungsergebnisse müssen identisch sein
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
if(3.14==atof("3.14")) printf("muss erfüllt sein\n");
//3.14 wird vom Compiler in ein Binärwert gewandelt
//Der String "3.14" wird zur Laufzeit mittels atof in ein Binärwert gewandelt
//Beide Wandlungsergebnisse müssen identisch sein
printf("Intern wird 3.14 wie folgt dargestellt %14.20f",3.14);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Konstanten Ausdrücke ===
Ergänzend zu den Zahlenwerten werden auch Ausdrücke durch den Compiler ausgewertet. Als Voraussetzung für die Ausdrücke gilt, dass alle Operatoren Literale/Konstante sein müssen, so dass der Compiler die Berechnung durchführen kann. Als Operatoren können alle im normalem Syntax erlaubten Operatoren (z.B.: +,-,*,/,&,&&,|,||,>>,<<,==,!=) genutzt werden.<br />
Beispiel:
<syntaxhighlight lang="C">
int var1=7*3+5; → wird vom Compiler durch 26 ersetzt
int var2=(4710+(8-1))&-8; → wird vom Compiler durch 4712 ersetzt
var1=4*4*var1+77*(77%3); → wird vom Compiler durch 16 * var1 + 154 ersetzt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
int var1=7*3+5; //→ wird vom Compiler durch 26 ersetzt
int var2;
var2=(4710+(8-1))&-8; //→ wird vom Compiler durch 4712 ersetzt
var1=4*4*var1+77*(77%3); //→ wird vom Compiler durch var1 * 16 + 154 ersetzt
return 0;
} | execCompilerOptions=-Wall|
h=g|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Konstante Ausdrücke bieten sich an, um den Sourcecode lesbarer zu gestalten. Da der Compiler die Berechnung durchführt, wird zur Laufzeit keine Rechenleistung benötigt. Einzig die Compiledauer wird etwas erhöht:
<syntaxhighlight lang="C">
double alpha1=0.7071067811;
double alpha2=sin(45.0*M_PI/180); //siehe nachfolgende Hinweise
if(ad_get() > 614 ) printf("Sensor defekt\n");
if(ad_get() > (int)(3.0/(5.0/1023)+0.5) ) printf("Sensor defekt\n");
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <math.h>
int ad_get(void) {
return 615; //614;
}
int main(int argc,char *argv[]) {
double alpha1=0.7071067811;
double alpha2=sin(45.0*M_PI/180);
printf("%f\n%f\n",alpha1,alpha2);
if(ad_get() > 614 ) printf("Sensor defekt\n");
if(ad_get() > (int)(3.0/(5.0/1023)+0.5) ) printf("Sensor defekt\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Ergänzend zu den oben aufgeführten Operatoren erlauben einige Compiler weitere Funktionen der Math.h Library in Konstantenausdrücken (z.B. sin(), cos(), ...)
* Konstanten Ausdrücke werden innerhalb des Compilers durch den Präprozessor ausgewertet, so dass dieser die Ergebnisse ebenfalls nutzen kann:
:<syntaxhighlight lang="C">
#define BUF_SIZE 512
#if (BUF_SIZE & (BUF_SIZE -1)) != 0
#endif
</syntaxhighlight>
=== String Konstanten ===
Stringkonstanten erzeugen ein Array von Characters. Mit dem abschließenden Hochkommata wird das Array um ein Stringendezeichen ergänzt:
<pre>
"abc" → (char []) {'a','b','c','\0'}
</pre>
Adjacent Strings Konstanten werden vom Compiler zu einer String-Kontante zusammengefasst, so dass nur ein Stringendezeichen vorhanden ist:
<pre>
"xxx" "yyy" → (char []) {'x','x','x','y','y','y','\0'}
</pre>
Über Prefixe können alternative Zieldatentypen/Konvertierungen erzwungen werden:
<pre>
L"string" → (wchar_t[7]){L's',L't',L'r' …)
</pre>
Über Postfixes können in C++ Objekte erzeugt werden:
<pre>
"string"s → erzeugt einen String vom Datentyp std::string
"string"sw → Erzeugt einen String vom Datentyp std::string_view
</pre>
String Konstanten werden Compilerintern über unnamed Variablen realisiert, welche als globale Variable angelegt werden und per default const sind:
<syntaxhighlight lang="C">
printf("Wert=%d",4);
//entspricht
const char unnamed1[]="Wert=%d";
printf(unnamed1,4);
//String Konstanten sind per Default Konstant
char *str="hallo"; //Typkonflikt!, da "hallo" vom Datentyp const char[] ist
str[0]='H'; //Laufzeitfehler, da nun schreibender Zugriff auf im
//Readonly Speicher angelegt Variable.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
printf("Wert=%d\n",4);
//entspricht
const char unnamed1[]="Wert=%d\n";
printf(unnamed1,4);
fflush(stdout); //Zur Darstellung der Ausgabe, da nachfolgend
//das Programm abstürzt und die gepufferte Ausgabe
//nicht zur Anzeige gebracht wird
//String Konstanten sind per Default Konstant
char *str="hallo"; //Typkonflikt!, da "hallo" vom Datentyp const char[] ist
str[0]='H'; //Laufzeitfehler, da nun schreibender Zugriff auf im
//Readonly Speicher angelegt Variable.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Für doppelte String Konstanten wird nur einmal Speicher reserviert:
<syntaxhighlight lang="C">
const char *str1="hallo";
const char *str2="hallo";
if(str1==str2) printf("Identische Startadressen");
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
const char *str1="hallo";
const char *str2="hallo";
if(str1==str2)
printf("Identische Startadressen");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Initialisierungsliste / Compound Literal ==
Arrays, Strukturen und Unions bestehen zumeist aus mehreren Elementen. Zur Initialisierung solcher Variablen werden die Initialisierungswerte in geschweiften Klammern als Initialisierungsliste zusammengefasst.
<code>
Syntax: {Initialisierungsliste}
</code>
Für eine Initialisierungsliste wird kein Speicher vorgehalten. Vielmehr wird bei der Variablendefinition die Variable direkt mit dem Inhalt der Liste initialisiert. Der Datentyp der Initialisierungsliste ergibt sich aus dem Datentyp der zu initialisierenden Variable:
<syntaxhighlight lang="C">
int arr[5] = { 1,2,3,4,5 };
struct xyz { int x,y,z;}; //Definition einer Struktur
struct xyz var = { 1,2,3 };
</syntaxhighlight>
Wird der Initialisierungsliste ein Datentyp in runden Klammern vorangestellt, so wird hiermit eine 'unnamend' Variable/Objekt, ein Compound Literal erstellt:
<code>
Syntax: (type) {Initialisierungsliste}
</code>
Ein Compound Literal entspricht einer anonymen Variablen des angegebenen Datentyps. Wie bei einer normalen Variablendefinition wird hier ebenfalls eine Variable angelegt und diese mit den Initialisierungswerten initialisiert. Im Unterschied zu einer normalen Variable kann auf solch eine Variable im Nachgang nicht mehr zugegriffen werden. Der Rückgabewert eines Compound Literals entspricht somit dem einer Variablen.</br>
Compound Literale bieten sich überall dort an, wo Variablen nur für einen einmaligen Zweck angelegt werden (bspw. bei der Parameterübergabe von Funktionen):
<syntaxhighlight lang="C">
struct point {int x; int y;};
drawline((struct point){1,2},(struct point){2,3});
printarray((int []){1,2,3,4});
//entsprechen
struct point unnamed1={1,2},unnamed2={2,3};
drawline(unnamed1,unnamed2);
int unnamed3[]={1,2,3,4};
printarray(unnamed3);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct point {int x,y;};
void drawline(struct point start,struct point end) {
printf("Linie von (%d,%d) nach (%d,%d)\n",start.x,start.y,end.x,end.y);
}
void printarray(int arr[4]) {
printf("[ ");
for(size_t idx=0;idx<4;idx++)
printf("%d ",arr[idx]);
printf("]\n");
}
#include <stdlib.h>
int main(int argc,char *argv[]) {
struct point {int x; int y;};
drawline((struct point){1,2},(struct point){2,3});
printarray((int []){1,2,3,4});
//entsprechen
struct point unnamed1={1,2},unnamed2={2,3};
drawline(unnamed1,unnamed2);
int unnamed3[]={1,2,3,4};
printarray(unnamed3);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Über den Adressoperator kann auch die Adresse der anonymen Variablen ermittelt werden. In diesem Falle ist dann der Gültigkeitsbereich/-dauer des Compound Literals zu berücksichtigen. Wird eine Compound Literals außerhalb eines Block-Scopes angelegt, so entspricht sie einer globalen Variable, andernfalls einer lokalen Variablen. Außerhalb des Gültigkeitsbereiches verliert die Adresse auf solch eine Variable ihre Gültigkeit:
<syntaxhighlight lang="C">
drawlinep( &(struct point){1,2},&(struct point){2,3});
//entspricht
struct point unnamed1={1,2},unnamed2={2,3};
drawlinep( &unnamed1, &unnamed2);
struct point1, *point2;
{ //Block-Scope, zwecks Darstellung von lokalen Variablen
point1= (struct point){1,2}; //Compound Literal entspricht hier
//Initialisierungswert für point1
point2=&(struct point){3,4}; //Compound Literal ist nur in diesem
//Block gültig
drawlinep(&point1 /*OK*/, point2 /*OK*/);
}
drawlinep(&point1 /*OK*/, point2 /*KO*/); //Zeiger zeigt auf nicht mehr
//gültigen Speicherbereich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct point {int x,y;};
void drawlinep(struct point *start,struct point *end) {
printf("Linie von (%d,%d) nach (%d,%d)\n",start->x,start->y,end->x,end->y);
}
#include <stdlib.h>
int main(int argc,char *argv[]) {
drawlinep( &(struct point){1,2},&(struct point){2,3});
//entspricht
struct point unnamed1={1,2},unnamed2={2,3};
drawlinep( &unnamed1, &unnamed2);
struct point point1, *point2;
{ //Block-Scope, zwecks Darstellung von lokalen Variablen
point1= (struct point){1,2}; //Compound Literal entspricht hier
//Initialisierungswert für point1
point2=&(struct point){3,4}; //Compound Literal ist nur in diesem
//Block gültig
drawlinep(&point1 /*OK*/, point2 /*OK*/);
}
drawlinep(&point1 /*OK*/, point2 /*KO*/); //Zeiger zeigt auf nicht mehr
//gültigen Speicherbereich
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Compound-Literal sind per Default keine Konstanten, können also zur Laufzeit geändert werden (siehe Kap. [[Programmieren in C/C++: DatentypeSpecifier#Const Type Qualifier|DatentypeSpecifier:Const Type Qualifier]]):
:<syntaxhighlight lang="C">
float *arr=(float []){1.1,2.2,3.3}; //Kein Typkonflikt
arr[0]=47.11; //Änderung des 'Konstanten' arr[0] ist möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
float *arr=(float []){1.1,2.2,3.3}; //Kein Typkonflikt
arr[0]=47.11; //Änderung des 'Konstanten' arr[0] ist möglich
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Die geschweiften Klammern <code>{ }</code> sind nicht mit dem Block-Operator (siehe [[Programmieren in C/C++: Grundlagen#Block / Compound-Statement | Block / Compound-Statement]]) zu verwechseln. Werden die geschweiften Klammern bei der Initialisierung von Variablen genutzt, dann beschreibt der Inhalt der geschweiften Klammern eine Initialisierungsliste. Wird diesen ein Datentyp vorangestellt, dann wird hiermit eine Compound Literal definiert.
== Variableninitialisierung ==
Mit der Definition einer Variable kann diese optional initialisiert werden. Der tatsächliche Zeitpunkt der Variableninitialisierung (zur Laufzeit oder zur Compilezeit) und damit die Ausführung der Initialisierung (Maschinensprachebefehle oder Speichervorbelegung) hängt von der Gültigkeit/Sichtbarkeit der Variablen ab(siehe [[Programmieren in C/C++: Grundlagen#Gültigkeit/Sichtbarkeit von Variablen| Gültigkeit/Sichtbarkeit von Variablen]]).
=== Globale + Static lokale Variablen ===
Globale und statisch globale Variablen werden in einem während der Laufzeit des Programms festen Speicherbereich gehalten. Zum Startzeitpunkt des Programms ist der Speicherplatz solch einer Variable mit dem Initialisierungswert gefüllt, so das bei erstmaliger Nutzung dieser Variablen diese ihre Initialisierungswerte enthalten. Die Belegung des Speicherplatzes erfolgt durch den Compiler, so dass als Initialisierungswerte / Inhalt der Initialisierungsliste nur Konstanten oder Konstanten-Ausdrücke (siehe [[Programmieren in C/C++: Grundlagen#Literale/Konstanten | Literale/Konstanten]]) erlaubt sind:
<syntaxhighlight lang="C">
int g=1; //Speicherstelle der Variable g wird
//mit 1 belegt
short array[3]={1,1+1, sin(0.0)}; //Speicherstellen des Arrays wird
//mit 1, 2 und 0 (Funktion sin() wird zur
//Compilezeit ausgeführt) belegt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
double sin(double); //DJ: Include-Anweisung in wikibooks schlägt fehlt
int g=1; //Speicherstelle der Variable g wird
//mit 1 belegt
short array[3]={1,1+1, sin(0.0)}; //Speicherstellen des Arrays wird
//mit 1, 2 und 0 (Funktion sin() wird zur
//Compilezeit ausgeführt) belegt
int main(int argc,char *argv[]) {
printf("%hd %hd %hd\n",array[0],array[1],array[2]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Nicht initialisierte globale und static lokale Variablen werden mit 0 initialisiert! D.h. die Speicherstellen dieser Variablen werden mit dem Wert 0 vorbelegt::
<syntaxhighlight lang="C">
int f; //f hat den Wert 0
double arr[10]; //Alle Elemente von arr werden mit 0.0 initialisiert!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int f; //f hat den Wert 0
double arr[10]; //Alle Elemente von arr werden mit 0.0 initialisiert!
int main(int argc,char *argv[]) {
printf("f=%d\n",f);
printf("%f %f %f\n",arr[0],arr[1],arr[2]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Lokale Variable ===
Der Speicherplatz für lokale Variable wird auf dem Stack zur Verfügung gestellt. Mit jedem öffnenden Block-Scope wird Speicher für die innerhalb dies Block-Scopes vorhandenen Variablen vom Stack nach dem LIFO Prinzip reserviert und mit der Variablendefinition Maschinencode zur Initialisierung der Speicherstellen ausgeführt (sofern Variable einen Initialisierungswert hat):
<syntaxhighlight lang="C">
{ //Öffnende Klammer erzeugt Maschinencode zur Speicherreservierung
//von 4 Bytes (für int) und 8 Bytes (für double)
int var1=12; //erzeugt Maschinencode zur Initialisierung
//der ersten 4 Byte mit dem Wert 12
double var2=sin(f); //erzeugte Maschinencode, welche zunächst
//die Funktion sin() mit dem Übergabewert f
//aufruft und dessen Rückgabewert in die
//nächsten 8 Byte des reservierten Speichers
//kopiert
...
{ //siehe zuvor
int var3=var1; //siehe zuvor
double var4=var2+var1;
} //siehe nachfolgenden
} //Freigabe des zuvor reservierten Speichers
</syntaxhighlight>
Dies gilt auch für Funktionsaufrufe. Mit der öffnenden geschweiften Funktionsklammer wird ebenfalls Speicher reserviert:
<syntaxhighlight lang="C">
void foo(int par)
{ //Öffnende Funktionsklammer erzeugt Maschinencode zur Speicherreservierung
//von 4 Bytes (für (Übergabe)Variable par und 4 Bytes für Variable var
int var; //Da keine Initialisierung vorhanden ist wird auch
//kein Maschinencode zur Initialisierung ausgeführt
{ //Öffnende Klammer erzeugt Maschinencode zur Speicherreservierung
//von 4 Byte für Variable x
int x;
...
</syntaxhighlight>
Aufgrund der mit der Initialisierung bedingten Erzeugung von Maschinencode können die Initialisierungswerte/Inhalte der Initialisierungsliste bei lokalen Variablen aus beliebigen Ausdrücken bestehen und müssen keine Konstanten oder Konstanten Ausdrücke sein:
<syntaxhighlight lang="C">
void foo(float f,float g) {
float summe=f+g; //Initialisierungswerte
float arr[3] = {f+f,g-f,sin(f)}; //werden zur Laufzeit berechnet
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <math.h> //fuer sinf()
void foo(float f,float g) {
float summe=f+g; //Initialisierungswerte
float arr[3] = {f+f,g-f,sinf(f)}; //werden zur Laufzeit berechnet
printf("%f\n",(double)summe);
printf("%f %f %f\n",(double)arr[0],(double)arr[1],(double)arr[2]);
}
int main(int argc,char *argv[]) {
foo(3,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dieser Maschinencode wird jedes Mal ausgeführt, wenn die dazugehörige Anweisung abgearbeitet wird und bedingt dementsprechend Rechenzeit. Zehnmaliges Ausführen einer Funktion oder zehnmaliges Öffnen eines Block-Scopes innerhalb einer For-Schleife führt zur zehnmaligen Ausführung der oben genannten Sachverhalte:
<syntaxhighlight lang="C">
void foo(int);
void var(void) {
for(int lauf=10; lauf>0; lauf--)
{ //zehnmaliges Reservieren von Speicher
int var=lauf*2; //zehnmalige Initialisierung
foo(var);
} //Freigabe des Speichers
}
void foo(int par) { //zehnmaliges Reservieren von Speicher
int var=12; //zehnmalige Initialisierung
} //Freigabe des Speichers
</syntaxhighlight>
Nicht initialisierte lokale Variablen werden nicht initialisiert, d.h. keine zusätzlichen Maschinenbefehle zum Initialisieren erzeugt. Der Variablenwert entspricht dann einem 'Zufallswert' oder korrekter gesagt dem Inhalt der Variablen, welcher zuvor der Speicherstelle zugewiesen war:
<syntaxhighlight lang="C">
int first(void) {
int var_first=7;
return var_first;
}
int second(void) {
int var_second; //Variable var_second bekommt den identischen
return var_second; //Speicherbereich wie var_first zugwiesen
//und damit auch dessen zuletzt gültigen Wert
}
int main(int argc, char *argv[]) {
int var1=first(); //var1 beinhaltet Wert 7
int var2=second(); //var2 beinhaltet Wert 7
printf("var_foo=%d\n",var1);
printf("var_far=%d\n",var2);
return 0;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int first(void) {
int var_first=7;
return var_first;
}
int second(void) {
int var_second; //Variable var_second bekommt den identischen
return var_second; //Speicherbereich wie var_first zugwiesen
//(und damit auch dessen zuletzt gültigen Wert)
}
int main(int argc, char *argv[]) {
printf("%d\n",second()); //Zufallswert (0, da Stack mit 0 initialisiert ist)
printf("%d\n",first()); //Stack belegen
printf("%d\n",second()); //Zufallswert (7, da Speicherstelle zuvor mit 7
return 0; //belegt wurde)
} | execCompilerOptions=|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird eine Variableninitialisierung mit einer switch oder goto Anweisung übersprungen, so wird zwar die Variable angelegt (Speicherplatz reserviert), jedoch die Maschinenbefehle zur Initialisierung dieser Variablen nicht ausgeführt (siehe auch [[Programmieren in C/C++: Grundlagen# Switch-Anweisung|Switch-Anweisung]] und [[Programmieren in C/C++: Grundlagen# Label + Goto|Label + Goto]]). Die Variable enthält dann einen Zufallswert:
<syntaxhighlight lang="C">
switch(value) {
case 0:
int lok=7;
printf("%d",lok); //OK, lok beinhaltet den Wert 7
break;
default:
printf("%d",lok); //KO, Variable lok vorhanden,
//aber nicht initialisiert. D.h. Ausgabe einer
break; //Zufallszahl
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
void foo(int value) {
switch(value) {
case 0:
int lok=7;
printf("%d\n",lok); //OK, lok beinhaltet den Wert 7
break;
default:
printf("%d\n",lok); //KO, Variable lok vorhanden,
//aber nicht initialisiert. D.h. Ausgabe einer
break; //Zufallszahl
}
}
void far(void) {
int var1=4711;
int var2=1799;
printf("Marke: %d, Erscheinungsjahr: %d\n",var1,var2);
}
int main(int argc,char *argv[]) {
foo(2); //Zufallswert (0, da Stack mit 0 initialisiert ist)
foo(0); //Initialisierungswert
far(); //Stack belegen
foo(2); //Zufallswert
return 0;
} | execCompilerOptions=|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei erstmaligem Funktionsaufruf kann eine nicht initialisierten lokale Variablen den Wert 0 beinhalten (Stackframe wird mit Programmstart auf 0 gesetzt). Beim nächsten Aufruf der Funktion ist zumeist die Speicherstelle der lokalen Variablen mit anderen Werten gefüllt worden, so dass nun ein anderer 'Zufallswert' als 'Initialisierungswert' enthalten ist
=== C++ ===
In C++ ist ergänzend die Initialisierung einer Variablen über () möglich. Bei Objekten wird hierüber der zugehörige Konstruktor aufgerufen. Bei primitiven Datentypen entspricht der Wert in den Klammern dem Initialisierungswert:
<syntaxhighlight lang="C++">
int variable(10); //Bei primitiven Datentype entspricht dies
//int variable=10;
struct test {
int a;
test(int par) {a=par;} //Konstruktor der Struktur test
};
struct test test(4); //Konstruktor test(int par) wird aufgerufen
struct test test(4,5); //KO, kein passender Konstruktor vorhanden
</syntaxhighlight>
=== Sonstiges ===
Folgende weitere Sachverhalten gilt es bzgl. Variableninitialisierung zu berücksichtigen:
* Nach C-Spezifikation ist eine Initialisierung von Variablen nicht notwendig. Es liegt folglich kein Fehler vor, wenn auf eine nicht initialisierte Variable lesend zugegriffen wird. Ungeachtet der C-Spezifikation überprüft der Compiler mit dem Schalter '-Wall' diesen Sachverhalt und gibt eine Warning aus
* Deklarationen/Prototypen können keinen Initialisierungswert enthalten
<syntaxhighlight lang="C++">
extern int var=7; //Fehlerhaft
</syntaxhighlight>
* Const und lokale Static Variablen sollten initialisiert werden, auch wenn C in diesem Fall keinen Fehler meldet!
<syntaxhighlight lang="C++">
const int konstante; //Syntaktisch OK, Initialisierungswert fraglich!
static int statisch;
</syntaxhighlight>
== Anweisung (Statement) & Expression ==
Eine Anweisung (Statement) stellt entsprechend dem Wikipedia Artikel {{w|Anweisung_(Programmierung) | Anweisung}} ''"ein in der Syntax einer Programmiersprache formulierte einzelne Vorschrift dar, die im Rahmen der Abarbeitung des Programms auszuführen ist"''.</br>
Aus der Statement Spezifikation ergibt sich folglich, welche Bestandteile ein Programm beinhaltet kann. In der C-Spezifikation [C11 6.8] sind folgende Anweisungen definiert:
: labeled-statement: Eine Sprungmarke für die Switch- und die Goto-Anweisung
: compound-statement: siehe nachfolgendes Kapitel
: expression-statement: siehe nachfolgendes Kapitel
: selection-statement: Eine if() oder switch() Anweisung
: iteration-statement: Eine while(), do while() oder eine for() Anweisung
: jump-statement: Eine goto, break, continue oder return Anweisung
so dass ein Programmablauf wie folgt aussehen könnte:
<syntaxhighlight lang="C">
int main(int argc, char argv[]) {
int var; //declaration innerhalb eines compound-statements
label: //labeled-statement
var=var*2+1; //expression-statement
for(var=0;var<100;var++); //iteration-statement
if(var<0) //selection-statement
printf("var<0"); //espression-statement
{ int lok=var; lok++; } //compound-statement
goto label; //jump-statement
return 0;
}
</syntaxhighlight>
=== Ausdruck (Expression) ===
Entsprechend der C-Spezifikation [C11 6.5] ist ein Ausdruck eine Folge von Operatoren und Operanden, die die Berechnung eines Werts angibt, ein Objekt oder eine Funktion bezeichnet, Nebenwirkungen erzeugt oder eine Kombination davon ausführt. Die Wertberechnungen der Operanden eines Operators werden vor der Wertberechnung des Ergebnisses des Operators ausgeführt (siehe auch {{w|lang=en|Expression_(computer_science)|Expression}}).
Beispiele:
<syntaxhighlight lang="C">
//Ausdruck ohne Nebenwirkung
a=sqrt(a*a+b*b);
//Ausdruck mit Nebenwirkungen (Erhöung der globalen Variable a)
int func(int par) { a++; return par*2;}
b=func(1)*func(2);
//Ausdruck mit undefinierten Verhalten (siehe später)
a=++a + 1;
//Statement (welches folglich keinen Rückgabewert hat)
//for-Statement beinhaltet jedoch 3 Ausdrücke (Initialisierungsteil,
//Testteil und Fortsetzungsteil)
a=for(int lauf=10;lauf>0;lauf--);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <math.h>
int a=0;
int func(int par) {
a++;
return par*2;
}
int main(int argc,char *argv[]) {
int a=4,b=7;
//Ausdruck ohne Nebenwirkung
a=sqrt(a*a+b*b);
//Ausdruck mit Nebenwirkungen (Erhöhung der globalen Variable a)
b=func(1)*func(2);
//Ausdruck mit undefinierten Verhalten (siehe später)
a=++a + 1;
//Statement (welches folglich keinen Rückgabewert hat)
//for-Statement beinhaltet jedoch 3 Ausdrücke (Initialisierungsteil,
//Testteil und Fortsetzungsteil)
a=for(int lauf=10;lauf>0;lauf--);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Ausdrücke entsprechen somit Rechenvorschriften, die ausgewertet werden. Ausdrücke sind in C/C++ überall dort erlaubt, wo ein Operand erwartet wird:
<syntaxhighlight lang="C">
//Ausdruck innerhalb der Parameterübergabe
func1(3*12*func2());
//Ausdruck innerhalb einer if/for/switch-Anweisung
if(a+1*3 > 3)
for(a=4*func1(12); 12*func2()<9; func3(a)*9);
switch( (a*3)&0x0f) {}
//Ausdruck innerhalb der Arraydefinition
int arr[1*3*13];
//Ausdruck innerhalb eines Funktionskopfes
void func3(int par, int arr[par*3*printf()]) {}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <math.h>
//Ausdruck innerhalb eines Funktionskopfes
int func1(int par) {
return 1;
}
int func2(void) {
return 1;
}
//Ausdruck innerhalb eines Funktionskopfes
void func3(int par, int arr[par*3*printf("func() called\n")])
{
printf("func() body\n");
}
int main(int argc,char *argv[]) {
int a=1;
//Ausdruck innerhalb der Parameterübergabe
func1(3*12*func2());
//Ausdruck innerhalb einer if/for/switch-Anweisung
if(a+1*3 > 3)
for(a=4*func1(12); 12*func2()<9; func1(a)*9);
switch( (a*3)&0x0f) {}
//Ausdruck innerhalb der Arraydefinition
int arr[1*3*13];
func3(1,arr);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dies ist unter anderen ein Grund dafür, dass C/C++ als unleserlich gilt. Zur besseren Lesbarkeit eines Codes sollte dieses 'Feature' nur dann genutzt werden, wenn es zwingend notwendig ist.
=== Discarded Value / null statement ===
Alle Ausdrücke und nicht void-Funktionen haben einen Rückgabewert, der weiter verwendet werden kann:
<syntaxhighlight lang="C">
a+7 //Rückgabewert ist das Ergebnis der Addtion
printf("hallo") //printf() Funktion ist vom Typ int und gibt die Anzahl
//der ausgegebenen Zeichen zurück
a //gibt den Inhalt der Variablen zurück
7 //gibt den 'Inhalt' der Konstanten zurück
b=(a=7) //der Zuweisungsoperator gibt den Zuweisungswert zurück
</syntaxhighlight>
Der letzte Rückgabewert eines fasst jeden Ausdruckes wird somit nicht genutzt. Dies wird Discarded Value bezeichnet:
<syntaxhighlight lang="C">
int a=7;
a; //Variable a wird gelesen, der Wert jedoch verworfen
7; //Konstante wird erzeugt und anschließend verworfen
a+7; //Ergebnis wird Berechnet und verworfen
printf("hallo"); //Rückgabewert von printf wird verworfen
a=a+7; //Die Zuweisung hat einen Rückgabewert, der verworfen wird
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
int a=7;
a; //Variable a wird gelesen, der Wert jedoch verworfen
7; //Konstante wird erzeugt und anschließend verworfen
a+7; //Ergebnis wird Berechnet und verworfen
printf("hallo"); //Rückgabewert von printf wird verworfen
a=a+7; //Die Zuweisung hat einen Rückgabewert, der verworfen wird
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der einfachste Fall eines Discarded Values ist ein Leeranweisung / null statement, d.h. die Anweisung besteht nur aus einem Semikolon. Dies stellt eine syntaktisch korrekte Anweisung dar, die keine Auswirkung hat:
<syntaxhighlight lang="C">
; //Leeranweisung
</syntaxhighlight >
Überall wo statements/Anweisungen erwartet werden (bspw. bei einer for-Schleife, bei einer if-Anweisungen) kann anstatt einer statements eine Leeranweisung stehen, welche dementsprechend nichts ausführt:
<syntaxhighlight lang="C">
for(size_t idx=0; str[idx]!=0; idx++)
; //Leeranweisung
while(a++ < 100)
; //Leeranweisungen
</syntaxhighlight>
An einige Stellen bietet sich die Nutzung dieser Sachverhalte als vorteilhaft an. Oft führen diese Sachverhalten jedoch zu Ausführungsfehlern, da sie aufgrund des korrekten Syntax vom Compiler nicht als Fehler gemeldet werden und beim Suchen dementsprechend nur schwer zu finden sind! Ggf. gibt der Compiler für einige Sachverhalte eine Warnung aus, so dass es vorteilhaft ist, Compiler-Warnings zu beachten!
Hinweise:
* Soll bewusst der Rückgabewert verworfen werden, so kann/sollte mit dem explizten Cast auf (void) der Rückgabewert explizit 'verworfen' werden. Dies ist u.A. hilfreiche bei Variablen, die (noch) nicht benutzt werden und der Compiler die Warning "unsued Variable" ausgibt:
:<syntaxhighlight lang="C">
(void)a; //Zur Vermeidung von Compiler-Warnings "Unused Variable"
(void)(a+7); //hier eine explizte 'Ansage' der Verwerfung des Wertes
(void)func();
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int func(void) {
return 4711;
}
int main(int argc,char *argv[]) {
int a;
(void)a; //Zur Vermeidung von Compiler-Warnings "Unsued Variable"
(void)(a+7); //hier eine explizte 'Ansage' der Verwerfung des Wertes
(void)func();
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mit der Anweisung <nowiki>[[nodiscard]]</nowiki> (ab C++17, ab C23) wird der Compiler angewiesen, dass der Aufrufer einer Funktion mit Rückgabewert der Rückgabewert entgegenzunehmen ist. Wird der Rückgabewert verworfen, so gibt der Compiler eine Fehlermeldung aus:
:<syntaxhighlight lang="C">
[[nodiscard]] int Client(int socket);
Client(5); ////Fehlermeldung, da Rückgabewert nicht verwendet wird
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
[[nodiscard]] int Client(int socket) {
return socket+1;
}
int Server(int socket) {
return socket+1;
}
int main(int argc,char *argv[]) {
Server(5); //keine Fehlermeldung
Client(5); //Fehlermeldung, da Rückgabewert nicht verwendet wird
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Sequence Point ===
Ein Sequenzpunkt (u.A. das abschließende Semikolon am Ende der Anweisung) ist nach dem Wikipedia Artikel {{w|lang=en|Sequence_point|Sequence Point}} definiert als der Punkt in der Ausführung eines Computerprogramms, an dem garantiert ist, dass alle Nebenwirkungen früherer Bewertungen durchgeführt wurden und noch keine Nebenwirkungen von nachfolgenden Bewertungen durchgeführt wurden.</br>
Sequenzpunkte führen somit zur Trennung der Abarbeitungsreihenfolge innerhalb von Ausdrücken. Das abschließende Semikolon am Ende eines Ausdruckes sorgt somit dafür, dass zunächst der vorangegangene Ausdruck abgearbeitet wird, bevor der nächste Ausdruck beachtet wird.</br>
Beschreibt das Semikolon explizit einen Sequenzpunkt, so gibt es auch andere Operatoren, die einen Sequenzpunkt beinhalten. Bei solchen Operatoren wird somit zunächst vollständig der erste Teilausdruck ausgewertet, bevor der nächste folgt. Zwei Beispiele für Operatoren mit Sequenzpunkt sind das logische Und <code>&&</code> und der <code>?</code>-Operator:
<syntaxhighlight lang="C">
int a=0;
bool val = a++*5-1 && func(a);
//Der &&-Operator ist ein Sequenzpunkt, so dass zunächst
//der Ausdruck des linken Operators 'a++*5-1' vollständig berechnet wird,
//bevor der rechte Operator 'func(a)' ausgeführt wird.
//Wird beim logischen UND der linke Operator zu false ausgewertet,
//so kommt der rechte Operator nicht zur Ausführung!
int b=0,c=0;
c=c+++b*5+3 ? c++ : c--;
//Der ?-Operator beinhaltet zwei Sequenzpunkte. Zunächst wird
//der ganz linke Ausdruck 'c+++b*5+3 ausgewertet. Wird dieser
//zu TRUE ausgewertet, wird im Anschluss der mittlere Ausdruck 'c++'
//ausgewertet und der rechte Ausdruck 'c--' entfällt.
//Andernfalls wird nur der rechte Ausdruck ausgewertet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int func(int par) {
return printf("func(%d) called\n",par);
}
int main(int argc,char *argv[]) {
int a=0;
bool val = a++*5-1 && func(a);
//Der &&-Operator ist ein Sequenzpunkt, so dass zunächst
//der Ausdruck des linken Operators 'a++*5-1' vollständig berechnet wird,
//bevor der rechte Operator 'func(a)' ausgeführt wird.
//Wird beim logischen UND der linke Operator zu false ausgewertet,
//so kommt der rechte Operator nicht zur Ausführung!
int b=0,c=0;
c=c+++b*5+3 ? c++ : c--;
//Der ?-Operator beinhaltet zwei Sequenzpunkte. Zunächst wird
//der ganz linke Ausdruck 'c+++b*5+3 ausgewertet. Wird dieser
//zu TRUE ausgewertet, wird im Anschluss der mittlere Ausdruck 'c++'
//ausgewertet und der rechte Ausdruck 'c--' entfällt.
//Andernfalls wird nur der rechte Ausdruck ausgewertet
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Ein weiteres Beispiel ist der Komma-Operator. Hier teilt das Komma den Gesamtausdruck in mehrere Teilausdrücke auf, die nacheinander abgearbeitet werden (siehe
[[Programmieren in C/C++: Grundlagen#Komma-Operator | Komma-Operator]]).
=== Abarbeitungsreihenfolge ===
Die Abarbeitungsreihenfolge der Operatoren innerhalb eines Ausdruckes wird durch die Prioritätenliste/Rangfolge (siehe [[C-Programmierung: _Liste_der_Operatoren_nach_Priorität| C-Programmierung:Liste der Operatoren nach Priorität]]) vorgegeben. Operatoren mit höherer Priorität werden vor Operatoren mit niedriger Priorität ausgeführt. Die ()-Klammer hat die höchste Priorität:
<syntaxhighlight lang="C">
//Der Ausdruck
c = sizeof(x) + ++a / 3;
//wird aufgrund der Prioritäten wie folgt ausgewertet:
c= (sizeof(x)) + ( (++a) / 3);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
int a=2;
int c;
int x=0;
c = sizeof(x) + ++a / 3;
printf("a=%d c=%d\n",a,c);
//Wird aufgrund der Prioritäten wie folgt ausgewertet:
a=2;
c= (sizeof(x)) + ( (++a) / 3);
printf("a=%d c=%d\n",a,c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei identischer Priorität ergibt sich die Abarbeitungsreihenfolge aus der Assoziativität (L-R oder R-L):
<syntaxhighlight lang="C">
a=33 / 5 / 2;
//Wird aufgrund der L-R Assoziativität wie folgt ausgewertet:
//a= (33 / 5) / 2;
//und damit zu 3 und nicht zu 16 (bei 33 / (5/2)) ausgewertet
a = b = c = d*2; //→ a=(b=(c=(d*2)));
a = b = 1+c = d; //→ a=(b=((1+c)=d)); //Compilerfehler, da
//1+c kein lvalue ist
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
a=33 / 5 / 2;
printf("a=%d\n",a);
//Wird aufgrund der Assoziativität wie folgt ausgewertet:
//a= (33 / 5) / 2
printf("a=%d\n",a);
//und damit zu 3 und nicht zu 16 (bei 33 / (5/2)) ausgewertet
int b,c,d=8;
a = b = c = d*2; //→ a=(b=(c=(d*2)));
printf("a=%d b=%d c=%d d=%d\n",a,b,c,d);
a = b = 1+c = d; //→ a=(b=((1+c)=d)); //Compilerfehler, da
//1+c kein lvalue ist
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
An einigen Stellen gibt die C/C++ Spezifikation die Abarbeitungsreihenfolge nicht vor (indeterminately-sequenced), überlässt diese somit dem Compiler:
* Bei Funktionsaufrufen ist die Abarbeitungsreihenfolge der Parameter nicht spezifiziert:
:<syntaxhighlight lang="C">
//Quelle: C-Spec Kap. 6.5.2.2
//Aufrufruf einer Funktion, deren Parameter sich aus Funktionsaufrufen
//ergeben
(*pf[f1()]) (f2(), f3() + f4()); //pf -> Array von Funktionszeigern
//Die Funktionen f1,f2,f3 und f4 können in einer beliebigen Reihenfolge
//aufgerufen werden
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int f1(void) {
printf("f1 called\n");
return 1;
}
int f2(void) {
printf("f2 called\n");
return 2;
}
int f3(void) {
printf("f3 called\n");
return 3;
}
int f4(void) {
printf("f4 called\n");
return 4;
}
void func1(int par1,int par2) {
printf("func1(%d,%d) called\n",par1,par2);
}
void func2(int par1,int par2) {
printf("func2(%d,%d) called\n",par1,par2);
}
int main(int argc,char *argv[]) {
//Quelle: C-Spec Kap. 6.5.2.2
void (*pf[2])(int,int)={func1,func2};
//Aufrufruf einer Funktion, deren Parameter sich aus Funktionsaufrufen
//ergeben
(*pf[f1()]) (f2(), f3() + f4()); //pf -> Array von Funktionszeigern
//Die Funktionen f1,f2,f3 und f4 können in einer beliebigen Reihenfolge
//aufgerufen werden
//Gerne anderen Compiler auswählen, z.B. x86-64 icc...
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Per Postinkrement/-dekrement Operator sagt aus, dass für die eigentliche Operation der Wert der Variablen genutzt wird und im Anschluss die Variable erhöht / erniedrigt werden soll. Nach C-Spezifikation [C11 6.5.2.4] muss dies spätestens vor dem nächsten Sequence Point erfolgt sein. Der genaue Zeitpunkt innerhalb des Sequence Points ist jedoch nicht vorgegeben:
:<syntaxhighlight lang="C">
int a=7;
int b=a++ + a; //Ergebnis Abhängig, ob das Postinkrement vor oder
//nach der Addition ausgeführt wird.
a=a++ + 1; //dito
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
int a=7;
int b=a++ + a; //Ergebnis Abhängig, ob das Postinkrement vor oder
//nach der Addition ausgeführt wird.
a=a++ + 1; //dito
printf("a=%d b=%d\n",a,b);
//Gerne anderen Compiler auswählen, z.B. x86-64 icc...
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Innerhalb einer Initialisierungliste ist Abarbeitungsreihenfolge nicht spezifiziert:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
struct abc var={var.c=1,var.a=2};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc {int a,b,c;};
struct abc var={var.c=1,var.a=2};
printf("var={a=%d b=%d c=%d}\n",var.a,var.b,var.c);
//Gerne anderen Compiler auswählen, z.B. x86-64 icc...
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Compound-Statement ===
Ein Compound-Statement ist innerhalb der C-Spezifikation ein alternativer Ausdruck für ein block-scope. Dieser fasst mehrere Statements und Deklarationen zu einem Statement zusammen:
<code>
Syntax: {Declaration-or-statement-list/textsuperscript<sub>OPT</sub>}
</code>
Ein Block wird nicht wie bei einer Anweisung mit einem Semikolon abgeschlossen (Das angehängte Semikolon wäre dann eine separate leere Anweisung!).
Ein Block hat blockweite Sichtbarkeit (siehe [[Programmieren in C/C++: Grundlagen#Blockweite Sichtbarkeit | Blockweite Sichtbarkeit]]), , so dass hier definierte Variablen nur hier gültig sind. Deklarationen sind ebenfalls nur in dem Block gültig:
<syntaxhighlight lang="C">
void foo(void) {
int var1;
{ //Block innerhalb von Block als Strukturierungswerkzeug
int var1; //Var1 'überdeckt' var1 des äußeren Blockes
struct xyz{int x,y,z;}; //Defintion eines Datentyps im Block
struct xyz var3;
void far(void); //Prototyp
far();
}
struct xyz var4; //KO, Datentyp hier nicht mehr bekannt
far(); //KO, Prototyp hier nicht mehr bekannt
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
void foo(void) {
int var1;
{ //Block innerhalb von Block als Strukturierungswerkzeug
int var1; //Var1 'überdeckt' var1 des äußeren Blockes
struct xyz{int x,y,z;}; //Defintion eines Datentyps im Block
struct xyz var3;
void far(void); //Prototyp
far();
}
struct xyz var4; //KO, Datentyp hier nicht mehr bekannt
far(); //KO, Prototyp hier nicht mehr bekannt
}
int main(int argc,char *argv[]) {
foo();
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Verwendung findet das Compound-Statement a) als Strukturierungsmöglichkeit innerhalb von Funktionen (zur Darstellung, dass dieser Bereich 'zusammengehörig' ist) und b) an den Stellen, an denen C/C++ nur eine Anweisung erwartet. Dies sind bspw. die If- und die For-Anweisungen:
<syntaxhighlight lang="C">
for(..) Anweisung; //For-Schleife führt nur diese eine Anweisung aus
for(…) {Block} //For-Schleife führt Block (als eine Anweisung) aus
if(..) Anweisung; else Anweisung; //IF-Anweisung führt nur 'eine'
//Anweisung aus
if(..) {Block} else {Block} //IF-Anweisung führt Block aus
if( ) {Block}; else {Block}; //Semikolon ist eine separate
//Leer-Anweisung, so dass else
//nicht zur IF-Anweisung zugeordnet
//werden kann (2 Anweisungen vor Else)</syntaxhighlight>
=== Embedded Statement ===
Embedded Statements sind eine GNU-C Erweiterung (siehe [https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html GNU-C-Manual 3.18]). Da diese vom Autor als sehr nützlich angesehen und auch von diversen Compilern und auch in C++ unterstützt werden, werden diese nachfolgend beschrieben.
Ein Compound-Statement fasst mehrere Anweisungen zu einer Anweisung zusammen, hat jedoch kein Rückgabewert. Ein Embedded-Statement entspricht einem Compound-Statement mit der Ergänzung, dass dieser einen Rückgabewert hat, so dass ein Embedded-Statement überall dort eingesetzt werden kann, wo eine Operand erwartet wird.
<code>
Syntax: ({Declaration-or-statement-list<sub>OPT</sub>})
</code>
Der Rückgabewert (und Datentyp) wird nicht über eine return-Anweisung angegeben, sondern entstammt aus dem Rückgabewert der letzten Anweisung innerhalb der Liste:
<syntaxhighlight lang="C">
int var;
var={int par=7;} //KO Block hat keine Rückgabewert.
var=({int par=7; par++; par;}); //OK Embedded-Statement hat einen
//Rückgabewert, der sich aus der
//letzten Anweisung 'Par;' ergibt
//Hier 8.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
int var;
var={int par=7;} //KO Block hat keine Rückgabewert.
var=({int par=7; par++; par;}); //OK Embedded-Statement hat einen
//Rückgabewert, der sich aus der
//letzten Anweisung 'Par;' ergibt
//Hier 8.
printf("var=%d\n",var);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Ein Embedded-Statement ähnelt folglich einem Funktionsaufruf mit dem Unterschied, dass a) in der Tat kein Funktionsaufruf stattfindet und b) der Rückgabewert nicht mit return, sondern über die letzte Anweisung zurückgegeben wird. Der Anwendungsfall ist dort zu finden, wo eine Operand erwartet wird und mehrere Anweisungen zum Ermitteln des Operanden notwendig sind:
<syntaxhighlight lang="C">
int var1=8;
int b=({int d=var1++;d>10?10:d;});
if( ({int d=b;b=var1;b=d;}) > 1)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc,char *argv[]) {
int var1=8;
int b=({int d=var1++;d>10?10:d;});
if( ({int d=b;b=var1;b=d;}) > 1)
printf("Bedingung erfüllt");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Ein Embedded-Statement ist insbesondere bei Nutzung von Makros (siehe Kap [[Programmieren in C/C++: Präprozessor | Präprozessor]]) hilfreich
* Mittels eines Embedded-Statement kann eine anonyme Funktion/Lambdafunktion dargestellt werden:
<syntaxhighlight lang="C">
void test(int (*fptr)(int),int arr[10]) {
for(int lauf=0;lauf<10;lauf++)
arr[lauf]=fptr(arr[lauf]);
}
int main(int argc, char *argv[]) {
int arr[]={1,2,3,4,5,6,7,8,9,10};
//Aufruf mit einer anonymen Funktion
test( ({int func(int a) {return a%2?a:0;} ; func;})
,arr);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
void test(int (*fptr)(int),int arr[10]) {
for(int lauf=0;lauf<10;lauf++)
arr[lauf]=fptr(arr[lauf]);
}
int main(int argc, char *argv[]) {
int arr[]={1,2,3,4,5,6,7,8,9,10};
//Aufruf mit einer anonymen Funktion
test( ({int func(int a) {printf("Called:%d\n",a);return a%2?a:0;} ; func;})
,arr);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Funktionen / Prozeduren ==
Funktionen/Prozeduren sind ein Strukturierungsmerkmal, so dass Teile der Funktionalität des Programmes wiederverwendbar sind. C/C++ unterscheidet nicht zwischen Funktionen (haben einen Rückgabewert, können damit als Operand in Ausdrücken verwendet werden) und Prozeduren (haben keine Rückgabewert, resp. Rückgabetyp void). <br/>
Mit jedem Aufruf einer Funktion wird für den zugehörigen Block ein eigener Stack-Kontext angelegt, so dass Funktionen sich selbst aufrufen können (Rekursion). Jeder Funktionsinstanz hat somit seinen eigenen lokalen Variablenbereich, teilen sich jedoch die globalen und die statisch lokalen Variablen.<br />
Mit dem Aufruf einer Funktion können Parameter übergeben werden, wobei die Übergabeparameter vom Aufrufer (Caller) durch den Aufruf in die lokalen Variablen des Aufgerufenen (Callee) kopiert/zugewiesen werden (Call by Value). Wird ein Zeiger übergeben, hat der Callee über die Dereferenzierung des Zeigers die Möglichkeit, die Variablen des Caller zu verändern (Call by Reference) (siehe Kap. [[Programmieren in C/C++: Zeiger #Zeiger bei Funktionsaufrufen | Zeiger:Zeiger bei Funktionsaufrufen).]]).
Hinweise:
* Die Klammerung hinter dem Funktionsnamen (<code>foo()</code>) zeigt an, dass es sich um einen Funktionsaufruf (Verzweigung der Programmausführung zu der Startadresse der Funktion) handelt:
:<syntaxhighlight lang="C">
void foo(void) {printf("foo called");};
foo(); //Klammern hinter dem Funktionsnamen bedeuten Aufruf der Funktion
</syntaxhighlight>
* Die Nutzung des Funktionsnamens ohne Klammerung (<code>foo</code>) gibt die Startadresse der Funktion zurück. Die Startadresse kann in einem Zeiger auf Funktionen gespeichert werden (siehe Kap. [[Programmieren in C/C++: Zeiger#Zeiger auf Funktionen | Zeiger:Zeiger auf Funktionen]]):
:<syntaxhighlight lang="C">
void foo(void) {printf("foo called");};
void (*fptr)(void)=foo; //Gibt Startadresse der Funktion zurück
//ohne diese aufzurufen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void foo(void) {
printf("foo called");
};
int main(int argc, char *argv[]) {
void (*fptr)(void)=foo; //Gibt Startadresse der Funktion zurück
//ohne diese aufzurufen
fptr(); //Aufruf der Funktion
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Deklaration/Definition vor dem ersten Aufruf der Funktion 'notwendig', damit Compiler die Übergabeparameter entsprechend bereitstellt und ggf. eine implizite Typkonvertierung durchführt (dito Rückgabewert). Die Angabe der Variablennamen können bei der Deklaration entfallen
* Die fehlende Angabe der Übergabeparameter bedeutet in C (bis einschl. C18), dass diese Funktion mit beliebigen Übergabeparametern aufgerufen werden kann und der Compiler keine Typprüfung durchführt:
:<syntaxhighlight lang="C">
int func(/*Keine Übergabeparameter angegeben*/) {...}
//kann wie folgt aufgerufen werden
func();
func(4);
func("hallo Welt",4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func() {
printf("foo called\n");
};
int main(int argc, char *argv[]) {
func();
func(4);
func("hallo Welt",4.7);
//Ab C23 hat sich die Bedeutung geändert.
//Zum Testen C-Versionsvorgabe -sdc=xxx unter Compiler-options aendern
return 0;
} | execCompilerOptions=-Wall -std=c17|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:→ unbedingt vermeiden<br />
:Hat die Funktion keinen Übergabewert, so wird dies in C mit void gekennzeichnet
* In C++ bedeutet die Schreibweise ohne Datentypbeschreibung, dass keine Parameter erwartet werden
* In der Parameterliste von Funktionen dient in der GNU-C Spezifikation das Semikolon zum Trennen zwischen Deklaration von Übergabeparameter und den Übergabeparametern. Alle Übergabewerte links vom Semikolon sind (Forward)deklarationen:
:<syntaxhighlight lang="C">
void test1(int a; int b,int a) {
// Forward; Parameter
printf("a=%d b=%d\n",a,b);
}
//Aufruf
test1(3,7); //a=7 b=3
//Sinnvoll im Umgang mit Variable Length Arrays
void test2(int dim; const char str[dim], int dim);
//Aufruf
test2("hallo",6);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void test1(int a; int b,int a) {
// Forward; Parameter
printf("a=%d b=%d\n",a,b);
}
//Sinnvoll im Umgang mit Variable Length Arrays
void test2(int dim; const char str[dim], int dim) {
printf("dim=%d\n",dim);
}
int main(int argc, char *argv[]) {
//Aufrufe
test1(3,7); //a=7 b=3
test2("hallo",6);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Return-Anweisung ===
Mit der Return-Anweisung wird eine Funktion (vorzeitig) beendet. Der optionale Parameter dient der Angabe des Rückgabewertes der Funktion an den Aufrufer. Der Datentyp des Parameters ergibt sich aus dem Rückgabedatentyp der Funktion.
<code>
Syntax: return expression<sub>OPT</sub>
</code>
Der Rückgabewert expresion sagt aus, dass hier nicht nur Konstanten oder Variablen stehen können, sondern ein komplexer Ausdrücke erlaubt ist. Der resultierende Datentyp des Ausdruckes sollte dem Rückgabedatentyp der Funktion entsprechen, andernfalls wird eine implizite Typkonvertierung vollzogen (sofern möglich):<syntaxhighlight lang="C">
int foo(double a, double b) {
return (int)(a*a+b*b);
}
</syntaxhighlight>
Hinweise:
* Bei nicht void-Funktionen ist eine return-Anweisung mit einer Expression entsprechend dem Datentyp der Funktion zwingend notwendig:
:<syntaxhighlight lang="C">
int func(void) {
return 5.1; //Datentyp wird zuvor int konvertiert
}
double a=func(); //int wird in double konvertiert
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int func(void) {
return 5.1; //Datentyp wird zuvor int konvertiert
}
int main(int argc, char *argv[]) {
double a=func(); //int wird in double konvertiert
printf("a=%f\n",a);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Bei einer void-Funktion ist die return-Anweisung ohne Expression optional. Hier entspricht der schließende Block der Return-Anweisung
:<syntaxhighlight lang="C">
void func(char *str) {
if(str==NULL)
return;
printf("%s",str);
}
</syntaxhighlight>
Sollen mehr als ein Rückgabewert an den Aufrufer zurückgegeben werden so empfiehlt sich:
* die Rückgabewerte in einer Struktur zu packen (siehe [[Programmieren in C/C++: Datentypen#Verbundtyp Struktur/Klasse (nur C++) |Datentypen:Verbundtyp Struktur/Klasse (nur C++)]])
* die Rückgabewerte über die Aufrufparameter als Call-by-Reference zu übergeben (siehe [[Programmieren in C/C++: Zeiger#Zeiger bei Funktionsaufrufen | Zeiger:Zeiger bei Funktionsaufrufen]])
==== Rückgabewert aus Datentypsicht ====
Aus Datentypsicht kann der Funktionsname inkl. den Parameter(n) in einem Ausdruck mit dem Datentyp des Rückgabewertes der Funktion ausgetauscht werden:
<syntaxhighlight lang="C">
int foo(void) {return 4711;}
int var;
var=1+foo(); //Aus Datentypsicht (int)=(int)+(int)
</syntaxhighlight>
Daraus ergibt sich, dass bei Arrays/Strukturen/Unions direkt auf einzelne Komponenten zugegriffen werden kann, ohne diese zuvor einer Variablen zuzuweisen:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;};
struct xyz foo(int par) {
struct xyz var;
var.x=var.y=var.z=par;
return var;
}
if(foo(12).x == 12) printf("Identisch\n");
int *far(size_t par) {
int *ret=malloc(par*sizeof(int));
for(size_t lauf=0;lauf<par;ret[lauf]=lauf,lauf++);
return ret;
}
if(far(3)[2] == 2) printf("Identiisch\n");
//Hinweis: Funktion erzeugt aufgrund des fehlenden free's
//ein MemoryLeak
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stdlib.h>
struct xyz{int x,y,z;};
struct xyz foo(int par) {
struct xyz var;
var.x=var.y=var.z=par;
return var;
}
int *far(size_t par) {
int *ret=malloc(par*sizeof(int));
for(size_t lauf=0;lauf<par;ret[lauf]=lauf,lauf++);
return ret;
}
int main(int argc, char *argv[]) {
if(foo(12).x == 12)
printf("Identisch\n");
if(far(3)[2] == 2)
printf("Identiisch\n");
//Hinweis: Funktion erzeugt aufgrund des fehlenden free's
//ein MemoryLeak
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
==== Fehlerrückgabe ====
Viele Funktionen können unter gewissen Umständen nicht korrekt ausgeführt werden. Z.B. aufgrund dessen, dass:
* der benötigter Speicher vom Heap nicht bereitgestellt werden kann
* Übergabeparameter außerhalb des zulässigen Wertebereiches liegen
* angeforderte Ressource (Datei, Geräte, …) nicht vorhanden/verfügbar sind
Solche Fälle gilt es dem Aufrufer mitzuteilen, da in diesen Fällen die vom Aufrufer geforderte Funktionalität nicht erfüllt ist und der Aufrufer ggf. nicht weiterarbeiten kann. Zur Mitteilung des Fehlers sollte vorrangig der Rückgabewerte genutzt werden. (auch wenn in C++ mit Exception eine Alternative hierzu bereitsteht)
<syntaxhighlight lang="C">
char *strdup(char *src) {
char *dst;
if((dst=malloc(strlen(src)+1))==NULL)
return NULL;
strcpy(dst,src);
return dst;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *strdup1(char *src) {
char *dst;
if((dst=malloc(strlen(src)+1))==NULL)
return NULL;
strcpy(dst,src);
return dst;
}
int main(int argc, char *argv[]) {
char *dup=strdup1("hallo");
if(dup == NULL)
printf("Fehler\n");
else
printf("dup='%s'\n",dup);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C Library-Funktionen geben in diesem Fall zumeist ein -1 (Rückgabewert Ganzzahl) oder einen NULL-Zeiger (Rückgabewert Zeiger) zurück. Der genaue Fehlergrund ist dann ergänzend in der globalen Variablen errno gespeichert. Mittels der Standard-C Funktion strerror() kann die Zahl in einen für den Anwender/Programmierer lesbaren String umgewandelt werden (die GNU-C Library Funktion printf() bietet ergänzend den Conversion Spezifier %m als alternative Ausgabemöglichkeit an):
<syntaxhighlight lang="C">
#include <errno.h>
int var;
if(-1==scanf("%d",&var) ) printf("Es wurde keine Zahl erkannt\n");
int ret=open("/etc/ptmp",O_WRONLY|O_CREAT|O_EXCL,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if(-1==ret)
printf("open failed() with %s\n",strerror(errno));
if(-1==ret)
printf("open failed() with %m (nur glibc)\n");
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[]) {
int var;
if(-1==scanf("%d",&var) ) printf("Es wurde keine Zahl erkannt\n");
int ret=open("/etc/ptmp",O_WRONLY{{!}}O_CREAT{{!}}O_EXCL,
S_IRUSR{{!}}S_IWUSR{{!}}S_IRGRP{{!}}S_IROTH);
if(-1==ret)
printf("open failed() with %s\n",strerror(errno));
if(-1==ret)
printf("open failed() with %m (nur glibc)\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
'''Für eine sauber Programmierung sollte diese Methodik generell angewendet werden.''' Jede Funktion, welche Fehlschlagen kann, teilt dies per Rückgabewert dem Aufrufer mit. Der Rückgabewert einer jeden Funktion wird vom Aufrufer kontrolliert.
=== Main-Funktion ===
Mit Start der Anwendung übergibt das Betriebssystem die Kontrolle an die Anwendung und führt dort die Funktion main aus. Als Übergabe- und Rückgabeparameter sind folgende Varianten erlaubt:
<syntaxhighlight lang="C">
int main(void) { }
int main(int argc, char *argv[]) { }
</syntaxhighlight>
Mit dem Start der Anwendung kann, wie bei jedem Funktionsaufruf, Parameter an den startenden Prozess übergeben werden. Die Parameter werden als Array von Strings übergeben. Im Parameter argc ist die Anzahl der Strings enthalten. Im Parameter argv[0..argc-1] sind die einzelnen Strings enthalten. Sofern vorhanden ist im ersten String der Programmname/Aufrufname der Anwendung enthalten:
<syntaxhighlight lang="C">
int main(int argc, char *argv[]) {
//Variante 1: Darstellung des Inhaltes des Arrays von Strings
for(int lauf=0;lauf < argc; lauf++)
printf("%d.Parameter: '%s'\n",lauf,argv[lauf]);
//Variante 2: Darstellung des Inhaltes des Arrays von Strings
(void)argv; //Wird hier nicht benötigt
for(char **str=argv;*str!=NULL;str++)
printf("Parameter: '%s'\n",*str);
return EXIT_SUCCESS;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int max_width=0;
int ret;
//Variante 1: Darstellung des Inhaltes des Arrays von Strings
for(int lauf=0;lauf < argc; lauf++) {
ret=printf("%d.Parameter: '%s'\n",lauf,argv[lauf]);
max_width=ret>max_width ? ret : max_width;
}
//Trennzeichen drucken
char term[max_width];
memset(term,'-',max_width);
printf("%.*s\n",max_width-1,term);
//Variante 2: Darstellung des Inhaltes des Arrays von Strings
(void)argv; //Wird hier nicht benötigt
for(char **str=argv;*str!=NULL;str++)
printf("Parameter: '%s'\n",*str);
return EXIT_SUCCESS;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im Compiler-Explorer können die Parameter im Executor unter 'Execution Arguments', getrennt mit Leerzeichen eingegeben werden.
Wird die Funktion main beendet, entweder über die return Anweisung oder den Aufruf der exit() Funktion, wird die Kontrolle zurück an den startenden Prozess (zumeist Shell) gegeben. Über den Rückgabewert wird im Allgemeinen dem Aufrufer der Fehlerstatus mitgeteilt (EXIT_SUCCESS oder 0 bedeutet fehlerfreie , EXIT_FAILURE oder Werte ungleich 0 fehlerhafte Ausführung).
Hinweise:
* Der Return-Wert der main-Funktion kann mit >>echo $? in der Bash abgefragt werden
* Mittels <code>exit(int status)</code> kann das Programm an jeder Stelle innerhalb des Programms beendet werden. <code>status</code> entspricht dann der expression der return Anweisung von main()
* Ungeachtet des Rückgabedatentyps int bei der Defintion der main() Funktion beträgt der zulässige Wertebereich für Linux Anwendungen 0..255. Der korrekte Rückgabedatentyp der main() Funktion müsste somit 'unsigned char' lauten
=== Inline Funktion ===
Wie der Name inline andeutet, ist die Intention von Inline, dass die aufgerufen Funktion Bestandteil der aufrufenden Funktion ist. Die aufgerufene Funktion soll somit im Kontext des Aufrufers ausgeführt werden, so dass kein eigener Stack bereitgestellt werden muss. Der Start der Funktion kann somit schneller erfolgen:
<code>
inline int foo(void) { }
</code>
Das Funktionseinbindung/zusammenführung erfolgt durch den Compiler (und nicht durch den Linker). Damit das inline vom Compiler ausgeführt werden kann, muss die zu inlinende Funktion vor dem Aufruf definiert sein, d.h. sie muss in derselben C-Datei oder in einer der einzubindenden Header-Dateien enthalten sein [C11 6.7.4].
Hinweis:
* Das 'inlinen' von Funktionen über die eigene Objektdatei hinweg erfolgt in C/C++ über Link Time Optimization (LTO). Hierzu fügt der Compiler den Zwischencode mit in die Objektdatei, so dass der Linker das 'inlinen' vollziehen kann (siehe {{w|lang=en|Interprocedural_optimization| Interprocedural Optimization}})
=== Variadic Function / Ellipsis Punctuator ===
Mit dem Ellipsis Puncturator '…' kann in Funktionsdefinitionen angegebenen werden, dass an dieser Stelle beliebig viele Parameter/Argumente übergeben werden können. Dies wird unter anderen in der printf() Anweisung genutzt:
<syntaxhighlight lang="C">
int printf(const char *fmt, ... );
</syntaxhighlight>
Die wie folgt aufgerufen werden kann:
<syntaxhighlight lang="C">
printf("Hello World"); //es folgt kein Parameter
printf("%d",100); //es folgt ein Parameter vom Datentyp int
printf("%f",1.1); //es folgt ein Parameter vom Datentyp double
printf(conststr,1,2,3,"xyz") //Ohne Worte
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World\n"); //es folgt kein Parameter
printf("%d\n",100); //es folgt ein Parameter vom Datentyp int
printf("%f\n",1.1); //es folgt ein Parameter vom Datentyp double
const char *conststr="%d %x %c '%s'\n";
printf(conststr,1,2,33,"xyz"); //Ohne Worte
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei der Parameterübergabe wird der Datentyp nicht mit übergeben, so dass die aufgerufene Funktion keine Möglichkeit hat, den Datentype der Parameter zur Laufzeit zu ermitteln. Einzig werden bei Aufruf der variadischen Funktion so viel Bytes auf den Stack gelegt, wie der Datentyp der einzelnen Übergabeparameter groß ist:
:<code>int --> 4 Byte</code>
:<code>double --> 8 Bytes</code>
:<code>Zeiger --> 4/8 Byte</code>
Damit die aufgerufene Funktion die fehlende Datentypinformation dennoch mitgeteilt bekommt, erfolgt dies am Beispiel der printf Funktion über den Format-String:
<syntaxhighlight lang="C">
int vari;
printf("%d",vari); //%d erwartet einen Integer Übergabeparameter (4-Byte)
size_t vars;
printf(" %zu %d ", vars, vari); // %zu zur Mitteilung, dass anstatt
//integer nun size_t als Datentyp übergeben wird
//und somit anstatt 4 Bytes 8 Bytes vom Stack genommen werden
</syntaxhighlight>
<code>printf()</code> entnimmt entsprechend der Datentypbeschreibung im Formatstring die passende Anzahl an Bytes vom Stack.
Da der Compiler für die optionalen Parameter nicht den Zieldatentyp kennt, erlaubt die C-Spezifikation als Übergabedatentypen hier nur die Grunddatentypen <code>signed int, unsigned int, long, long long, double</code> und <code>Zeiger</code>. Entspricht der übergebene Parameter nicht einen dieser Datentypen, so wird er mittels implizit Cast entsprechend nachfolgender Tabelle gewandelt [C11 6.5.2.2 Default Argument Promotions]:
{| class="wikitable"
|-
! Ausgangstyp !! Umwandlungstyp
|-
| char, signed char, short || int
|-
| unsigned char, unsigned short || unsigned int
|-
| float || double
|-
| Alle anderen Datentypen || bleiben erhalten
|}
Bspw.:
<syntaxhighlight lang="C">
signed char varc=-1;
float varf =0.1;
printf("%d %f",varc, varf); //varc wird beim Aufruf nach int konvertiert!
//varf wird beim Aufruf nach double konvertiert!
//Über den Length-Modifier Parameter im Formatstring kann printf mitgeteilt
//werden, dass von dem übergebenem Integerwert weniger Bytes zu
//interpretieren sind
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
signed char varc=-1;
float varf =0.1;
printf("%d %f",varc, varf); //varc wird beim Aufruf nach int konvertiert!
//varf wird beim Aufruf nach double konvertiert!
//Zur Darstellung der besagten Konvertierung siehe rechtes Fenster
return 0;
} | execCompilerOptions=-Wall|
h=g
}} Öffnen im Compiler Explorer] }}
Zum Umgang mit dem variadischen Parameter stellt C die Funktionen <code>va_start(), va_arg(), va_copy()</code> und <code>va_end()</code> bereit. Auf Grundlage des dazugehörigen Datentyps <code>va_list</code> können variadische Parameter auch an Unterfunktionen weitergereicht werden (bspw vprintf()). Dieses Thema bedingt jedoch genaue Kenntnisse vom Umgang mit dem Stack und ist nicht Bestandteil dieser Vorlesung.
=== Funktion in Funktion ===
Die GNU-C Reference (nicht C++) erlaubt es, Funktionen innerhalb von Blöcken (und damit innerhalb von Funktionen) zu definieren. Diese innere Funktion steht dann nur in diesem Block zur Verfügung und kann von außerhalb des Blockes nicht aufgerufen werden. Als Gimmick können Funktionen in Funktionen auf die zuvor definierten lokalen Variablen der inkludierenden Funktion zugreifen:
<syntaxhighlight lang="C">
void foo(void) {
{
int label=1;
//Funktion innerhalb einer Funktion
void dummy(void){
label++; //Zugriff auf Variablen des umschließenden Blockes
}
dummy(); //Aufruf der nur in diesem Block gültigen Funktion
}
dummy(); //KO, Funktion hier nicht mehr gültig
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void foo(void) {
{
int label=1;
//Funktion innerhalb einer Funktion
void dummy(void){
label++; //Zugriff auf Variablen des umschließenden Blockes
}
dummy(); //Aufruf der nur in diesem Block gültigen Funktion
}
dummy(); //KO, Funktion hier nicht mehr gültig
}
int main(int argc,char *argv[]) {
foo();
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Variable Length Array (VLA) ==
Im Normalfall ergibt sich die Anzahl der Elemente eines Arrays aus einer Konstanten, so dass der Compiler zur Compilezeit passend Speicher reserviert (siehe Kap. [[Programmieren in C/C++: Array | Array]]):
<syntaxhighlight lang="C">
int arr[4]; //Compiler reserviert für Variable arr
//4*sizeof(int) Speicherplatz
</syntaxhighlight>
Bei Variable Lenght Array wird die Arraydimension nicht über eine Konstante, sondern über eine Variable oder einen Ausdruck angegeben. D.h. die tatsächliche Dimension des Arrays ergibt sich erst zum Ausführungszeitpunkt der Definition:
<syntaxhighlight lang="C">
void foo(size_t n) {
int arr[n*2+1]; //Arraydimension ergibt sich zum Ausführungszeitpunkt
n++; //Nachträgliches Ändern von n ändert nicht
//die Größe des Arrays!
}
</syntaxhighlight>
Ein Variable Length Array kann nur als lokale Variable oder als Übergabeparameter definiert werden (wobei im letzteren Fall kein Speicher hiermit reserviert wird). Eine Initialisierung eines VLA's mit der Definition ist nicht möglich, d.h. nach der Definition beinhaltet das Array 'zufällige' Werte. Es empfiehlt sich daher, diese bspw. mit memset händisch zu initialisieren (siehe auch Kap [[Programmieren in C/C++: Array#Initialisierung | Array:Initialisierung]]):
<syntaxhighlight lang="C">
void foo(size_t n) {
char str[n];
memset(str,0,n*sizeof(char)); //Array mit 0 füllen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
void foo(size_t n) {
char str[n];
memset(str,0,n*sizeof(char)); //Array mit 0 füllen
for(size_t lauf=0;lauf<n;lauf++)
printf("str[%zu]=%d\n",lauf,str[lauf]);
}
int main(int argc, char *argv[]) {
foo(4);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mittels sizeof kann weiterhin der Speicherbedarf ermittelt werden, wobei sizeof mit einem VLA als Argument kein Konstantenausdruck ist. Stattdessen wird die Größe zur Laufzeit ermittelt:
<syntaxhighlight lang="C">
void foo(size_t n) {
int arr[n*2+1]; //VLA
size_t size;
size=sizeof(arr); //sizeof(arr) entspricht einem Funktionsaufruf
//welcher die Speichergröße des VLA's ermittelt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void foo(size_t n) {
int arr[n*2+1]; //VLA
size_t size;
size=sizeof(arr); //sizeof(arr) entspricht einem Funktionsaufruf
//welcher die Speichergröße des VLA's ermittelt
printf("size=%zu\n",size);
}
int main(int argc, char *argv[]) {
foo(5);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
VLA wurden erstmals in C mit C99 eingeführt. In C11 wurden VLA's als optional eingestuft und mit C23 zurück auf notwendig gesetzt. In C++ sind VLA's nicht definiert, werden jedoch vom GCC Compiler unterstützt. Als alternativen Datentyp wird hier std::array empfohlen.
Hinweis:
* VLA sind nicht direkt in einem Switch-Case Block definierbar. Wird hier ein VLA benötigt, so muss hierzu ein Block erzeugt werden:
:<syntaxhighlight lang="C">
switch(value) {
case 1:
char arr1[value]; //Compilerfehler, da bei value!=1 kein Speicherplatz
//für das VLA reserviert wird
break;
case 2: {
char arr2[value]; //OK
}
break;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int value=argc;
switch(value) {
case 1:
char arr1[value]; //Compilerfehler, da bei value!=1 kein Speicherplatz
//für das VLA reserviert wird
break;
case 2: {
char arr2[value]; //OK
}
break;
}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Operatoren ==
In der Programmiersprache C sind folgende Punctuators [C11 6.4.6] definiert:
<syntaxhighlight>
[ ] ( ) { } . ->
++ -- & * + - ~ !
/ % << >> < > <= >= == != ^ | && ||
? : ; ...
= *= /= %= += -= <<= >>= &= ^= |= , # ##
<: :> <% %> %: %:%:
</syntaxhighlight>
Die Funktionalitäten sind identisch zu Java. Aufgrund des Datentyps Zeiger gibt es in C ergänzend den Punctuator <code>-></code> (siehe Kap [[Programmieren in C/C++: Datentypen#Verbundtyp Struktur/Klasse (nur C++)|Datentypen:Verbundtyp Struktur/Klasse (nur C++)]]). Der Präprozessor bedingt die beiden Punctuatoren <code>#</code> und <code>##</code> (siehe Kap [[Programmieren in C/C++: Präprozessor | Präprozessor]]).
Die letzten 6 Punctuators <code><: :> <% %> %: %:%:</code> werden zu <code>[ ] { } # ##</code> ersetzt. Sie sind für Computersysteme gedacht, welche keine ALTGR-Taste besitzen.<br />
Java kennt ergänzend den <code>>>></code> Operatoren, welcher in C über den normalen Schiebebefehl und den zugrundeliegenden Datentyp gesteuert wird.
Wie in Java sind einige Punctuators vom Kontext abhängig und haben damit unterschiedliche Funktionalitäten:
<syntaxhighlight>
++ → (Postfix) ++ vs. ++(Präfix)
-- → (Postfix) -- vs. --(Präfix)
+/- → Vorzeichen vs. Addition/Subtraktion
() → Funktionsaufruf() vs. Befehlsbestandteil if() vs. Priorisierung
</syntaxhighlight>
Für den Umgang mit dem Datentyp Zeiger besitzen einige Punctuatoren ergänzende Funktionalitäten (siehe Kap [[Programmieren in C/C++: Zeiger| Zeiger]]):
<syntaxhighlight>
& → Bitweises UND:
Anwendung: Ganzahlausdruck & Ganzahlausdruck
& → Adressoperator:
Anwendung: &Variable
* → Multiplikation
Anwendung: Ganzahl-/Gleitkommaausdruck * Ganzahl-/Gleitkommaausdruck
* → Datentyp Zeiger
Anwendung: Datentyp * Variablenname;
* → Dereferenzierung:
Anwendung: * Zeiger
</syntaxhighlight>
Punctuatoren, welche von Java abweichende / ergänzende Funktionalitäten haben, werden nachfolgend gesondert beschrieben.
Sind in einer Anweisung mehrere Operatoren enthalten, so hängt die Abarbeitungsreihenfolge von der Rangfolge/Priorität der Operatoren ab (siehe [[Programmieren in C/C++: Grundlagen#Abarbeitungsreihenfolge | Abarbeitungsreihenfolge]]).<br />
Die Rangfolge ist identisch zu Java, wobei C mehr Operatoren kennt. Generell empfiehlt sich, lieber eine Klammer zu viel als zu wenig zusetzen. Klammern haben die höchste Priorität.
=== Zuweisungs-Operator ===
Die Zuweisung ('='-Operator, assignment expression) weist dem L-Value den R-Value zu.
Der Zuweisungs-Operator gibt den L-Value als Rückgabewert der Zuweisung zurück, so dass mehrere Zuweisungen in einem Ausdruck möglich sind. Die Abarbeitungsreihenfolge ist von rechts nach links (R-L Assoziativität). Wird der 'letzte' Rückgabewert nicht verwendet, so wird dieser verworfen (siehe Kap. [[Programmieren in C/C++: Grundlagen#Discarded Value / null statement | Discarded Value / null statement]]).<br />
Beispiel:
<syntaxhighlight lang="C">
a=7; //Zuweisung
a=b=7; //Erste Zuweisung (b=7) hat einen Rückgabewert, welcher im
//Anschluss a zugewiesen wird
if(a=7) //Variablen a wird der Wert 7 zugewiesen. Der Rückgabewert
//der Zuweisung wird im Anschluss auf True oder False geprüft
if(7=a) //Besser, da aufgrund der fehlerhafter Zuweisung ein
//Compilerfehler geworfen wird
x*=y=z //entspricht x=x*(y=z)
a=b=d+7; //entspricht a=(b=(d+7))
a=b==c; //a bekommt das boolesche Ergebnis der Vergleichsoperation
//zugewiesen
a=7+b=8; //Fehler, da der Zuweisungs-Operator die zweitniedrigste Priorität hat
//Abarbeitungsreihenfolge: a=(7+b)=8 -> 7+b kann keinen Wert zugewiesen werden
a=7+(b=8);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int a,b,c=3,d=4;
int x,y,z;
a=7; //Zuweisung
a=b=7; //Erste Zuweisung (b=7) hat einen Rückgabewert, welcher im
//Anschluss a zugewiesen wird
if(a=7) //Variablen a wird der Wert 7 zugewiesen. Der Rückgabewert
; //der Zuweisung wird im Anschluss auf True oder False geprüft
if(7=a) //Besser, da aufgrund der fehlerhafter Zuweisung ein
; //Compilerfehler geworfen wird
x*=y=z; //entspricht x=x*(y=z)
a=b=d+7; //entspricht a=(b=(d+7))
a=b==c; //a bekommt das boolesche Ergebnis der Vergleichsoperation
//zugewiesen return 0;
a=7+b=8; //Fehler, da der Zuweisungs-Operator die zweitniedrigste Priorität hat
//Abarbeitungsreihenfolge: a=(7+b)=8 -> 7+b kann keinen Wert zugewiesen werden
a=7+(b=8);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Auf beiden Seiten der Zuweisung muss der identische Datentyp stehen. Wenn andernfalls eine implizite Typkonvertierung nicht möglich ist, gibt der Compiler einen Fehler aus:
:<syntaxhighlight lang="C">
int a = 7.3; //implizite Typkonvertierung
double b=a+3; //Implizite Typkonvertierung der Intergeraddition nach double
float c=(float)a+(float)3; //Explizite Typkonvertierung
char *d=a; //Compilerfehler, da Integerwert nicht implizit in einen
//Zeiger konvertiert werden kann
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int a = 7.3; //implizite Typkonvertierung
double b=a+3; //Implizite Typkonvertierung der Intergeraddition nach double
float c=(float)a+(float)3; //Explizite Typkonvertierung
char *d=a; //Compilerfehler, da Integerwert nicht implizit in einen
//Zeiger konvertiert werden kann
//Zur Darstellung der besagten Konvertierung siehe rechtes Fenster
(void)b;
(void)c;
(void)d;
return 0;
} | execCompilerOptions=-Wall|
h=g
}} Öffnen im Compiler Explorer] }}
* Bei der Parameterübergabe beim Funktionsaufruf wird ebenfalls indirekt der Zuweisungs-Operator angewendet. Die Parameter des Aufrufers werden per Zuweisung den lokalen Variablen der aufgerufenen Funktion zugewiesen
:<syntaxhighlight lang="C">
void func(int a, float b) {
printf("a=%d b=%f",a,b);
}
int x=4;
float y=5.0;
func(x,y); //der Inhalt der Variablen x wird der lokalen Variable a
//(a=x) und der Inhalt der Variablen y der lokalen Variablen b
//(b=y) zugewiesen.
func(y,x); //Dito, mit der Ergänzung, dass eine implizite Typkonvertierung
//stattfindet (a=(int)y) und (b=(float)x).
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int a, float b) {
printf("a=%d b=%f",a,b);
}
int main(int argc, char *argv[]) {
int x=4;
float y=5.0;
func(x,y); //der Inhalt der Variablen x wird der lokalen Variable a
//(a=x) und der Inhalt der Variablen y der lokalen Variablen b
//(b=y) zugewiesen.
func(y,x); //Dito, mit der Ergänzung, dass eine implizite Typkonvertierung
//stattfindet (a=(int)y) und (b=(float)x).
//Zur Darstellung der besagten Konvertierung siehe rechtes Fenster
return 0;
} | execCompilerOptions=-Wall|
h=g
}} Öffnen im Compiler Explorer] }}
=== Komma-Operator ===
Der Komma-Operator erlaubt es, zwei Ausdrücke auszuführen, wo nur einer erlaubt wäre. Die Ergebnisse/Rückgabewerte aller durch diesen Operator verknüpften Ausdrücke, außer dem letzten werden verworfen. Der letzte Ausdruck dient als Rückgabewert.
Folgendes gilt es bei der Nutzung des Komma-Operators zu beachten:
* Der Komma-Operator wird von links nach rechts ausgewertet (L-R Assoziativität)
* Das Komma selbst stellt eine Sequence Point dar (siehe Kap [[Programmieren in C/C++: Grundlagen#Sequence Point|Sequence Point]])
* An Stellen, wo das Komma zum Syntax gehört (z.B. Trennung der Übergabeparameter bei der Funktionsdefinition und beim Funktionsaufruf, Trennung von Variablen bei der Variablendefinition/-deklaration, Trennung der enum Konstanten) muss der Ausdruck ergänzend geklammert werden, wenn der Komma-Operator gefordert ist
* Der Komma-Operator hat von allen Operatoren die niedrigste Priorität/Rangfolge, so dass dieser Operator als letztes 'ausgewertet' wird
Beispiel:
<syntaxhighlight lang="C">
int a=(5,3); //5 wird verworfen, 3 dient als Rückgabewert, so dass
//a den Wert 3 erhält.
int b=5,3; //KO, da das Komma hier zur Trennung der Variablen dient
//und nicht als Komma-Operator fungiert
int c=1,d=2,e=3;
int f=(c+=2,a+a); //c um zwei erhöht, a+a in f
int g= c+=2,a+a; //KO, da Komma Bestandteil der Defintion ist
void func(int value){}
func(1); //Funktion wird mit dem Wert 1 aufgerufen
func(1,2); //KO, da Komma Bestandteil des Funktionsaufrufes ist
func((1,2)); //Funktion wird mit dem Wert 2 aufgerufen
int arr[12];
arr[3,4]=1; //3 wird verworfen, 4 dient als Index für das Array
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int value){
printf("func called with %d\n",value);
}
int main(int argc, char *argv[]) {
int a=(5,3); //5 wird verworfen, 3 dient als Rückgabewert, so dass
//a den Wert 3 erhält.
int b=5,3; //KO, da das Komma hier zur Trennung der Variablen dient
//und nicht als Komma-Operator fungiert
printf("a=%d\n",a);
int c=1,d=2,e=3;
printf("c=%d,d=%d,e=%d\n",c,d,e);
int f=(c+=2,a+a); //c um zwei erhöht, a+a in f
printf("c=%d,f=%d\n",c,f);
int g= c+=2,a+a; //KO, da Komma Bestandteil der Defintion ist
func(1); //Funktion wird mit dem Wert 1 aufgerufen
func(1,2); //KO, da Komma Bestandteil des Funktionsaufrufes ist
func((1,2)); //Funktion wird mit dem Wert 2 aufgerufen
int arr[12];
arr[3,4]=1; //3 wird verworfen, 4 dient als Index für das Array
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
'Sinnvolle' Anwendungsbeispiele:
* Bei For-Schleifen, so dass mehrere Variablen initialisiert und mehrere Variablen mit jedem Schleifendurchlauf geändert werden können:
:<syntaxhighlight lang="C">
int sum,lauf;
int arr[]={5,4,3,2,1};
for(sum=100,lauf=5 ; lauf ; lauf--,sum+=arr[lauf]);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int sum,lauf;
int arr[]={5,4,3,2,1};
for(sum=100,lauf=5 ; lauf ; lauf--,sum+=arr[lauf])
printf("sum=%d lauf=%d\n",sum,lauf);
printf("sum=%d\n",sum);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Bei der Return-Anweisung, bei welcher zur Darstellung der Zusammengehörigkeit mehrere Aktionen ausgeführt werden sollen:
:<syntaxhighlight lang="C">
return errno=EINVAL,-1;
return printf("Fehler"),-1;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <errno.h>
int foo(void) {
return errno=EINVAL,-1;
}
int far(void) {
return printf("Fehler\n"),-1;
}
int main(int argc, char *argv[]) {
printf("foo()=%d\n",foo());
printf("far()=%d\n",far());
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* An Stellen, wo nur eine Anweisung erlaubt ist (und man zu faul ist, einen Block zu öffnen)
:<syntaxhighlight lang="C">
if(…) y=2,z=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int y=0,z=0;
if(1) y=2,z=3;
printf("y=%d z=%d\n",y,z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* In vielen Ländern wird das Komma zur Darstellung von Gleitkommazahlen genutzt. Wird versehentlicher Weise dies in C/C++ übernommen, so führt dies zu einem unerwarteten Verhalten:
:<syntaxhighlight lang="C">
double var;
var=5.3; //Variable wird mit 5.3 initialisiert
var=5,3; //KO, da Komma Bestandteil der Defintion ist
var=(5,3); //Variable wird mit 3 initialisiert
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
double var;
var=5.3; //Variable wird mit 5.3 initialisiert
printf("var=%f\n",var);
var=5,3; //KO, da Komma Bestandteil der Defintion ist
var=(5,3); //Variable wird mit 3 initialisiert
printf("var=%f\n",var);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== ?-Operator / Conditional-Operator ===
Operator mit 3 Operanden, welcher in Abhängigkeit des ersten Ausdruckes den zweiten oder dritten Ausdruck ausführt und dessen Rückgabewert zurückgibt.
<code>
Syntax: Logical-OR-expression ? expression : condition-expression
</code>
Entspricht der if()-Anweisung, wobei der ?-Operator als solches einen Wert zurückgibt! <code>Expression</code> wird nur ausgeführt, wenn <code>Logical-OR-Expression</code> zu true ausgewertet wird. Andernfalls wird <code>condition-expression</code> ausgeführt. Der zurückgegebene Datentyp ergibt sich aus der <code>expression</code> resp. <code>condition-expression</code>. '''Beide Ausdrücke sollten somit einen identischen resultierenden Datentyp besitzen!'''
Folgendes gilt es bei der Nutzung des ?-Operators zu beachten:
* Der Datentyp <code>expression</code> und <code>condition-expression</code> sollte identisch sein:
<syntaxhighlight lang="C">
int a=5;
a=a > 10 ? "String" : 4; //KO, "String" ist vom Datentyp (char*) und
// 4 ist vom Datentyp (int).
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int a=5;
a=a > 10 ? "String" : 4; //KO, "String" ist vom Datentyp (char*) und
// 4 ist vom Datentyp (int).
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Nach der GNU-C Reference kann der mittlere Ausdruck fehlen. In diesem Fall wird stattdessen das Ergebnis des linken Operanden dort eingesetzt (siehe https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals)
<syntaxhighlight lang="C">
int a=13;
int b=a>10 ? : 0; //wenn a > 10 wird true, andernfalls false zurückgegeben
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int a=13;
int b=a>10 ? : 0; //wenn a > 10 wird true, andernfalls false zurückgegeben
printf("b=%d\n",b);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In der Abarbeitungsreihenfolge liegt der ?-Operator oberhalb der Komma- und des Zuweisungsoperators. Soll im <code>condition-expresion</code> Ausdruck der Komma- oder Zuweisung-Operator genutzt werden, so ist <code>condition-expression</code> zu klammern. Andernfalls bedingt die niedrige Priorität des Komma-Operators ein anders Verhalten, als erwartet:
<syntaxhighlight lang="C">
int a=7,max=5,var;
max=a>max ? a : max; //Alles bestens
var= a>5 ? a++,5:6; //Alles bestens
var= a>5 ? a++ :6,a=1; //Komma- und Zuweisungsoperator haben
//niedrigere Priorität, so das der
var=(a>5 ? a++ :6),a=1; //Ausdruck wie folgt interpretiert wird
var= a>5 ? a++ :(6,a=1); //Andernfalls Klammerung hilfreich!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int a=7;
int max=5;
max=a>max ? a : max; //Alles bestens
printf("max=%d\n",max);
int var;
var= a>5 ? a++,5:6; //Alles bestens
printf("var=%d a=%d\n",var,a);
var= a>5 ? a++ :6,a=1; //Komma- und Zuweisungsoperator haben
//niedrigere Priorität, so das der
printf("var=%d a=%d\n",var,a);
var=(a>5 ? a++ :6),a=1; //Ausdruck wie folgt interpretiert wird
printf("var=%d a=%d\n",var,a);
var= a>5 ? a++ :(6,a=1); //Andernfalls Klammerung hilfreich!
printf("var=%d a=%d\n",var,a);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Nutzung des ?-Operators empfiehlt sich an diversen Stellen:
* Bei Makros:
:<syntaxhighlight lang="C">
#define MAX(a,b) (a>b?a:b)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#define MAX(a,b) (a>b?a:b)
int main(int argc, char *argv[]) {
printf("MAX(4,5)=%d\n",MAX(4,5));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Beim Fehlerhandling:
:<syntaxhighlight lang="C">
char *str=strstr("hallo123","lox");
//Ausgabe von str nur, wenn Suche erfolgreich (str!=NULL) war
printf("%s",str!=NULL?str : "(not found)" );
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *str=strstr("hallo123","lox");
//Ausgabe von str nur, wenn Suche erfolgreich (str!=NULL) war
printf("%s",str!=NULL?str : "(not found)" );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Prüfen, ob eine Funktion erfolgreich ausgeführt wurde, bevor eine weitere Funktion ausgeführt wird:
<syntaxhighlight lang="C">
int ret;
ret=init1(); //im Fehlerfreien gibt init1() 0 zurück
ret=ret?:init2(); //Aufruf von init2() nur wenn ret==0 ist
//andernfalls wird ret zurückgegeben
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int init1(void) {
printf("init1() called\n");
return 0;
}
int init2(void) {
printf("init2() called\n");
return 0;
}
int main(int argc, char *argv[]) {
int ret;
ret=init1(); //im Fehlerfreien gibt init1() 0 zurück
ret=ret?:init2(); //Aufruf von init2() nur wenn Ret==0 ist
//andernfalls wird Ret zurückgegeben
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Logische Verknüpfungen ===
Alle logischen Operationen nutzen als Operanden Ganzzahlen ,Gleitkommazahlen oder Zeiger. Der Operand wird als false angesehen, wenn der Operand 0, 0.0 oder NULL ist. Andernfalls als true. Das Ergebnis ist immer vom Datentyp int und hat den Wert von 0 oder 1.
<code>Syntax: Expression && Expression</code><br />
<code>Syntax: Expression || Expression</code><br />
<code>Syntax: ! Expression</code><br/>
Bei der logischen UND und ODER Verknüpfung wird zuerst der linke Ausdruck ausgewertet (Operator ist ein Sequence Point). Der rechte Ausdruck wird nur ausgeführt, wenn:
* bei der logischen UND Verknüpfung der linke Ausdruck TRUE ergab
* bei der logische OR Verknüpfung der linke Ausdruck FALSE ergab
Andernfalls steht das Ergebnis schon mit der Auswertung des linken Operanden fest.<br />
In der theoretischen Informatik wird dies 'Non-strict-evaluation' genannt, bei welcher der Rückgabewert feststeht, bevor alle Ausdrücke bearbeitet worden sind.
Beispiel für das Verhalten des Ausbleibens der Auswertung des zweiten Operators:
<syntaxhighlight lang="C">
int a=0,b=0;
//a=-1; //Als alternativer Startwert
if(++a || ++a)
b=1;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int a=0,b=0;
//a=-1; //Als alternativer Startwert
if(++a {{!}}{{!}} ++a)
b=1;
printf("a=%d b=%d\n",a,b);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Diese Funktionalität ist insbesondere beim Umgang mit Fehlern vorteilhaft:
* Prüfen, ob eine Variable einen gültigen Wert hat, bevor sie weiterverwendet wird
<syntaxhighlight lang="C">
char *str = strstr("hallo123","la");
if(str!=NULL && strlen(str) )
printf("Len = %ld",strlen(str));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *str = strstr("hallo123","la");
if(str!=NULL && strlen(str) )
printf("Len = %ld",strlen(str));
else
printf("Kein Substring im String gefunden\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Prüfen, ob eine Funktion erfolgreich ausgeführt wurde, bevor eine weitere Funktion aufgerufen wird:
<syntaxhighlight lang="C">
int ret;
ret=init1(); //Bei erfolgreicher Initialisierung wird 1 zurückgegeben
ret=ret && init2();
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int init1(void) {
printf("init1() called\n");
return 1;
}
int init2(void) {
printf("init1() called\n");
return 1;
}
int main(int argc, char *argv[]) {
int ret;
ret=init1(); //Bei erfolgreicher Initialisierung wird 1 zurückgegeben
ret=ret && init2();
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Bitweise Verknüpfungen ===
Alle bitweisen Operationen nutzen als Operanden Ganzzahlen. Bei vorzeichenbehafteten Zahlen ist das Ergebnis nach [C11 6.5] Implementierungsabhängig, wobei das Vorzeichenbit zumeist als eigenständiges Bit angesehen wird und bei UND/ODER/EXOR als normales BIT betrachtet wird.
<code>Syntax: Ganzzahl & Ganzzahl → Bitweise UND Operation</code><br />
<code>Syntax: Ganzzahl | Ganzzahl → Bitweise ODER Operation</code><br />
<code>Syntax: Ganzzahl ^ Ganzzahl → Bitweise EXOR Operation</code><br />
<code>Syntax: ~ Ganzzahl → Bitweise Negierung</code><br />
<code>Syntax: Ganzzahl >> additive-expression</code><br />
<code>Syntax: Ganzzahl << additive-expression</code><br />
Mittels des Schiebeoperators können '''Ganzzahlen''' um <code>additive-expression</code> bitweise nach Links <code><<</code> oder Rechts <code>>></code> verschoben werden. Der resultierende Datentyp ergibt sich aus dem linken Operanden. Der rechte Operand muss positiv und der Wert kleiner gleich der Bitbreite des linken Operanden sein. Andernfalls ist das Ergebnis implementierungsspezifisch.
Nach [C11 6.5.7] ist das Ergebnis der Schiebeoperation implementierungsspezifisch, wenn der linke Operand eine negative vorzeichenbehaftete Zahl ist. In der Regel wendet der Compiler jedoch folgende Schiebeoperation an:
* Logisches Schieben (zu füllende Bit-Stellen werden mit 0 aufgefüllt), wenn der linke Operand einen vorzeichenlosen Datentyp hat
* Arithmetisches Schieben (zu füllende Bit-Stelle beim Rechtsschieben wird mit dem Vorzeichenbit aufgefüllt), wenn der linke Operand ein vorzeichenbehaftete Datentyp ist. Hiermit wird das Vorzeichen beibehalten, so dass eine negative Zahl nach dem Schieben weiterhin negativ ist (In Java erfolgt dies durch den >>> - Operator)
Hinweis:
* Ein Schieben um eine Stelle nach rechts entspricht einer Division durch 2
* Ein Schieben um eine Stelle nach links entspricht einer Multiplikation mit 2
=== sizeof-Operator ===
Der sizeof-Operator dient zur Ermittlung des Speicherbedarfs (in Bytes) einer Variablen/eines Datentyps.
<code>Syntax: sizeof (type-name)</code><br />
<code>Syntax: sizeof unary-expression</code><br />
Als Argument für den Sizeof-Operator kann wahlweise ein Datentyp, eine Variable oder ein Ausdruck genutzt werden. Sizeof gilt als Konstantenausdruck, d.h. seine Berechnung erfolgt durch den Compiler, sodass:
* sizeof zur Initialisierung von globalen Variablen genutzt werden
:<syntaxhighlight lang="C">
struct xyz{int x,y,z;};
size_t size=sizeof(struct xyz);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{int x,y,z;};
size_t size=sizeof(struct xyz); //3*sizeof(int)=12
int main(int argc, char *argv[]) {
printf("size=%zu\n",size);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei einem Ausdruck dieser nicht ausgeführt wird, sondern nur der resultierende Datentyp bestimmt wird und dessen Größe zurückgegeben
:<syntaxhighlight lang="C">
short var=4711;
size_t size=sizeof var++; //var=4711, size=2
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
short var=4711;
size_t size=sizeof var++; //var=4711, size=2
printf("size=%zu var=%d\n",size,var);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der resultierende Datentyp des Rückgabewertes ist <code>size_t</code>.
Es empfiehlt sich, den sizeof-Operator mit Klammern zu nutzen, andernfalls gibt sizeof bei Anwendung auf einen Ausdruck die Größe des linken Operators zurück:
<syntaxhighlight lang="C">
size_t size;
short var;
size=sizeof var+0; //size=2, da sizeof auf var angewendet wird
size=sizeof(var+0); //size=4, da sizoeof auf den resultierenden datentyp
//angewendet wird
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
size_t size;
short var=0;
size=sizeof var+0; //size=2, da sizeof auf var angewendet wird
printf("size=%zu var=%d\n",size,var);
size=sizeof(var+0); //size=4, da sizoeof auf den resultierenden datentyp
//angewendet wird
printf("size=%zu var=%d\n",size,var);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* sizeof angewendet auf char gibt immer den Wert 1 zurück.
* sizeof ist nicht auf Operanden vom Typ Funktion, void, Felder ohne Größenangabe und Bitfelder anwendbar
* wird sizeof auf ein VLA angewendet, so entspricht sizeof nicht mehr einen Konstantenausdruck, sondern einem Funktionsaufruf
:<syntaxhighlight lang="C">
void foo(int n) {
int arr[n];
size_t size=sizeof(arr); //Speicherbedarf ist kein Konstantenausdruck
//sondern wird zur Laufzeit berechnet
</syntaxhighlight>
* Sizeof entspricht nicht strlen(), da sizeof die Größe des für die Variable reservierten Speicherbereich zurückgibt und nicht wie strlen() den Inhalt des Speicher hinsichtlich des Stringendezeichens auswertet:
:<syntaxhighlight lang="C">
char string[100]="Test";
printf("%zu\n",sizeof(string)); //100
printf("%zu\n",strlen(string)); //4
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char string[100]="Test";
printf("%zu\n",sizeof(string)); //100
printf("%zu\n",strlen(string)); //4
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Anweisungen ==
=== If-Anweisung ===
<code>Syntax: if (expression) statement</code><br />
<code>Syntax: if (expression) statement else statement</code><br />
Das Ergebnis des Ausdruckes (Ganzzahl, Gleitkommazahl oder Zeiger) wird auf ungleich 0, 0.0 oder NULL getestet. Trifft dies zu, so wird <code>statement</code> ausgeführt. Andernfalls wird das <code>else statement</code> ausgeführt, sofern vorhanden. Sollen mehrere Anweisungen ausgeführt werden, so sind diese mittels Block zusammenzufassen (diesen dann bitte nicht mit ; abschließen).
Beispiel:
<syntaxhighlight lang="C">
if(a==1)
if(a=1) //Erst Zuweisung, dann prüfen der Rückgabe der Zuweisung
if(a) //entspricht a!=0
if(printf("hallo")<0) //prüfen, ob printf() fehlschlägt
if( ({int dummy=a;a=b;b=dummy;})==6)
if(a=7) //Zuweisung!
if(7=a) //KO, Eine Konstante kann kein L-Value sein
if(7==a)
{printf("a ist 7");}; //Semikolon hinter Blocksope ist eine zweite
else //Anweisung, so dass die ELSE Anweisung nicht
{printf("Compilerfehler");};//zur IF-Anwesigung zugeordnet werden kann.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int a=1,b=2;
if(a==1)
printf("a==1\n");
if(a=1) //Erst Zuweisung, dann prüfen der Rückgabe der Zuweisung
printf("a=1\n");
if(a) //entspricht a!=0
printf("a\n");
if(printf("hallo\n")<0) //prüfen, ob printf() fehlschlägt
printf("printf()\n");
if( ({int dummy=a;a=b;b=dummy;})==6)
printf("({...})\n");
if(a=7) //Zuweisung!
printf("a=7\n");
if(7=a) //KO, Eine Konstante kann kein L-Value sein
;
if(7==a)
{printf("a ist 7");}; //Semikolon hinter Blocksope ist eine zweite
else //Anweisung, so dass die ELSE Anweisung nicht
{printf("Compilerfehler");};//zur IF-Anwesigung zugeordnet werden kann.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei der Anweisung <code>if(a==7)</code> finden aus syntaktischer Sicht zwei Aktionen statt. Zunächst wird geprüft, ob a gleich 7 ist. Dieser Vergleich liefert true(=1) oder false(=0) zurück. Die If-Anweisung prüft im Anschluss, ob das Argument true oder false ist.
=== For-Anweisung ===
<code>Syntax: for(Initialisierungsteil<sub>OPT</sub> ; Test<sub>OPT</sub> ; Fortsetzung<sub>OPT</sub>) Statement</code>
Die For-Anweisung wird vom Compiler wie folgt umgesetzt:
<poem> '''Initialisierungsteil'''<sub>OPT</sub>
Goto Next
Goon:
//Continue-Anweisung entspricht goto Continue
//Break-Anweisung entspricht goto Break;
'''Statement'''
Continue:
'''Fortsetzung'''<sub>OPT</sub>
Next:
if('''Test'''<sub>OPT</sub>) goto Goon
Break:
</poem>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc, char *argv[]) {
int lauf;
int summe;
for(summe=lauf=0;lauf<20;lauf++)
summe+=lauf;
printf("summe=%d\n",summe);
//Initialisierungsteil
summe=lauf=0;
goto Next;
Goon:
//Continue-Anweisung entspricht goto Continue
//Break-Anweisung entspricht goto Break;
//Statement
summe+=lauf;
Continue: __attribute__((unused))
//Fortsetzung
lauf++;
Next:
//if(TestOPT) goto Goon
if(lauf<20) goto Goon;
Break: __attribute__((unused))
printf("summe=%d\n",summe);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die einzelne Elemente haben folgende Bedeutung/Besonderheiten:
;Initialisierungsteil: Zum Initialisieren von Schleifenvariablen, wird einmalig mit Beginn der FOR-Anweisung ausgeführt:
:* kann einen beliebigen '''Ausdruck''' oder alternativ eine '''Deklaration''' (ab C99 und in C++) enthalten. Im Falle einer Deklaration ist/sind die dort definierte Variablen nur innerhalb der for-Schleife gültig/sichtbar
:* kann Leer sein, dann erfolgt keine Initialisierung
;Testteil: Hierin wird vor jedem Schleifendurchlauf geprüft, ob die Schleifenbedingung erfüllt ist. Wenn die Bedingung nicht erfüllt ist (Ganzzahl, Gleitkommazahl oder Zeiger gleich 0,0.0 oder NULL), wird die For-Schleife beendet.
:* Kann leer sein, dann wird dieser Teil als true angesehen
;Fortsetzungsteil: Wird nach jeden Schleifendurchlauf ausgeführt. In der Regel sollte hier die Schleifenvariable aktualisiert werden
:* Kann leer sein
;Statement: In der Schleife auszuführender Ausdruck
:* Sollen mehrere Ausdrücke ausgeführt werden, so sind diese in einem Block zusammen zu fassen.
Ergänzende Anweisungen innerhalb des Statements/Block
* <code>continue</code> zum Fortsetzen des Schleifendurchlaufes, d.h. Sprung zum Fortsetzungs-Teil
* <code>break</code> zum Beenden des Schleifendurchlaufes
Beispiele:
* For-Schleife mit Ausdruck im Initialisierungsteil
:<syntaxhighlight lang="C">
unsigned int zahl=0b100010;
unsigned int mask,bits;
for(mask=0b10000000,bits=mask&0; mask!=0; mask>>=1 )
bits+= zahl & mask ? 1 : 0;
//Schleifenvariable mus keine Zählvariable sein!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
unsigned int zahl=0b100010;
unsigned int mask,bits;
for(mask=0b10000000,bits=mask&0; mask!=0; mask>>=1 )
bits+= zahl & mask ? 1 : 0;
//Schleifenvariable mus keine Zählvariable sein!
printf("Anzahl Einsen in %b = %d\n",zahl,bits);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* For-Schleife mit Deklaration im Initialisierungsteil und break-Anweisung
:<syntaxhighlight lang="C">
char string[]="hallo";
size_t size=0;
for(size_t lauf=0; lauf < strlen(string); lauf++) {
if(string[lauf]=='A') break;
size++;
}
//Variable lauf ist außerhalb der Schleife nicht mehr gültig!
// Dadurch ist im Nachgang nicht direkt feststellbar, ob die Schleife
// bis zum Ende gelaufen ist oder durch break beendet wurde
//Schleife ist Suboptimal, da in jedem Durchlauf die Funktion
// strlen() aufgerufen wird!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
#include <time.h>
struct timespec diff_timespec(const struct timespec *minuend,
const struct timespec *subtrahend ) {
struct timespec diff = {
.tv_sec = minuend->tv_sec - subtrahend->tv_sec,
.tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec};
//Sekundenüberlauf?
if (diff.tv_nsec < 0) {
diff.tv_nsec += 1000000000;
diff.tv_sec--;
}
return diff;
}
int main(int argc, char *argv[]) {
char string1[10000];
char string2[10000];
memset(string1,'a',sizeof(string1));
memset(string2,'a',sizeof(string2));
string1[sizeof(string1)-1]=0;
string2[sizeof(string2)-1]=0;
struct timespec start1,stop1;
struct timespec start2,stop2;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&start1);
size_t size1=0;
for(size_t lauf=0; lauf < strlen(string1); lauf++) {
if(string1[lauf]=='A') break;
size1++;
}
//Variable lauf ist außerhalb der Schleife nicht mehr gültig!
// Dadurch ist im Nachgang nicht direkt feststellbar, ob die Schleife
// bis zum Ende gelaufen ist oder durch break beendet wurde
//Schleife ist Suboptimal, da in jedem Durchlauf die Funktion
// strlen() aufgerufen wird!
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&stop1);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&start2);
size_t size2=0;
//Funktionsaufrufe mit konstanten Ergebnis vor die Schleife verlegen
size_t lauf_max=strlen(string2);
for(size_t lauf=0; lauf < lauf_max; lauf++) {
if(string2[lauf]=='A') break;
size2++;
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&stop2);
stop1=diff_timespec(&stop1,&start1);
stop2=diff_timespec(&stop2,&start2);
printf("Slow: Sum1=%zu Time=%lds %ldns\n",size1,stop1.tv_sec,stop1.tv_nsec);
printf("Fast: Sum2=%zu Time=%lds %ldns\n",size2,stop2.tv_sec,stop2.tv_nsec);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Schleife, bei welcher die gesamte Aktion innerhalb der For-Anweisung ausgeführt wird
:<syntaxhighlight lang="C">
char dest[5];
char src[10]="HalloWelt";
for(size_t l=0;
src[l]!=0 && l <sizeof(dest);
printf("l=%zu\n",l),dest[l]=src[l],l++);
//Beliebige Ausdrücke im Test- und Fortsetzungsteil möglich!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char dest[5];
char src[10]="HalloWelt";
for(size_t l=0;src[l]!=0 && l <sizeof(dest); printf("l=%zu\n",l),dest[l]=src[l],l++);
//Beliebige Ausdrücke im Test- und Fortsetzungsteil möglich!
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Zeiger als Schleifenvariable
:<syntaxhighlight lang="C">
char src[]="hallo";
char dst[strlen(src)+1];
char *s,*d;
for(s=src,d=dst; *s; )
*d++=*s++;
*d=0;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char src[]="hallo";
char dst[strlen(src)+1];
char *s,*d;
for(s=src,d=dst; *s; )
*d++=*s++;
*d=0;
printf("src='%s' dst='%s'\n",src,dst);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Auch wenn einige Compiler bei eingeschalteter Optimierung die Fähigkeit besitzen, Funktionsaufrufe innerhalb des Test- und Fortsetzungsteil vor die Schleife zu verschieben (siehe: [https://xania.org/202512/13-licking-licm Loop-Invariant Code Motion]), so sollten Funktionsaufrufe an diesen Stellen vermieden werden. Einerseits zeugt dies von schlechten Programmierstiel und andererseits führt dies bei ausgeschalteter Optimierung zu Performanceeinbußen:
:<syntaxhighlight lang="C">
for(size_t lauf=0;lauf<strlen("hallo");lauf++)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
#include <time.h>
struct timespec diff_timespec(const struct timespec *minuend,
const struct timespec *subtrahend ) {
struct timespec diff = {
.tv_sec = minuend->tv_sec - subtrahend->tv_sec,
.tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec};
//Sekundenüberlauf?
if (diff.tv_nsec < 0) {
diff.tv_nsec += 1000000000;
diff.tv_sec--;
}
return diff;
}
int main(int argc, char *argv[]) {
char string1[10000];
char string2[10000];
memset(string1,'a',sizeof(string1));
memset(string2,'a',sizeof(string2));
string1[sizeof(string1)-1]=0;
string2[sizeof(string2)-1]=0;
struct timespec start1,stop1;
struct timespec start2,stop2;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&start1);
size_t sum1=0;
for(size_t lauf=0; lauf < strlen(string1); lauf++)
sum1++;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&stop1);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&start2);
size_t sum2=0;
size_t count2=strlen(string2);
for(size_t lauf=0; lauf < count2; lauf++)
sum2++;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&stop2);
stop1=diff_timespec(&stop1,&start1);
stop2=diff_timespec(&stop2,&start2);
printf("Slow: Sum1=%zu Time=%lds %ldns\n",sum1,stop1.tv_sec,stop1.tv_nsec);
printf("Fast: Sum2=%zu Time=%lds %ldns\n",sum2,stop2.tv_sec,stop2.tv_nsec);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Zur Geschwindigkeitssteigerung sollte im Testteil auf 0 abgefragt werden, d.h. die Schleifenvariable dekrementiert werden:
:<syntaxhighlight lang="C">
for(int lauf=700000;lauf;lauf--)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
#include <time.h>
struct timespec diff_timespec(const struct timespec *minuend,
const struct timespec *subtrahend ) {
struct timespec diff = {
.tv_sec = minuend->tv_sec - subtrahend->tv_sec,
.tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec};
//Sekundenüberlauf?
if (diff.tv_nsec < 0) {
diff.tv_nsec += 1000000000;
diff.tv_sec--;
}
return diff;
}
int main(int argc, char *argv[]) {
char string1[10000];
char string2[10000];
memset(string1,'a',sizeof(string1));
memset(string2,'a',sizeof(string2));
string1[sizeof(string1)-1]=0;
string2[sizeof(string2)-1]=0;
struct timespec start1,stop1;
struct timespec start2,stop2;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&start1);
size_t sum1=0;
for(ssize_t lauf=700000000;lauf;lauf--)
sum1++;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&stop1);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&start2);
size_t sum2=0;
for(ssize_t lauf=0;lauf<700000000;lauf++)
sum2++;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&stop2);
stop1=diff_timespec(&stop1,&start1);
stop2=diff_timespec(&stop2,&start2);
printf("Slow: Sum1=%zu Time=%lds %ldns\n",sum1,stop1.tv_sec,stop1.tv_nsec);
printf("Fast: Sum2=%zu Time=%lds %ldns\n",sum2,stop2.tv_sec,stop2.tv_nsec);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Alternativ zu einer Laufvariablen empfiehlt sich die Nutzung von Pointer als Schleifenvariable:
:<syntaxhighlight lang="C">
for(char *ptr=str; *ptr; ptr++);
</syntaxhighlight>
* Verzweigungsbefehle sind einige der langsamsten Maschinenbefehl. Zur Vermeidung von diesen Maschinenbefehle 'entrollen' die Compiler bei eingeschalter Optimierungen und bekannter kleiner Anzahl von Schleifendurchläufe die For-Schleife (siehe: [https://xania.org/202512/10-loop-unrolling Unrolling Loops])
:<syntaxhighlight lang="C">
for(int lauf=4;lauf;lauf--)
sum+=arr[lauf];
//wird aufgrund bekannter Anzahl der Schleifendurchläufe wie folgt entrollt
sum+=arr[4];
sum+=arr[3];
sum+=arr[2];
sum+=arr[1];
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <string.h>
int arr[5];
void arr_init(void) {
memcpy(arr,(int []){1,2,3,4,6},sizeof(arr));
}
int main(int argc, char *argv[]) {
arr_init();
int sum;
sum=0;
for(int lauf=4;lauf;lauf--)
sum+=arr[lauf];
printf("sum=%d\n",sum);
//wird aufgrund bekannter Anzahl der Schleifendurchläufe wie folgt entrollt
sum=0;
sum+=arr[4];
sum+=arr[3];
sum+=arr[2];
sum+=arr[1];
printf("sum=%d\n",sum);
//Zur Darstellung von Loop-Runling Compiler-Option -O0 auf -O1 ändern
return 0;
} | execCompilerOptions=-Wall -O0|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== While-Anweisung ===
<code>Syntax: while(expression) Statement </code><br />
<code>Syntax: do Statement while(expression);</code><br />
Die While-Anweisungen werden vom Compiler wie folgt umgesetzt:
{| class="wikitable"
! while()-Anweisung !! do while()-Anweisung
|-
| <poem>
Continue:
if(!'''expression''')
goto Break;
//Break-Anweisung entspricht
// goto Break;
//Continue-Anweisung entspr.
// goto Continue;
'''Statement'''
goto Continue;
Break:
</poem> ||
<poem>
GoOn:
//Break-Anweisung entspr.
// goto Break;
//Continue-Anweisung ent.
// goto Continue;
'''Statement'''
Continue:
if('''expression''')
goto GoOn;
Break:
</poem>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
int main(int argc, char *argv[]) {
int lauf;
int summe;
lauf=summe=0;
while(lauf<10) {
if(lauf>=5)
break;
lauf++;
if(lauf<3)
continue;
summe+=lauf;
}
printf("summe=%d\n",summe);
lauf=summe=0;
Continue1:
if(!(lauf<10))
goto Break1;
//Break-Anweisung entspricht
// goto Break;
//Continue-Anweisung entspr.
// goto Continue;
//Statement
if(lauf>=5) {
goto Break1;
}
lauf++;
if(lauf<3)
goto Continue1;
summe+=lauf;
goto Continue1;
Break1:
printf("summe=%d\n",summe);
lauf=summe=0;
do {
lauf++;
if(lauf>5)
break;
if(lauf<3)
continue;
summe+=lauf;
} while(lauf<10);
printf("summe=%d\n",summe);
lauf=summe=0;
GoOn2:
//Break-Anweisung entspr.
// goto Break
//Continue-Anweisung ent.
// goto Continue
//Statement
lauf++;
if(lauf>5)
goto Break2;
if(lauf<3)
goto Continue2;
summe+=lauf;
Continue2:
if(lauf<10)
goto GoOn2;
Break2: __attribute__((unused));
printf("summe=%d\n",summe);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Folgendes gilt es bei der Nutzung der While-Anweisung zu beachten:
* Soll mehr als ein Statement innerhalb der while-Schleife ausgeführt werden, so sind diese in einem Block zu schreiben
* Statement kann eine Leeranweisung (gekennzeichnet durch ein Semikolon) sein
:<syntaxhighlight lang="C">
while(1);
do ; while(1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int lauf1=1000;
while(lauf1--);
int lauf2=1000;
do ; while(lauf2--);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Bei der do-while-Schleife ist das abschließende Semikolon Bestandteil des Befehls
* expression muss eine Ganzzahl, Gleitkommazahl oder Zeiger zurückgeben, der bei False (0, 0.0 oder NULL) die Schleife beendet.
Beispiele:
* Endlosschleife
:<syntaxhighlight lang="C">
while(1) {}
</syntaxhighlight>
* Schleife zum Durchlaufen eines String
:<syntaxhighlight lang="C">
char str[]="string";
char *ptr=str;
while(*ptr++);
size_t len=ptr-str-1;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char str[]="string";
char *ptr=str;
while(*ptr++);
size_t len=ptr-str-1;
printf("Stringlänge=%zu\n",len);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Switch-Anweisung ===
<code>Syntax: switch(expression) statement</code><br />
<code>Syntax: statement:= case constant-expression: statement<br /> default: statement</code><br />
Die Switch-Anweisung entspricht einer verschachtelten If-Anweisung mit der Besonderheit, dass der auszuführende Code nicht im If-Zweig enthalten ist, sondern im Nachgang zu der verschachtelten If-Anweisung steht (angeführt von einer Sprungmarke für jeden CASE-Fall) und in der If-Anweisung nur ein Sprung/Goto zu der Stelle im Nachgang enthalten ist:
{| class="wikitable"
! Switch-Anweisung !! Compilerumsetzung
|-
|<syntaxhighlight lang="C">
switch(a) {
case 1:
int a=7;
//Code
break;
case 2:
printf("%d",a);
case 3: {
int a;
//Code
}
case 4 ... 8:
default:
//Code
}
</syntaxhighlight>
||<poem>
if(a==1)
goto label1;
else if(a==2)
goto label2;
else
goto label_default;
//-------------------
label1:
//Code
goto label_break;
label2:
//Code
label_default:
goto label_break;
label_break:
</poem>
|}
Folgendes gilt es bei der Nutzung der Switch-Anweisung zu beachten:
* <code>Expression</code> muss zu einer Ganzzahl (int, short, char, long, long long) oder enum (entspricht einer Ganzzahl) ausgewertet werden
* <code>constant-expression</code> muss eine Ganzzahl-Konstante oder ein Enum-Element sein. Sie darf nicht doppelt im Block vorkommen. Der genaue Datentyp ergibt sich aus dem Datentyp der <code>expression</code>
* Lt. Spezifikation ist nur ein <code>statement</code> hinter der switch-Anweisung erlaubt, so dass nur ein <code>case</code> Fall oder der <code>default</code> Fall bedient werden kann::<syntaxhighlight lang="C">
int var=1;
switch(var) case 1: printf("hallo");
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int var=1;
switch(var) case 1: printf("hallo");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Die geschweifte Klammer der <code>switch</code>-Anweisung erzeugt einen Block, so dass a) hier mehrere <code>case</code>-Fälle und b) hierin definierte Variablen innerhalb des gesamten Blocks zur Verfügung stehen (sind somit nicht <code>case</code> abhängig):
:<syntaxhighlight lang="C">
switch(a) {
case 1:
int b=3; //Variable im gesamten Block gültig
break;
case 2:
int b=2; //Fehler, Variable im Block bereits enthalten
break;
case 3: { //Block, so dass Variable
int b=4711; //nur in diesem CASE gültig ist
break;
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int a=1;
switch(a) {
case 1:
int b=3; //Variable im gesamten Block gültig
break;
case 2:
int b=2; //Fehler, Variable im Block bereits enthalten
printf("b=%d\n",b);
break;
case 3: { //Block, so dass Variable
int b=4711; //nur in diesem CASE gültig ist
printf("b=%d\n",b);
break;
}
}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Die CASE Anweisung ist nichts anderes als eine Sprungmarke (welche durch die Switch-Anweisung angesprungen wird), so dass der Initialisierungsteil der lokalen Variablen übersprungen / nicht ausgeführt werden kann:
:<syntaxhighlight lang="C">
switch(a) {
int a=3; //Variable in gesamten Block gültig
case 1:
int b=3;
printf("%d %d",a,b); //a undefiniert, b=3
break;
case 2:
printf("%d %d",a,b); //a und b undefiniert
break;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int a=1;
switch(a) {
int a=3; //Variable in gesamten Block gültig
case 1:
int b=3;
printf("%d %d",a,b); //a undefiniert, b=3
break;
case 2:
printf("%d %d",a,b); //a und b undefiniert
break;
}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* GNU-C (siehe [https://www.gnu.org/software/c-intro-and-ref/manual/html_node/switch-Statement.html Switch-Statement]) erlaubt ergänzend zur Angabe einer Konstante die Angabe eines Wertebereiches:
:<syntaxhighlight lang="C">
switch(a) {
case 1 ... 8: //Leerzeichen zwischen den Konstanten zwingend notwendig
//andernfalls wird der Punkt zur Konstante zugehörig
//interpretiert (erzeugt dann eine Gleitpunktkonstante)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int a=2;
switch(a) {
case 1 ... 8: //Leerzeichen zwischen den Konstanten zwingend notwendig
//andernfalls wird der Punkt zur Konstante zugehörig
//interpretiert (erzeugt dann eine Gleitpunktkonstante)
printf("a im Bereich von 1 bis 8\n");
break;
}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* <code>break</code> ist optional. Mittels <code>break</code> wird an das Ende der Switch-Anweisung gesprungen. Wenn <code>break</code> weggelassen wird, wird die nachfolgende Anweisungen ausgeführt. Ggf. gibt der Compiler eine Warning aus. Mittels der GCC-Compiler-Anweisung __attribute__((fallthrough)); kann diese Warning unterdrückt werden:
:<syntaxhighlight lang="C">
switch(a) {
case 0: //ggf. Compiler-Warning
__attribute__((fallthrough)); case 1:
case 2:
break;
}
</syntaxhighlight>
* Ein Variable Length Array ist als Variable im Switch-Block direkt nicht erlaubt. Ist dies notwendig, so ist das VLA in einem inneren Block zu kapseln:
:<syntaxhighlight lang="C">
switch(var) {
case 1:
int arr[var]; //KO
break;
case 2: {
int arr[var]; //OK
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int var=1;
switch(var) {
case 1:
int arr[var]; //KO
break;
case 2: {
int arr[var]; //OK
}
}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Case - Anweisungen sind nichts anderes als Sprungmarken (Labels), so dass CASE-Anweisungen überall innerhalb des Switch-Blockes stehen können:
:<syntaxhighlight lang="C">
int prime(int value) {return value+1;}
void hallo(int var) {
switch(var) {
default:
if(prime(var))
case 2: case 4:
printf("%d",var);
else {
case 3: case 6:
printf("%x",var);
}
case 7:
printf("xyz");
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int prime(int value) {
return value+1;
}
int main(int argc, char *argv[]) {
int var=1;
switch(var) {
default:
if(prime(var))
case 2: case 4:
printf("%d",var);
else {
case 3: case 6:
printf("%x",var);
}
case 7:
printf("xyz");
}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:oder anderen Anweisungen innerhalb des Switch-Blockes enthalten sein können:
:<syntaxhighlight lang="C">
void send(register char *dst,
register char *src,
register size_t count)
{
register char unsigned n=(count+7)/8;
switch(count%8) {
case 0: do{ *dst = *src++;
case 7: *dst = *src++;
case 6: *dst = *src++;
case 5: *dst = *src++;
case 4: *dst = *src++;
case 3: *dst = *src++;
case 2: *dst = *src++;
case 1: *dst = *src++;
}while(--n>0);
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
#include <stdint.h> //fuer uintptr_t
void send(register char *dst,
register char *src,
register size_t count)
{
register char unsigned n=(count+7)/8;
switch(count%8) {
case 0: do{ *dst = *src++; printf("%02hhx ",*dst);
case 7: *dst = *src++; printf("%02hhx ",*dst);
case 6: *dst = *src++; printf("%02hhx ",*dst);
case 5: *dst = *src++; printf("%02hhx ",*dst);
case 4: *dst = *src++; printf("%02hhx ",*dst);
case 3: *dst = *src++; printf("%02hhx ",*dst);
case 2: *dst = *src++; printf("%02hhx ",*dst);
case 1: *dst = *src++; printf("%02hhx ",*dst);
}while(--n>0);
}
}
int main(int argc, char *argv[])
{
char src[20]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
char dst;
send(&dst,src,20);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Eine Switch-Case Anweisung über Strings sind in C/C++ nicht möglich:
:<syntaxhighlight lang="C">
switch(str) {
case "hallo":
return 1;
case "du da":
return 2;
case "xyz":
return 3;
default:
rReturn -1;
}
</syntaxhighlight>
:Ein direkte Lösungsansatz ist die Nutzung von strcmp() zum Vergleichen von String. Da strcmp zeichenweise den String vergleicht, ist dieser Ansatz langsam. Alternativ bietet sich an, von allen String einen Hash-Wert zu berechnen und zunächst diesen Hash-Wert zu kontrollieren. Da der Hash-Wert nicht eindeutig ist, muss ergänzend ein strcmp() erfolgen:
:<syntaxhighlight lang="C">
char *str="hallo";
switch(HASH_LAUFZEIT(str)) {
case HASH_COMPILEZEIT('d','u'):
if(!strcmp(str,"du"))
printf("Case \"du\":\n");
break;
case HASH_COMPILEZEIT('h','a','l','l','o'):
if(!strcmp(str,"hallo"))
printf("Case \"hallo\"\n");
else if(!strcmp(str,"xyz"))
printf("String='xyz'\n");
break;
default:
return -1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
#include <stdint.h>
//Lösungsansatz von: https://stackoverflow.com/questions/2826559/compile-time-preprocessor-hashing-of-string
#define H1(s,i,x) (x*65599u+(uint8_t)s[(i)<strlen(s)?strlen(s)-1-(i):strlen(s)])
#define H4(s,i,x) H1(s,i,H1(s,i+1,H1(s,i+2,H1(s,i+3,x))))
#define H16(s,i,x) H4(s,i,H4(s,i+4,H4(s,i+8,H4(s,i+12,x))))
#define H64(s,i,x) H16(s,i,H16(s,i+16,H16(s,i+32,H16(s,i+48,x))))
#define H256(s,i,x) H64(s,i,H64(s,i+64,H64(s,i+128,H64(s,i+192,x))))
#define HASH(s) ((uint32_t)(H256(s,0,0)^(H256(s,0,0)>>16)))
#define HASH_LAUFZEIT(s) (H256(s,0,0))
//Eigener Lösungsatz zur Umsetzung des vorherigen HASH-Algorithmus
//so dass dieser zur Compilezeit berechnet werden kann
//Was fehlt ist die abschließende EXOR berechnung!
//Problem war, dass die Array-Dereferenzierung nicht zur Compilezeit
//aufelöst werden kann
#define HH0(a,x) (x*65599u+a)
#define HH1(a) HH0(a,HH0(0,HH0(0,HH0(0,0))))
#define HH2(a,b) HH0(b,HH0(a,HH0(0,HH0(0,0))))
#define HH3(a,b,c) HH0(c,HH0(b,HH0(a,HH0(0,0))))
#define HH4(a,b,c,d) HH0(d,HH0(c,HH0(b,HH0(a,0))))
#define HH4x(a,b,c,d,x) HH0(d,HH0(c,HH0(b,HH0(a,x))))
#define HH5(a,b,c,d,e) HH4x(b,c,d,e,HH4x(0,0,0,a,0))
#define HH6(a,b,c,d,e,f) HH4x(c,d,e,f,HH4x(0,0,a,b,0))
#define HH7(a,b,c,d,e,f,g) HH4x(d,e,f,g,HH4x(0,a,b,c,0))
#define HH8(a,b,c,d,e,f,g,h) HH4x(e,f,g,h,HH4x(a,b,c,d,0))
#define HH9(a,b,c,d,e,f,g,h,i) HH4x(f,g,h,i,HH4x(b,c,d,e,HH4x(0,0,0,a,0)))
#define HH10(a,b,c,d,e,f,g,h,i,j) HH4x(g,h,i,j,HH4x(c,d,e,f,HH4x(0,0,a,b,0)))
#define HH11(a,b,c,d,e,f,g,h,i,j,k) HH4x(h,i,j,k,HH4x(d,e,f,g,HH4x(0,a,b,c,0)))
#define HH12(a,b,c,d,e,f,g,h,i,j,k,l) HH4x(i,j,k,l,HH4x(e,f,g,h,HH4x(a,b,c,d,0)))
#define HH13(a,b,c,d,e,f,g,h,i,j,k,l,m) HH4x(j,k,l,m,HH4x(f,g,h,i,HH4x(b,c,d,e,HH4x(0,0,0,a,0))))
#define HH14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) HH4x(k,l,m,n,HH4x(g,h,i,j,HH4x(c,d,e,f,HH4x(0,0,a,b,0))))
#define HH15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) HH4x(l,m,n,o,HH4x(h,i,j,k,HH4x(d,e,f,g,HH4x(0,a,b,c,0))))
#define HH16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) HH4x(m,n,o,p,HH4x(i,j,k,l,HH4x(e,f,g,h,HH4x(a,b,c,d,0))))
#define EIGHTEENTH_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11,a12,a13,a14,a15,a16,a17,a18, ...) a18
#define CONCAT(c,d) c ## d
#define CONCATI(a,b) CONCAT(a,b)
#define HASH_COMPILEZEIT(...) CONCATI(HH , EIGHTEENTH_ARGUMENT(dummy, ## __VA_ARGS__, \
16,15,14,13,12,11,10,9, 8, 7, 6, 5, 4, 3, 2, 1, 0))(__VA_ARGS__)
//Lösungsansatz basierend auf: https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/__VA_ARGS__/count-arguments
#define COUNT_ARGUMENTS(...) EIGHTEENTH_ARGUMENT(dummy, ## __VA_ARGS__, \
16,15,14,13,12,11,10,9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
int main(int argc, char *argv[]) {
char *str="hallo";
switch(HASH_LAUFZEIT(str)) {
case HASH_COMPILEZEIT('d','u'):
if(!strcmp(str,"du"))
printf("Case \"du\":\n");
break;
case HASH_COMPILEZEIT('h','a','l','l','o'):
if(!strcmp(str,"hallo"))
printf("Case \"hallo\"\n");
else if(!strcmp(str,"xyz"))
printf("String='xyz'\n");
break;
default:
return -1;
}
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Siehe:[https://benhoyt.com/writings/hash-table-in-c/ Hash Table in C]
=== C++ ===
==== Ranged-based-for-Anweisung ====
In C++ steht ergänzend zur For-Anweisung die Ranged-based-for-Anweisung zur Verfügung. Die Anzahl der Iterationen ergibt sich hier aus einem <code>Range-Initializer</code>.
<code>Syntax: for( declaration : range-initializer ) statement</code>
Mit der <code>declaration</code> wird eine Laufzeitvariable definiert, welcher nacheinander die einzelnen Elemente des <code>range-initializier</code> zugewiesen bekommt. Der Datentyp der Deklaration sollte somit identisch zum Datentyp der Elemente sein (alternativ Datentyp auto).</br>
Die Anzahl der Schleifendurchläufe ergibt sich in Abhängigkeit des Datentyps des range-initializers wie folgt:
* Array: Größe des Arrays
* Class: Aus den zugehörigen Klassenmethoden begin() und end()
* Datentyp: Aus den (überladenen) datentypespezifischen Funktionen von begin() und end()
Wie in der For-Schleife auch kann diese Schleife mit <code>break</code> vorzeitig abgebrochen und mit <code>continue</code> der aktuelle Durchlauf beendet werden.
Beispiele:
* Range-Initializer aus Array
<syntaxhighlight lang="c++">
//Quelle: CPPreference: https://en.cppreference.com/cpp/language/range-for
int a[] = {0, 1, 2, 3, 4, 5};
for (int n : a) // the initializer may be an array
std::cout << n << ' ';
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <iostream>
int main(int argc,char *argv[]) {
int a[] = {0, 1, 2, 3, 4, 5};
for (int n : a) // the initializer may be an array
std::cout << n << ' ';
return 0;
} | execCompilerOptions=|
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Range-Initializer aus Klasse (hier vector)
<syntaxhighlight lang="c++">
//Quelle: CPPreference: https://en.cppreference.com/cpp/language/range-for
std::vector<int> v = {0, 1, 2, 3, 4, 5};
for (const int& i : v) // access by const Preference
std::cout << i << ' ';
for (auto i : v) // access by value, the type of i is int
std::cout << i << ' ';
for (auto&& i : v) // access by forwarding reference, the type of i is int&
std::cout << i << ' ';
for (int n : {0, 1, 2, 3, 4, 5}) // the initializer may be a
// braced-enclosed initializer list
std::cout << n << ' ';
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <iostream>
#include <vector>
int main(int argc,char *argv[]) {
//Quelle: CPPreference: https://en.cppreference.com/cpp/language/range-for
std::vector<int> v = {0, 1, 2, 3, 4, 5};
for (const int& i : v) // access by const Preference
std::cout << i << ' ';
std::cout << std::endl;
for (auto i : v) // access by value, the type of i is int
std::cout << i << ' ';
std::cout << std::endl;
for (auto&& i : v) // access by forwarding reference, the type of i is int&
std::cout << i << ' ';
std::cout << std::endl;
for (int n : {0, 1, 2, 3, 4, 5}) // the initializer may be a
// braced-enclosed initializer list
std::cout << n << ' ';
std::cout << std::endl;
return 0;
} | execCompilerOptions=|
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
==== Initializer-List ====
Identisch zur For-Anweisung, bei welcher der Initialisierungsteil sowohl aus einer <code>expression</code> oder eine <code>declaration</code> bestehen kann, kann auch die <code>expression</code> bei der <code>if</code>-, <code>switch</code>- und <code>while</code>-Anweisung durch eine <code>declaration</code> ersetzt werden (nicht do while()).
<code>Syntax: if(declaration) statement</code></br>
<code>Syntax: if(declaration) statement else statement</code></br>
<code>Syntax: switch(declaration) statement</code></br>
<code>Syntax: while(declaration) statement</code>
Wie bei der <code>for</code>-Anweisung ist die deklarierte Variable nur innerhalb des nachfolgenden Blockes gültig. Die eigentliche 'Bedingung' ergibt sich aus dem Rückgabewert der Deklaration.
Beispiel:
* Begrenzung der Laufzeit von Variablen und damit Vermeidung von doppelten Variablen
<syntaxhighlight lang="c++">
//Quelle: CPPreference: https://en.cppreference.com/cpp/language/range-for
//Anstatt der Deklaration einer Variable kurz vor der if-Anweisung
const char *ptr1=strstr("hallo","welt");
if(ptr1)
std::cout<<"Found at" << ptr1;
//Deklaration der Variable in der IF-Anweisung
if(const char *ptr2=strstr("hallo","Welt"))
std::cout<<"Found at" << ptr2;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <iostream>
#include <string.h>
int main(int argc,char *argv[]) {
//Quelle: CPPreference: https://en.cppreference.com/cpp/language/range-for
//Anstatt der Deklaration einer Variable kurz vor der if-Anweisung
const char *ptr1=strstr("hallo","welt");
if(ptr1)
std::cout<<"Found at" << ptr1 << std::endl;
//Deklaration der Variable in der IF-Anweisung
if(const char *ptr2=strstr("hallo","Welt"))
std::cout<<"Found at" << ptr2 << std::endl;
return 0;
} | execCompilerOptions=|
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit C++17 wurde ergänzend für die <code>switch</code>- und die <code>if</code>-Anweisung das <code>init-statement</code> eingeführt. Vorab zur eigentlichen <code>expression</code> kann mit einem Semikolon abgetrennt (Bestandteil des <code>init-statements</code>) ergänzend eine weitere <code>expression</code> oder <code>declaration</code> erfolgen.
<code>Syntax: if(init-statement expression)</code></br>
<code>Syntax: switch(init-statement expression)</code>
so dass nun folgende Variante (am Beispiel der switch-Anweisung) existieren:
<code>Syntax: switch(expression; expression) statement</code></br>
<code>Syntax: switch(expression; declaration) statement</code></br>
<code>Syntax: switch(declaration; expression) statement</code></br>
<code>Syntax: switch(declaration; declaration) statement</code>
Der für die Verzweigung auszuwertende Wert ergibt sich aus der zweiten <code>expression/Declaration</code>.
Beispiel:
* Absicherung eines kritischen Bereiches durch automatischen Dekonstruktoraufruf
<syntaxhighlight lang="c++">
if (auto p = ptr.lock(); p && p->foo())
bar(*p);
</syntaxhighlight>
== Label + Goto ==
=== Label ===
<code>Syntax: name:</code><br />
Labels dienen zur Kennzeichnung einer Anweisung, so dass die Programmausführung an dieser Stelle fortgesetzt, resp. mit einer GOTO-Anweisung angesprungen werden kann. Ein Label ist durch den folgenden Doppelpunkt gekennzeichnet. Dem Label muss eine Anweisung folgen, welches auch eine Leeranweisung (Semikolon) sein kann.
Folgendes gilt es bei der Nutzung von Labels zu beachten:
* Ein Label entspricht der Speicheradresse des der Label-Anweisung folgenden Anweisung
* Bei nicht genutzten Labels (mit goto nicht angesprungene Labels) gibt der Compiler eine Warning aus. Diese kann beim GCC-Compiler mit __attribute__((unused)) unterdrückt werden
* die Case- und die Default-Anweisung aus der Switch-Anweisung entspricht einem Label
<br />
Labels hat eine funktionsweite Sichtbarkeit (siehe Kap [[#Gültigkeit/Sichtbarkeit von Variablen| Gültigkeit/Sichtbarkeit von Variablen]]). Dies bedeutet, dass das:
* Labels nur innerhalb einer Funktion gültig ist
* Labels einen von Variablen/Funktionen/Datentypen unabhängigen Namensraum haben
* Kein Prototyp für ein Label notwendig ist, wenn es bei Nutzung über goto noch nicht gesetzt worden ist, also nach vorne gesprungen wird
=== goto ===
<code>Syntax: goto label;</code><br />
Mit der Goto-Anweisung wird die Programmausführung an der mit <code>label</code> gekennzeichneten Stelle fortgesetzt.
Folgendes gilt es bei der Nutzung von goto zu beachten:
* Mit einer <code>goto</code> Anweisung kann an eine beliebige Steller innerhalb der '''identischen''' Funktion gesprungen werden. Es kann nicht zu einem Label in einer anderen Funktion gesprungen werden (hierzu ist <code>setjmp()</code> und <code>longjmp()</code> zu nutzen)
* Mit der Goto Anweisung kann gleichermaßen in einen Block hinein, als auch herausgesprungen werden:
:<syntaxhighlight lang="C">
goto first_time;
for(;;) {
if(a>10)
goto last_time:
first_time:
a++;
}
last_time: ;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int a=0;
goto first_time;
for(;;) {
printf("a=%d\n",a);
if(a>10)
goto last_time;
first_time:
a++;
}
last_time: ; //Leeranweisung wäre hier nicht nötig
return 0; //da dem Label ein return folgt!
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Wird mit der <code>goto</code> Anweisung der Initialisierungsteil einer Variablen übersprungen, so ist zwar die Variable existent, beinhaltet aber nicht ihren Initialisierungswert
Beispiel:
<syntaxhighlight lang="C">
goto label1;
if(a==3) {
label2:
printf("True\n");
}
else
label1:
{
printf("False\n");
}
if(a==3) goto label2;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int a=3;
goto label1;
if(a==3) {
label2:
printf("True\n");
a++;
}
else
label1:
{
printf("False\n");
}
if(a==3) goto label2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* In Java gibt es das Schlüsselwort goto, welches aber ohne Funktion ist. Es gibt jedoch Labels, die mit "break label" angesprungen werden können
=== Anwendungsbeispiele ===
Prinzipiell sind Goto-Anweisungen zu vermeiden. In einigen Anwendungsfällen erweist sich goto als nützlich:
* Nutzung nur einer <code>return</code> Anweisung in einer Funktionen
:<syntaxhighlight lang="C">
#include <unistd.h>
int input(int hdl,size_t buflen) {
int rc=-1;
unsigned char packettype;
if(read(hdl,&packettype,1) != 1)
goto exit;
unsigned short packetlen;
if(read(hdl,&packetlen,2) != 2)
goto exit;
if((1+packetlen) > buflen) {
rc=-2;
goto exit;
}
rc=packetlen;
exit:
return rc;
}
</syntaxhighlight>
* Konstruktor mit mehreren Initialisierungsteilen
:<syntaxhighlight lang="C">
int main(int argc,char *argv[]) {
enum {INIT_2,INIT_1,INIT_START} fortschritt=INIT_START;
int *ptr1;
int *ptr2;
if(!(ptr1=malloc(10)))
goto end;
fortschritt=INIT_1;
if(!(ptr2=malloc(20)))
goto end;
fortschritt=INIT_2;
// ...
end:
switch(fortschritt) {
case INIT_2: free(ptr2); __attribute__((fallthrough));
case INIT_1: free(ptr1); __attribute__((fallthrough));
case INIT_START:
}
return (int)fortschritt;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
enum {INIT_2,INIT_1,INIT_START} fortschritt=INIT_START;
int *ptr1;
int *ptr2;
if(!(ptr1=malloc(10)))
goto end;
fortschritt=INIT_1;
if(!(ptr2=malloc(20)))
goto end;
fortschritt=INIT_2;
// ...
end:
switch(fortschritt) {
case INIT_2: free(ptr2); __attribute__((fallthrough));
case INIT_1: free(ptr1); __attribute__((fallthrough));
case INIT_START:
}
return (int)fortschritt;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Abbruch einer verschachtelten Schleife
:<syntaxhighlight lang="C">
int arr[10][10];
size_t zeile;
size_t spalte;
for(zeile=0;zeile<10;zeile++)
for(spalte=0;spalte<0;spalte++)
if(arr[zeile][spalte]==0)
goto label_end;
label_end:
if((zeile==0) && (spalte==0))
printf("Nichts gefunden");
else
printf("Gefunden an %zu %zu",zeile,spalte);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc, char *argv[]) {
int arr[10][10];
size_t zeile;
size_t spalte;
for(zeile=0;zeile<10;zeile++)
for(spalte=0;spalte<0;spalte++)
if(arr[zeile][spalte]==0)
goto label_end;
label_end:
if((zeile==0) && (spalte==0))
printf("Nichts gefunden");
else
printf("Gefunden an %zu %zu",zeile,spalte);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Toolchain/Entwicklungsumgebung
|zurücktext=Toolchain/Entwicklungsumgebung
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: Datentypen
|vortext=Datentypen}}
</noinclude>
dddx8p5l3d7oal49iw3ww7qfh4uearj
Programmieren in C/C++: Datentypen
0
118049
1090840
1090601
2026-09-15T06:14:19Z
D. Justen
102048
Formatierung geändert
1090840
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C kennt nachfolgende grundlegende Datentypen und Zeiger auf diese Datentypen (siehe auch [[Programmieren in C/C++: Grundlagen# Grundlegende Datentypen und Typsicherheit| Grundlagen:Grundlegende Datentypen und Typsicherheit]])
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| [[#Ganzzahl Datentypen|Ganzzahl]] ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| [[#Gleitkomma Datentypen|Gleitkommazahl]] ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Array|Arrays]] ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| [[#Struktur/Verbundtyp|Strukturen]]/[[#Union|Unions]] ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| [[#Enum/Aufzählungstyp|Aufzählungstyp]] ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Grundlagen #Boolescher-Datentype/Operatoren|Boolescher Datentyp]] ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| [[#Komplexe Zahlen|Komplexe Zahlen]] ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
Bis auf die Datentypen Funktionen, Array und die Zeiger sollen die wesentlichen Aspekte dieser Datentypen im nachfolgenden beschrieben werden.
'''Der grundlegende Datentyp ist <code>int</code>!'''
* Es wird mit nichts Kleinerem gerechnet als mit dem Datentyp <code>int</code> (siehe [[#Implizite Typumwandlung | Implizite Typumwandlung]]) :
:<syntaxhighlight lang="C">
char var1=10,var2=20,var3;
var3=var1+var2; //Addition findet auf Basis des Datentyps int statt
</syntaxhighlight>
* Es gibt zwar den Booleschen Datentyp, dieser entspricht jedoch einem Ganzzahldatentyp und <code>true</code> und <code>false</code> entsprechen den Integerwerten 0 und 1
* Der Aufzählungsdatentyp und seine Aufzählungselemente sind vom Datentyp <code>int</code>
* Bis einschl. C90 wurde bei der Definition von Variablen ohne Angabe des Datentyps, bei Definition einer Funktion ohne Angabe des Datentyps der Übergabeparameter, des Rückgabedatentyps der Datentyp implizit auf int gesetzt (implizit int)
:<syntaxhighlight lang="C">
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}int main(int argc,char *argv[]) {
printf("%d",foo(1,var2));
return 0;
} | execCompilerOptions=-Wall -std=c90|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Ganzzahl Datentypen ==
Grundlegend kennt die Programmiersprache C nur zwei Ganzzahldatentypen:
* Datentyp: <code>int</code>
: Vorzeichenbehafteter (signed) Datentyp, dessen Bitbreite von der Rechnerarchitektur und des Compilers abhängig ist
* Datentyp <code>char</code>
: Datentyp mit einer Mindestbreite von 8-Bit u.A. zur Speicherung von Zeichen typischerweise im ASCII Format. Die C-Spezifikation [C11 6.2.5 Types] lässt es dem Compiler frei, ob <code>char</code> als vorzeichenbehafteter oder vorzeichenloser Datentyp implementiert wird.
: Ergänzend kann der Datentyp <code>char</code> auch zur Speicherung von ganzen Zahlen genutzt werden. In diesem Fall empfiehlt sich, diese explizit als <code>signed</code> und <code>unsiged</code> zu definieren. Wenn nur ASCII Zeichen gespeichert werden, so ist diese Angabe nicht nötig!
Optional können Qualifier dem Datentyp vorangestellt werden:
* <code>unsigned</code> / <code>signed</code> zur Angabe, ob der Inhalt als vorzeichenlose Zahl oder als vorzeichenbehaftete Zahl zu interpretieren ist. Ohne Angabe sind Variablen vom Datentyp <code>int</code> vorzeichenbehaftet
* <code>short</code> / <code>long</code> / <code>long long</code> (letzteres seit C99) als vorangestellten Qualifier zu <code>int</code> zur Vergrößerung/Verkleinerung der Bitbreite. Bei Angabe des Qualifiers ist das Schlüsselwort <code>int</code> optional. Die Beschreibung <code>long long int</code> und <code>long long</code> sind gleichbedeutend!
Als Bitbreite für die Datentypen ist im C-Standard nur ein Mindestbreite definiert. Die genaue Bitbreite hängt von der Rechenbreite des Systems und vom Compiler ab (siehe [C11 6.2.5 Types]):
{| class="wikitable"
|-
! Datentype !! Mindest<br />breite !! Typisch bei 32-Bit<br />Architektur !! Typisch bei 64-Bit<br />Architektur !! printf Format<br />Anweisung
|-
| <code>char</code> || 8 || 8 || 8 || <code>%c</code>
|-
| <code>signed char</code><br /><code>unsigned char</code>|| 8 || 8 || 8 || <code>%hhd</code><br /><code>%hhu</code>
|-
| <code>short</code><br /><code>short int</code>|| 16 || 16 || 16 || <code>%hd</code> / <code>%hu</code>
|-
|<code>int</code>|| 16 || 16/32 || 32 || <code>%d</code> / <code>%u</code>
|-
|<code>long</code><br /><code>long int</code>|| 32 || 32 || 32/64 || <code>%ld</code> / <code>%lu</code>
|-
|<code>long long</code><br /><code>long long int</code>|| 64 || 64 || 64 || <code>%lld</code> / <code>%llu</code>
|}
In der Header-Datei <code>limits.h</code> sind die tatsächlichen Grenzwerte der Datentypen gespeichert:
{| class="wikitable"
|-
! Konstante !! Beschreibung !! Typ. bei 64-Bit Architektur
|-
| <code>CHAR_BIT</code> || Anzahl der Bits in einem Char || 8
|-
| <code>SCHAR_MIN</code> || min. Wert, den der Typ bei signed char aufnehmen kann || -128
|-
| <code>SCHAR_MAX</code> || max. Wert, den der Typ bei signed char aufnehmen kann || 127
|-
| <code>UCHAR_MAX</code> || max. Wert, den der Typ bei unsigned char aufnehmen kann || 255
|-
| <code>CHAR_MIN</code> || min. Wert, den der Typ char aufnehmen kann || 0 oder SCHAR_MIN
|-
| <code>CHAR_MAX</code> || max. Wert, den der Typ char aufnehmen kann || SCHAR_MAX oder UCHAR_MAX
|-
| <code>SHRT_MIN</code> || min. Wert, den der Typ short int annehmen kann || -32.768
|-
| <code>SHRT_MAX</code> || max. Wert, den der Typ short int annehmen kann || 32.767
|-
| <code>USHRT_MAX</code> || max. Wert, den der Typ unsigned short int annehmen kann || 65.535
|-
| <code>INT_MIN</code> || min. Wert, den der Typ int annehmen kann || -2.147.483.648
|-
| <code>INT_MAX</code> || max. Wert, den der Typ int annehmen kann || 2.147.483.647
|-
| <code>UINT_MAX</code> || max. Wert, den der Typ unsigned int aufnehmen kann || 4.294.967.296
|-
| <code>LONG_MIN</code> || min. Wert, den der Typ long int annehmen kann || -2.147.483.648 oder<br />-9.223.372.036.854.775.808
|-
| <code>LONG_MAX</code> || max. Wert, den der Typ long int annehmen kann || 2.147.483.647 oder<br />9.223.372.036.854.775.807
|-
| <code>ULONG_MAX</code> || max. Wert, den der Typ unsigned long int annehmen kann || 4.294.967.296 oder<br />18.446.744.073.709.551.616
|-
| <code>LLONG_MIN</code> || min. Wert, den der Typ long long int annehmen kann || -9.223.372.036.854.775.808
|-
| <code>LLONG_MAX</code> || max. Wert, den der Typ long long int annehmen kann || 9.223.372.036.854.775.807
|-
| <code>ULLONG_MAX</code> || max. Wert, den der Typ unsigned long long int annehmen kann || 18.446.744.073.709.551.615
|}
Aufgrund dessen, dass die Breite der Datentypen von der Rechnerarchitektur und vom Compiler abhängig ist, sind in der Header-Datei <code>stdint.h</code> Aliase für Datentypen enthalten, welche in ihrem Alias die tatsächliche Breite und das Vorzeichens beinhalten:
<syntaxhighlight lang="C">
uint8_t --> unsigned 8-Bit
int8_t --> signed 8-Bit
uint16_t --> unsigned 16-Bit
int16_t --> signed 16-Bit
...
</syntaxhighlight>
Für C++ sehen diese Datentypen wie folgt aus:
<syntaxhighlight lang="C++">
std::intptr_t
std::int8_t std::uint8_t
std::int16_t std::uint16_t
std::int32_t std::uint32_t
Std::int64_t std::uint64_t
</syntaxhighlight>
Zur Erzeugung von portablen/rechnerunabhängigen Programmen empfiehlt sich, diese Datentypen zu nutzen. Die Rechenbreite ist dann unabhängig vom Compiler und Betriebssystem.
== Gleitkomma Datentypen ==
Gleitkommazahlen werden im Computer auf Basis folgender Schreibweise dargestellt (siehe auch: {{w|Gleitkommazahl}}):<br />
<syntaxhighlight lang="C">
Dezimalsystem Dualsystem
12,3456710 = 1234567 * 10^-5 0,110 = 1,1001100110011 * 2^-4
------- -- --------------- --
Mantisse Exponent Mantisse Exponent
</syntaxhighlight>
;Mantisse: Vorzeichenlose ganze Zahl (ggf. mit einer festen Position des Dezimalpunktes=Festkommazahl)
;Exponent: Vorzeichenbehaftete ganze Zahl, welche um einen Bias verschoben ist
;Vorzeichen: Vorzeichen der (vorzeichenlosen) Mantisse
Zur Speicherung im Computer werden das Vorzeichen, die Mantisse und der Exponent getrennt im Binärformat gespeichert, für den Programmierer aber als eine (zusammenhängende) Zahl dargestellt:
[[File:Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse.png|thumb|400px|center|Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse]]
Gleitkommazahlen haben genauso wie ganze Zahlen einen beschränkten Wertebereich:
* Die Anzahl der Bits der Mantisse bestimmen die Anzahl der Nachkommastellen:
:<syntaxhighlight lang="C">
Bei 23-Bit Mantisse ist die max. Zahl 2^-23-1=0,000000119,
welches 6..7 dezimale Stellen entspricht!
</syntaxhighlight>
* Mit dem Exponent kann 'quasi' der kleinste und der größte Wertebereich angegeben werden:
:<syntaxhighlight lang="C">
Bei 8-Bit Exponent mit einem Bias von 127 liegt der Wertebereich des
Exponenten im Bereich von -126 … +127 (Exponent -127 und +127 wird zur
Darstellung weitere Zahlen benötigt).
Die kleinste darstellbare Zahl (unter Vernachlässigung der Nachkommastellen der Mantisse ist:
2^-126=1/2^126≅1,175*10^-38
Die größte darstellbare Zahl ist:
2^127 ≅1,7*10^38
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
float sqrtf(float);
float powf(float,float);
#include <ieee754.h>
#include <complex.h>
union test {
unsigned int i;
float f;
union ieee754_float b;
};
int main(int argc,char *argv[]) {
union test var = {.f=-0.1};
printf("Float=%f Binär=%032b\n",var.f,var.i);
printf("v=0b%b e=0b%08b m=0b(1).%023b\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%10d m=%29d\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%d-%d=%d m=1+%d/2^-23=%f\n",var.b.ieee.negative,
var.b.ieee.exponent,IEEE754_FLOAT_BIAS,var.b.ieee.exponent-IEEE754_FLOAT_BIAS,
var.b.ieee.mantissa,1.0+var.b.ieee.mantissa*1.0/(1<<23));
printf("\n--- Beispiele von Genauigkeitsprobleme im Umgang mit Gleitkommazahlen (hier float) ----\n");
printf("powf(sqrtf(%1.8f),2) = %1.8f\n",2.0f,powf(sqrtf(2.0f),2));
printf("%f + %f = %f\n",2000.0,0.0004,(double)(2000.0f+0.0004f));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Grundlegend kennen die Programmiersprachen C/C++ folgende Gleitkommadatentypen:
* Datentyp: <code>float</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindesten 6 Stellen betragen, so dass der Datentyp typischerweise 32-Bit groß ist
* Datentyp: <code>double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, so dass der Datentyp typischweise 64-Bit Große ist
* Datentyp: <code>long double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, damit könnte dieser Datentyp gleich dem Datentyp <code>double</code> gesetzt werden. In der Tat ist die Datenbreite Rechner- und Compilerabhängig. Einige Compiler setzen diesen Datentyp identisch zu <code>double</code>, bei x86 Prozessoren wird aufgrund der Hardwareunterstützung 80-Bit genutzt (wobei in der Tat der Datentyp dann 16-Byte Speicherplatz beansprucht) und einige Systeme nutzen 128-Bit (wobei hier aufgrund ggf. fehlender Hardwareunterstützung Operationen mit diesem Datentyp per Software emuliert werden) (siehe Wikipedia Artikel {{w|lang=en|Long_double|long double}}).
Die genaue Darstellung (Anzahl der Bits für Mantisse und Exponent, Darstellung von NAN/INF, ….) ist in C nicht spezifiziert und somit compiler- und rechnerabhängig. Zumeist wird mittlerweile die {{w|IEEE 754}} Standardisierung genutzt (Norm wurde von Intel mit der Entwicklung der 8087 FPU entworfen).
Grunddatentypen und der Wertebereich (nach {{w|IEEE 754}})
{| class="wikitable"
|-
! Daten-<br/>type !! Speicher-<br />platz !! Exponent !! Mantisse !! Größte Zahl !! Kleinste Zahl !! Genauigkeit !! printf Format Anweisung
|-
| binary32→<code>float</code> || 4 Byte || 8 bit || 23 bit || ~3,4*10<sup>38</sup> || ~1,2*10<sup>-38</sup> || 7..8 Stellen || ---
|-
| binary64→<code>double</code> || 8 Byte || 11 bit || 52 bit || ~1,8*10<sup>308</sup> || ~2,2*10<sup>-308</sup> || 15..16 Stellen || %f %e %g
|-
| binary64 extended→<code>long double</code> || ≥10 Byte || ≥15 bit || ≥63 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 19..20 Stellen || %Lf %Le %Lg
|-
| binary128→<code>long double</code> || 16 Byte || 15 bit || 112 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 34 Stellen || %Lf %Le %Lg
|}
Die tatsächliche Auflösung der Datentyps kann auf Basis nachfolgender Konstanten, definiert in der Header-Datei <code>float.h</code>, ermittelt werden:
:<syntaxhighlight lang="C">
FLT_DIG --> Anzahl der dezimalen Nachkommastellen für float
DBL_DIG --> Anzahl der dezimalen Nachkommastellen für double
LDBL_DIG --> Anzahl der dezimalen Nachkommastellen für long double
FLT_MIN_10_EXP --> Minimaler Exponent zur Basis 10
DBL_MIN_10_EXP
LDBL_MIN_10_EXP
FLT_MAX_10_EXP --> Maximaler Exponent zur Basis 10
DBL_MAX_10_EXP
LDBL_MAX_10_EXP
LDBL_MANT_DIG --> Anzahl der Bits für die Mantisse
LDBL_MANT_DIG
LDBL_MANT_DIG
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <float.h>
int main(){
printf("FLT_DIG =%u\n",FLT_DIG);
printf("DBL_DIG =%u\n",DBL_DIG);
printf("LDBL_DIG =%u\n",LDBL_DIG);
printf("FLT_MIN_10_EXP =%d\n",FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP =%d\n",DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP=%d\n",LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP =%d\n",FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP =%d\n",DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP=%d\n",LDBL_MAX_10_EXP);
printf("FLT_MANT_DIG =%d\n",FLT_MANT_DIG);
printf("DBL_MANT_DIG =%d\n",DBL_MANT_DIG);
printf("LDBL_MANT_DIG =%d\n",LDBL_MANT_DIG);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Aufgrund des nicht standardisierten Formates sollte ein Gleitkommadatentyp nicht im Binärformat für den Datenaustausch (mit Netzwerk, über Dateien, ..) genutzt werden. Andere Rechnersysteme/Programmiersprachen würde aufgrund der anderen Interpretation andere Zahlenwerte aus den übertragenen/gespeicherten Binärdaten auslesen!
<syntaxhighlight lang="C">
float var1;
write(file_hdl,&var1,sizeof var1); //Schreiben des Binärwertes
//in eine Datei
double var2;
send(socket_hdl,&var2,sizeof var2,0);//Senden des Binärwertes
//über ein Netzwerk
</syntaxhighlight>
Die Standard-C-Library bietet einige mathematische Funktionen wie <code>sin() / cos() / tan() / atan2() / sqrt() / pow() / exp()/…</code> an. Die Prototypen dieser Funktion sind in der Header-Datei <code>math.h</code> beschrieben, so dass diese bei Nutzung dieser Funktion zu inkludieren ist. Ergänzend ist die Shared Library libm.so über den Compilerschalter '-lm' einzubinden:
<syntaxhighlight lang="C">
#include <math.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
double sqrt(double);
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
printf("var1=%f var2=%f\n",var1,var2);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen basieren auf den Datentyp <code>double</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist vom Datentyp <code>double</code>. Die Prototypen sehen wie folgt aus:
<syntaxhighlight lang="C">
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double); //Wertebereich der Rückgabe von -PI/2..+PI/2
double atan2(double,double); //Wertebereich der Rückgabe von -Pi .. +PI
double sqrt(double);
double log(double);
</syntaxhighlight>
Über den Suffix f oder l im Funktionsnamen kann der zugrundeliegende Datentyp auf float (Suffix f) oder long double (Suffix l) geändert werden:
<syntaxhighlight lang="C">
float sinf(float);
long double sinl(long double);
</syntaxhighlight>
Ergänzend zu den Prototypen sind die gebräuchlichen Naturkonstanten in <code>math.h</code> definiert (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
M_E Value of e
M_LOG2E Value of log_2 e
M_LOG10E Value of log_10 e
M_LN2 Value of log_e 2
M_LN10 Value of log_e 10
M_PI Value of π
M_PI_2 Value of π/2
M_PI_4 Value of π/4
M_1_PI Value of 1/π
M_2_PI Value of 2/π
M_2_SQRTPI Value of 2/√π
M_SQRT2 Value of √2
M_SQRT1_2 Value of 1/√2
</syntaxhighlight>
Gleitkommazahlen können nicht nur Zahlenwerte, sondern auch Sonderwerte annehmen. Diese Sonderwerte sind ebenfalls in <code>math.h</code> beschrieben (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
INFINITY A constant expression of type float representing
positive or unsigned infinity, if available; else a
positive constant of type float that overflows at
translation time.
NAN A constant expression of type float representing a
quiet NaN. This macro is only defined if the
implementation supports quiet NaNs for the float type.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <math.h>
//Quelle: https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c
#ifdef NAN
#define NAN_STR "NAN is supported"
#else
#define NAN_STR "NAN is not supported"
#endif
#ifdef INFINITY
#define INFINITY_STR "INFINITY is supported"
#else
#define INFINITY_STR "INFINITY is not supported"
#endif
int main(int argc, char *argv[argc]) {
printf("%s\n%s\n",NAN_STR,INFINITY_STR);
double x=0.0;
double y=1/x;
printf("1/%e -> %e\n",x,y);
if(y==INFINITY)
printf("1) Initinity\n");
if(isinf(y)) //besser
printf("2) Initinity\n");
printf("%llx\n%llx\n\n",*(long long *)&y,INFINITY);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
double z=-(x/x);
printf("%e/%e -> %e\n",x,x,z);
if(z == NAN) //funktioniert nicht
printf("1) Not a Number\n");
if(isnan(z)) //besser
printf("2) Not a Number\n");
if(z != z)
printf("3) Not a Number\n");
printf("%llx\n%llx",*(long long *)&z,NAN);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
return 0;
} | execCompilerOptions=-lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit <code>fesetround()/fegetround()</code> kann gesetzt/gelesen werden, wie mit Ergebnissen umzugehen sind, die nicht exakt darstellbar sind. Mögliche Werte sind 'round to nearest' (default), 'round up', 'round down' und 'round toward zero'.
== Komplexe Zahlen ==
Nach dem Wikipedia Artikel {{w|komplexe Zahlen}} ''stellen komplexe Zahlen eine Erweiterung der reellen Zahlen dar. Ziel der Erweiterung ist es, algebraische Gleichungen wie x<sup>2</sup>+1=0 bzw. x<sup>2</sup>=-1 lösbar zu machen. ... Da die Quadrate aller reellen Zahlen größer oder gleich 0 sind, kann die Lösung der Gleichung x<sup>2</sup>=-1 keine reelle Zahl sein. Man braucht eine ganz neue Zahl, die man üblicherweise i nennt, mit der Eigenschaft i<sup>2</sup>=-1. Diese Zahl i wird als imaginäre Einheit bezeichnet.
Komplexe Zahlen werden nun als Summe a+b*i definiert, wobei a und b reelle Zahlen sind und i die oben definierte imaginäre Einheit ist.''<br />
Der Datentyp für komplexe Zahlen (erst ab C99 enthalten) beinhaltet folglich zwei Gleitkommazahlen, eine für den reelen Teil und eine für den imaginären Teil. Entsprechend den Gleitkommazahlen steht der komplexe Datentyp ebenfalls in drei unterschiedlichen Genauigkeiten zur Verfügung:
{| class="wikitable"
|-
! Datentype !! Speicherplatz
|-
| <code>float _Complex</code> || 2x4Byte
|-
| <code>double _Complex</code><br /><code>_Complex</code> || 2x8Byte
|-
| <code>long double _Complex</code> || 2x10Byte
|}
Wie auch beim Booleschen Datentyp ist in der Header-Datei <code>complex.h</code> für den einfacheren Umgang mit diesem Datentyp das Makro <code>complex</code> als Textersetzung für <code>_Complex</code> gesetzt.
Zur Darstellung von komplexen Konstanten wurde die Gleitkommakonstante um den Suffix i ergänzt. Durch Anhängen von i wird aus dem ansonsten rellen Teil der imaginäre Teil und damit aus der Gleitkommakonstante eine komplexe Gleitkommakonstante:
<syntaxhighlight lang="C">
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Normale Gleitkommavariablen werden als reellen Teil einer komplexen Zahl angesehen. Bei Operationen von Gleitkommazahlen und komplexen Zahlen wird der imaginäre Teil der Gleitkommazahl auf 0 gesetzt. Beim Zuweisen einer komplexen Zahl an eine Gleitkommazahl wird nur der reele Teil 'gelesen'.<br />
Soll eine Gleitkommavariablen zu einem imaginären Teil gewandelt werden, so muss diese bspw mit der Konstanten 1.0i multipliziert werden:
<syntaxhighlight lang="C">
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C-Library bietet diverse mathematische Funktionen wie csin(), ccos(), csqrt(), cpow() und ergänzend Umrechnungsfunktionen von Gleitkommazahlen in komplexe Zahlen (und umgedreht) wie creal(),cimag() ,cabs() für den Umgang mit komplexen Zahlen an:
<syntaxhighlight lang="C">
double _Complex csin(double _Complex);
double _Complex csqrt(double _Complex);
double creal(double _Complex);
double cimag(double _Complex);
</syntaxhighlight>
Zur Nutzung dieser Funktionen muss die Header-Datei <code>complex.h</code> inkludiert und ergänzend die Shared Library libm.so über den Compilerschalter '-lm' eingebunden werden.
<syntaxhighlight lang="C">
#include <complex.h>
//Math-Library mittels Linker-Command '-lm' einbinden
int main(int argc, char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen beruhen auf den Datentyp <code>double _Complex</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist <code>double _Complex</code> resp. <code>double</code> (bei den Umrechnungsfunktionen). Über den Suffix f und l im Funktionsnamen kann der zugrundeliegende Datentyp geändert werden:
<syntaxhighlight lang="C">
float crealf(float _Complex z);
long double creall(long double _Complex z);
</syntaxhighlight>
Hinweis:
* Der Datentyp <code>_Complex</code> und die dazugehörigen mathematischen Funktionen sind in der C-Spezifikation als optional gekennzeichnet.
== Generische mathematische Funktionen ==
In der <code>tgmath.h</code> Header Datei sind für die mathematischen Funktionen Makros enthalten, welche den Datentyp der Übergabeparameter bestimmen und basierend auf den Datentyp die dazugehörige mathematische Funktion aufrufen.
<code>tgmath.h</code> selbst inkludiert <code>math.h</code> und <code>complex.h</code>, so dass diese nicht weiter zu inkludieren sind.
Steht für den Übergabedatentyp keine passende Funktion zu Verfügung, so ist das Verhalten des Makros undefiniert (bspw. wenn ein komplexes Argument an eine Funktion übergeben wird, die nur für Gleitkommazahlen ausgelegt ist <code>ceil(1+2i);</code> )
Folgendes Regelwerk wird angewendet:
* Ist einer der Übergabeparameter imaginär, so ist die ausgewählte Funktion in der Spezifikation der Funktion beschrieben
* Ist einer der Übergabeparameter Komplexe, so wird die Komplexe Variante der Funktion aufgerufen, andernfalls die Gleitkomma Variante
* Ist einer der Übergabeparameter vom Datentyp <code>long double</code>, so wird die <code>long double</code> Variante, bei integer und double die <code>double</code> Variante und andernfalls die <code>float</code> Variante aufgerufen
Beispiel:
<syntaxhighlight lang="C">
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
int main(int argc,char *argv[]) {
foo(1l+1li,2.0l,3.0f,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=c
}} Öffnen im Compiler Explorer] }}
== Boolschescher Datentyp ==
Siehe [[Programmieren in C/C++: Grundlagen#Boolescher-Datentype/Operatoren|Grundlagen: Boolescher-Datentype/Operatoren]]
== void / unvollständiger Datentype ==
Der Datentyp <code>void</code> dient vorrangig dazu, nicht vorhandene Über- und Rückgabewerte von Funktionen anzuzeigen. Eine Variable vom Datentyp <code>void</code> kann nicht angelegt werden. Ein Zeiger vom Datentyp <code>void</code> ist möglich, kann aber nicht dereferenziert werden (siehe Kap. [[Programmieren in C/C++: Zeiger #Void-Zeiger| Zeiger:Void-Zeiger]])
<syntaxhighlight lang="C">
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* <code>sizeof(void)</code> ist nach der C-Spezifikation nicht erlaubt. Dennoch geben viele Compiler hier den Wert 1 zurück!
* Mit einem expliziten Cast auf den Datentyp void wird dem Compiler mitgeteilt, dass diese Variable in Gebrauch ist, der Wert in dieser Operation aber nicht genutzt wird. Hierüber kann die Compilerwarning 'unused Variable' unterbunden werden:
:<syntaxhighlight lang="C">
void func(int par1, int par2) {
int var1=12;
int var2=13;
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int par1, int par2) {
int var1=12;
int var2=13;
int var3=14; //Nicht genutzte Variable
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
printf("Genutzt\n");
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Datentypkonvertierung ==
Für das Rechnen/Vergleichen müssen beide Operatoren vom identischen Datentyp sein! Sind diese nicht identisch, so müssen die Datentypen 'angeglichen' werden. Dies kann einerseits ‚automatisch‘ mittels 'implizierter' Typumwandlung oder ‚manuell‘ mittels ‚expliziter' Typumwandlung erfolgen.<br />
Beim Zuweisungsoperator (inkl. Parameterzuweisung bei Funktionsaufrufen und Funktionsrückgabewerte mittels return) gilt dies ebenso, nur dass hier der Quelldatentyp an den Zieldatentyp angepasst werden muss. Die impliziten Regeln finden hier keine Anwendung.
Hinweis:
* Empfehlenswert ist, die Datentypen der Variablen so zu wählen, dass der Compiler keine implizite Typumwandlung tätigt. Kann dies nicht vermieden werden, so sollte die explizite Typumwandlung genutzt werden (um sich einen möglichen Datenverlust bewusst zu machen)
* Der Datentyp selbst sollte den möglichen Wertebereich der Variablen entsprechen und nicht unnötig groß gewählt werden
:<syntaxhighlight lang="C">
Datentyp zur Speicherung der Stundenzeit:
Wertebereich: 0 ... 23 -> unsigned char
Datentyp zur Speicherung einer Jahreszahl:
Wertebereich: 2000 v.C. ... 4000 n.C -> signed short
Datentyp zur Speicherung einer Temperatur:
Wertebreich: -273,0°C ... 2000,0°C -> float
</syntaxhighlight>
=== Implizite Typumwandlung ===
Diese Regeln wurden so aufgestellt, dass dabei stets ein Datentyp in einen anderen Datentyp mit höherem Wertigkeit umgewandelt wird [C11 6.3.1.8] und [Harbison: S 199]. Bei Ganzzahlen gilt ergänzend folgende (Rangordnung [C11 6.3.1.1]: long long, long, int, short,char,_Bool):
{| class="wikitable"
|-
! Regel/<br />Priorität !! If either operand<br />has Type !! And the other operand<br />has Type !! Converts both to
|-
| 1 (hoch) || long double || any real type || long double
|-
| 2 || double || any real type || double
|-
| 3 || float || any real type || float
|-
| 4 || any unsigned type || any unsigned type || the unsigned type<br/>with the greater rank
|-
| 5 || any signed type || any signed type || the signed type<br/>with the greater rank
|-
| 6 || any unsigned type || a signed type with a equal<br/> or less rank || the unsigned type
|-
| 7 || any unsigned type || a signed type that can represent<br/>all of values of the unsigned type || the signed type
|-
| 8 (niedrig) || any other type || any other type || both operands are<br/> converted to the unsigned <br/>integer type corresponding<br/> to the type of the operand<br/> with the signed<br/> integer type
|}
Ergänzend gilt das Regelwerk zu Integer Promotion, welche Datentypen kleiner als <code>signed int</code> zu <code>int</code> und kleiner als <code>unsigned int</code> zu <code>unsigned int</code> konvertiert (Compiler kann hiervon abweichen, wenn sichergestellt ist, dass kein Datenverlust eintritt).
Regel 6 und 7 sind der nicht klar definierten Bitbreite der ganzzahligen Datentypen geschuldet und versuchen, Konvertierungsverluste zu vermeiden. Sie lesen sich zunächst kryptisch, lassen sich aber einfach am folgenden Beispiel erklären:
<syntaxhighlight lang="C">
Operand 1: unsigned int (hier 32-Bit)
Operand 2: long (hier 32-Bit / 64-Bit)
</syntaxhighlight>
* Im Fall, dass der Datentyp <code>long</code> 64-Bit breit ist, kann dieser problemlos die vorzeichenlose 32-Bit Zahl ohne Konvertierungsverluste repräsentieren, so dass der Zieltype <code>signed long</code> ist (Regel 7)
* Im Fall, dass der Datentyp <code>long</code> 32-Bit breit ist, kann dieser mit seinen Wertebereich von -2.147.483.648 bis +2.147.483.647 nicht den vorzeichenlosen Zahlenbereich von 0…4.294.967.295 darstellen. In diesem Fall hat der unsigned Datentyp einen höheren Rang, so dass als Zieltyp <code>unsigend long</code> gewählt wird (Regel 6)
'''Regel 6 bedeutet die Gefahr eines Konvertierungsverlustes, dessen man sich bewusst sein sollte!''' Diese tritt insb. dann in Kraft, wenn ein Operand vom Typ <code>unsigned long long</code> ist (64-Bit).
Beispiele von impliziten Typumwandlungen:
<syntaxhighlight lang="C">
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
vari=5.0*(int)sin(vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ Wikibooks Formatierung schlägt hier fehlt
double sin(double);
int main(int argc,char *argv[]) {
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
printf("vars=%hd\n",vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
printf("vars=%hd\n",vars);
vari=5.0*(int)sin(vars);
printf("vari=%d\n",vari);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
printf("vari=%d\n",vari);
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im CompilerExplorer können sie sich die impliziten Typumwandlungen anzeigen lassen. Dazu gehen sie bitte wie folgt vor:
:* Im Source-Fenster mit '+Add new' ein Compiler Fenster öffnen
:* Im Compiler-Fenster mit '+Add new' ein 'GCC Tree/RTL' Fenster öffnen
:* Im GCC Tree/RTL-Fenster unter 'Select a pass…' 'original tree' auswählen
Um implizite Typumwandlung besser erkennen zu können, wird oftmals bei Variablennamen die ''' 'Ungarische Notation' ''' angewendet (siehe {{w|Ungarische Notation}}). Aufgrund der besonderen Namensgebung kann der Programmierer ohne großen Aufwand frühzeitig mögliche Typkonflikte erkennen. Der Variablenname setzt sich wie folgt zusammen:
<syntaxhighlight lang="C">
{Präfix}{Datentyp}{Bezeichner}
</syntaxhighlight>
:'''Präfix''': p->Pointer h->Handle i->index c->count f->flag rg->Array
:'''Datentyp''': ch->Character st->string w->word b->byte…
:'''Bezeichner''': Zum Binden der Variable an eine konkrete Aufgabe (keine Unterstriche).
:Bezeichner ist optional, wenn aus Präfix und Datentyp die 'Aufgabe' der Variable direkt sichtbar ist
Beispiele:
<syntaxhighlight lang="C">
char rgchtemp[10]; //Array (Range) vom Datentyp character
int ich; //Index zum Adressieren eines Arrays vom Datentyp
//character
</syntaxhighlight>
=== Explizite Typumwandlung ===
Programmierer erzwingt durch explizite Typumwandlung (auch CASTen genannt) eine Umwandlung eines Datentyps in einen anderen. Dazu wird der Zieldatentyp in runden Klammern vor Quelldatentype geschrieben:
<syntaxhighlight lang="C">
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
In der Rangfolge der Operatoren steht der Cast-Operator unterhalb von bspw. Funktionsaufrufen, Arrayzugriffen aber auch der Dereferenzierung:
{| class="wikitable"
|-
! Priorität !! Symbol !! Assoziativität !! Bedeutung
|-
| 15 || ... || ... || ...
|-
| 14
||
++/-- (Präfix)<br />
+/- (Vorzeichen) <br />
<nowiki>!</nowiki>/~ <br />
&<br />
<nowiki>*</nowiki><br />
(TYP)<br />
...
|| R-L
||
Präfix-Inkrement/Dekrement<br />
Vorzeichen<br />
Logisches/Bitweises Nicht<br />
Adresse<br />
Zeigerdereferenzierung<br />
'''Typumwandlung (Explizites Cast)'''<br />
...
|-
| 13
||
* / %
|| L-R
|| Multiplikation/Division/Modulo
|-
| 12 || ... || ... || ...
|}
Im Zweifel gilt auch hier, den zu wandelnden Typ ergänzend zu klammern.
Hinweis:
* Bedenke, dass die explizite Typumwandlung so aufgestellt sein sollte, dass der Zieldatentyp dem notwendigen Datentyp entspricht. Andernfalls wendet der Compiler ergänzend eine implizierte Typumwandlung an:
:<syntaxhighlight lang="C">
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Mittels expliziter Typumwandlung können Ganzzahl nach Gleitkommazahlen (und andersherum) und Zeiger in einen anderen Zeiger und auf andere Datentypen gewandelt werden. Eine Konvertierung von Arrays, Strukturen, Unions zu anderen Datentypen als sich selbst ist weiterhin nicht möglich:
<syntaxhighlight lang="C">
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei den möglichen Konvertierungen sollte Folgendes berücksichtigt werden:
* '''Vorzeichenlose Ganzzahl''' → '''Vorzeichenlose Ganzzahl''': Wenn der Zieldatentyp größer ist, wird die Zahl durch führende '0' erweitert. Wenn der Zieldatentyp kleiner ist, werde die zu vielen Bitstellen abgeschnitten/verworfen (ggf. Datenverlust)
* '''Vorzeichenbehaftete Ganzzahl''' → '''Vorzeichenbehaftete Ganzzahl''': Wenn der Zieldatentyp größer ist, wird vorzeichenrichtig erweitertet (d.h. das Auffüllen erfolgt auf Basis des Vorzeichens). Wenn der Zieldatentyp kleiner ist, werden auch hier die zu vielen Bits abgeschnitten/verworfen (Vorsicht: Negative Zahlen können dabei in positive Zahlen gewandelt werden)
* '''Gleitkommazahl''' → '''Gleitkommazahl''': Hier wird vereinfacht ausgedrückt sowohl die Mantisse als auch der Exponent einzeln kopiert. Wenn die Zielmantisse kleiner ist, gehen 'Nachkommastellen' verloren. Wenn der Quellexponent einen größeren Wert beinhaltet, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf Unendlich gesetzt. Umgedreht, wenn der Quellexponent kleiner ist, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf 0 gesetzt
* '''Ganzzahl''' → '''Gleitkommazahl''': Hier wird, vereinfacht ausgedrückt, die Ganzzahl in die Mantisse kopiert. Um Datenverluste zu vermeiden, sollte die Bitbreite der Zielmantisse größer gleich der Bitbreite der Ganzzahl sein
* '''Gleitkommazahl''' → '''Ganzzahl''': Im Wesentlichen wird hier die Mantisse übernommen, so dass hier die Bitbreite des Zieldatentyps mindestens der Bitbreite der Mantisse sein sollte
* '''Zeiger''' ↔ '''Ganzzahl''': Die Konvertierung ist möglich. Da bei 64-Bit Systemen der Zeiger 64-Bit und Integer 32-Bit breit ist, meckert ggf. der Compiler. Für solche Fälle existieren die Datentypen 'intptr_t' und 'uintptr_t', über welche sichergestellt ist, dass ein Zeiger in einen Ganzzahldatentyp gespeichert werden kann!
* '''Zeiger''' ↔ '''Gleitkommazahl''': Diese Konvertierung ist nicht möglich!
* '''Struktur/Union''' ↔ '''Ganzzahl/Gleitkommazahl''': Diese Konvertierung ist nicht möglich. Es können nur einzelnen Strukturelemente konvertiert werden, sofern diese vom Typ Ganzzahl/Gleitkommazahl sind
* '''Array''' ↔ '''Ganzzahl/Gleitkommazahl''': Der Arrayname entspricht einen Zeiger, so dass hier ein Zeiger in eine Ganzzahl oder umgedreht konvertiert wird (siehe Zeiger ↔ Ganzzahl)
In C++ gibt es weitere CAST-Operatoren, auf welche hier derzeit noch nicht weiter eingegangen wird!
* Static_cast (Entspricht dem Expliziten Cast)
* Const_cast
* Dynamic_cast
* Reinterpret_cast
== Verbundtyp Struktur/Klasse (nur C++) ==
Nach dem Wikipedia Artikel {{w|Verbund (Datentyp)}} ist ''ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten können wiederum Verbünde enthalten, wodurch auch komplexe Datenstrukturen definiert werden können.<br />
Für jedes Strukturelement wird Speicher reserviert. Alle Strukturelemente liegen hintereinander im Speicher.''
<code>Syntax: struct Strukturname<sub>Opt</sub> {Datentype Strukturelementname; … }<sub>OPT</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Verbund entspricht einer Java Klasse mit dem Unterschied zu C (nicht C++) , dass ein Verbund keine Methoden beinhaltet und keine Zugriffsbeschränkung für die Attribute gesetzt werden können.
Der Syntax erlaubt es, gleichermaßen einen Datentyp (über Strukturname) zu definieren und Variablen von diesem Datentyp (über Variablenliste) anzulegen. Da beide Elemente optional sind, ergeben sich diverse Kombinationsmöglichkeiten:
* Nur Strukturname → Definition eines neuen Datentyps
:<syntaxhighlight lang="C">
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
var1.y=2;
var1.z=1;
printf("var1.x=%d var1.y=%d var1.z=%d\n",var1.x,var1.y,var1.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C: Der Strukturname ist nur mit dem vorangestellten <code>struct</code> gültig. Der Strukturname stellt somit einen eigenen Namensraum, getrennt von dem Namensraum der Variablen/Funktionen, dar. Daher kann ein Strukturname identisch zu einem Variablennamen sein:
:<syntaxhighlight lang="C">
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
xyz2.x=xyz2.y=xyz2.z=1;
printf("xyz2.x=%d xyz2.y=%d xyz2.z=%d\n",xyz2.x,xyz2.y,xyz2.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C++: Der Strukturname ist sowohl mit als auch ohne dem vorangestellten <code>struct</code> gültig. Auch hier stellt der Strukturname einen eigenen Namensraum dar, der jedoch eine niedrigere Priorität als der der Variablen hat:
:<syntaxhighlight lang="C++">
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz beschreibt hier die Variable
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz3 beschreibt hier die Variable
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
* Nur Variablenliste → Definition einer/mehrerer Variablen von einem 'unnamed' Datentyp
:<syntaxhighlight lang="C">
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Angewendet wird die Schreibweise gerne, wenn eine Struktur innerhalb einer Struktur definiert wird und die innere Struktur zur besseren Strukturierung dient:
:<syntaxhighlight lang="C">
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Strukturname und Variablenliste → Definition eines Datentyps und Definition von Variablen. D.h. es können im Nachhinein weitere Variablen von diesem Datentyp angelegt und die hier angelegten Variablen genutzt werden.
:<syntaxhighlight lang="C">
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y; //Nutzung der Variablen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y=1; //Nutzung der Variablen
(void)var1;
(void)ptr1;
(void)ptr2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Kein Strukturname und keine Variablenliste → "Anonymous Struct", d.h. Definition eines 'unnamed' Datentyps, von der ergänzend keine Variable angelegt wird. Anonymus Structs sind nur innerhalb von Strukturen erlaubt/einsetzbar. Hier dienen sie der besseren Strukturierung und ersparen dem Programmierer die Benennung des normalerweise notwendigen Strukturelementes:
:<syntaxhighlight lang="C">
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
(void)var;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Eine Struktur (und auch eine C++ Klasse) wird mit einem Semikolon abgeschlossen
* Eine alternative Beschreibung zu Strukturen finden sie in [https://abstractexpr.com/2023/06/29/structures-in-c-from-basics-to-memory-alignment/ Structures in C: From Basics to Memory Alignment]
=== Strukturelement ===
Innerhalb der Struktur können beliebige Strukturelemente von beliebigen Datentypen angelegt werden. Einzige Voraussetzung, der Datentyp des anzulegenden Strukturelementes muss zuvor definiert worden sein. Ergänzend kann der neue Datentyp auch in der Struktur selbst definiert werden, sofern mit der Definition des Datentyps auch eine Variable angelegt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zugriff auf Strukturelemente ===
Die Programmiersprachen C/C++ unterscheiden zwei 'Zugriffsarten' auf die Strukturelemente, abhängig vom zugrundeliegenden Datentyp des linken Operanden::
* Handelt es sich beim linken Operanden um eine (struct)Variablen, so erfolgt der Zugriff über den Punkt-Operator <code>.</code>:
:<syntaxhighlight lang="C">
struct {
int a,b,c;
} abc;
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct {
int a,b,c;
} abc;
int main(int argc,char *argv[]) {
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c=12;
printf("abc.a=%d abc.b=%d abc.c=%d\n",abc.a,abc.b,abc.c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Handelt es sich beim linken Operanden um einen Zeiger auf eine (struct)Variable, so erfolgt der Zugriff über den Zeiger-Operator <code>-></code>:
:<syntaxhighlight lang="C">
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
int main(int argc,char *argv[]) {
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Werden innerhalb von Strukturen weitere Strukturen und Zeiger auf Strukturen angelegt, so müssen diese Regeln auf jedes innere Strukturelement einzeln angewendet werden:
<syntaxhighlight lang="C">
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
int main(int argc,char *argv[]) {
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Strukturen ===
Mit dem Anlegen einer Strukturvariablen kann diese auch initialisiert werden. Eine 'Vorbelegung' der Strukturelemente bei der Definition der Struktur ist in C nicht möglich.<br />
Die Initialisierung erfolgt über eine Initialisierungsliste (siehe Kap [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]). Innerhalb der Initialisierungsliste stehen die Initialisierungswerte entweder in der Reihenfolge der Datentypdefinition oder werden explizit mit dem ‘.‘ Operator angesprochen (designated initializers). Werden einzelne Strukturelemente ausgelassen, so werden diese mit 0 initialisiert:
<syntaxhighlight lang="C">
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
int main(int argc,char *argv[]) {
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
printf("v1.a=%d v1.b=%d v1.str[0]=%d\n",v1.a,v1.b,v1.str[0]);
printf("v2.a=%d v2.b=%d v2.str[0]=%d\n",v2.a,v2.b,v2.str[0]);
printf("v3.a=%d v3.b=%d v3.str[0]=%d\n",v3.a,v3.b,v3.str[0]);
printf("v4.a=%d v4.b=%d v4.str[0]=%d\n",v4.a,v4.b,v4.str[0]);
printf("v5.a=%d v5.b=%d v5.str[0]=%d\n",v5.a,v5.b,v5.str[0]);
printf("v6.a=%d v6.b=%d v6.str[0]=%d\n",v6.a,v6.b,v6.str[0]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Initialisierung einer Struktur über nachfolgende Art bewirkt etwas anderes, als erwartet:
<syntaxhighlight lang="C">
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
printf("var.a=%d var.b=%d var.c=%d\n",var.a,var.b,var.c);
//Gerne mal den Compiler Wechseln
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der Initialisierungsliste wird über 'var.b=12' und 'var.c=3' die zu diesem Zeitpunkt noch nicht initialisierte Variable var die Elemente b und c initialisiert. Mit dem Werten der Initialisierungsliste (hier {12,3}) wird nachfolgend die Variable erneut initialisiert und 12 dem Strukturelement a und 3 dem Strukturelement b zugewiesen. Abhängig vom Compiler ist das Strukturelement c entweder 3 oder 0.
Bei verschachtelten Strukturen muss entsprechend obiger Aussage für jede innere Struktur eine eigene Initialisierungsliste erstellt werden. Die inneren Initialisierungslisten können entfallen, was jedoch nicht empfohlen wird und ergänzend vom Compiler bei '-Wall' als Warning angemerkt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8}}
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={{.x=5,.y=6},{7,8}},
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8} }
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={ {.x=5,.y=6},{7,8} },
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
int main(int argc,char *argv[]) {
printf("v1.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v1.a, v1.b, v1.xy.x, v1.xy.y, v1.arr[0].x, v1.arr[0].y, v1.arr[1].x, v1.arr[1].y );
printf("v2.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v2.a, v2.b, v2.xy.x, v2.xy.y, v2.arr[0].x, v2.arr[0].y, v2.arr[1].x, v2.arr[1].y );
printf("v3.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v3.a, v3.b, v3.xy.x, v3.xy.y, v3.arr[0].x, v3.arr[0].y, v3.arr[1].x, v3.arr[1].y );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zuweisen/Kopieren von Strukturen ===
Strukturen werden über den Namen als 'ganzes' angesprochen, so dass eine Zuweisung als 'ganzes' möglich ist. Bei bspw. einer 12-Byte großen Struktur werden bei Nutzung der Variable die gesamten 12-Byte gelesen/geändert!
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1,var2;
var1=var2; //12-Bytes kopiert
//--> entspricht memcpy(&var1,&var2,sizeof(xyz));
</syntaxhighlight>
Die Zuweisung als 'ganzes' gilt auch bei der Parameterübergabe und -rückgabe von Funktionen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;};
//Funktionsdefinition
struct xyz function(struct xyz par) {
return (struct xyz){par.z,par.y,par.x};
}
//Funktionsaufruf
struct xyz var=function((struct xyz){1,2,3});
//Mit dem Aufruf der Funktion werden 12-Bytes in die Variable par kopiert
//Mit dem Ende der Funktion werden 12-Bytes in die Variable var kopiert
</syntaxhighlight>
Bedenke, dass bei großen Strukturen das Kopieren Rechenzeit benötigt und folglich vermieden werden sollte! Alternativ sollten Zeiger auf Strukturen über- und zurückgeben werden.
Über Compound Literal (siehe Kap. [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]) kann einer Strukturvariablen als 'ganzes' einen neuen Wert zugewiesen werden:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
var1={.a=7}; //KO, Initialisierungsliste kann hier nicht
//angewendet werden
var1=(struct abc){.a=7}; //Wertezuweisung über Compound Literal möglich
</syntaxhighlight>
Formel gesehen entspricht das Compound Literal einer 'unnamed Variable', die als erstes angelegt und initialisiert wird. Der Inhalt dieser Variablen wird im Anschluss der eigentlichen Variable zugewiesen!
=== Prototyp / Deklaration einer Struktur ===
Soll der Datentyp einer Struktur genutzt werden, der erst an weiter hinten liegenden Stellen im Programm definiert wird, so ist wie bei Variablen/Funktionen ein Prototyp/Deklaration notwendig:
<syntaxhighlight lang="C">
struct abc; //Prototyp der Struktur abc
...
struct abc { int a,b,c;}; //Definition der Struktur abc
</syntaxhighlight>
Die Deklaration sagt einzig aus, dass die Struktur später definiert wird, beinhaltet aber nicht die Strukturelemente. Folglich kann auf Basis dieses Prototyps keine Variable definiert werden, sondern einzig ein Zeiger auf solche eine Struktur:
<syntaxhighlight lang="C">
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Anwendung:
* Struktur, welche auf sich selbst verweist (Verkettete Liste)
:<syntaxhighlight lang="C">
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
int main(int argc,char *argv[]) {
struct vl *head=NULL;
struct vl a={.daten="Ele a"};
struct vl b={.daten="Element b"};
struct vl c={.daten="c-Eleent"};
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL; //Zur Kennzeichnung des letzten Elementes
for(struct vl*ptr=head;ptr;ptr=ptr->next)
printf("'%s'\n",ptr->daten);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Entsprechend der objektorientierten Programmierung, wenn alle Attribute der Klasse private sind:
:{| class="wikitable"
|-
! !! class.h
|-
|
||<syntaxhighlight lang="C">
struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
</syntaxhighlight>
|-
! main.c !! class.c
|-
|<syntaxhighlight lang="C">
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
..
//Kein Zugriff auf
//Strukturelemente möglich
return 0;
}
</syntaxhighlight>
||<syntaxhighlight lang="C">
#include "class.h"
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *)
malloc(sizeof(struct class));
this->attr1=10;
*me=this;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
//..
//Kein Zugriff auf Strukturelemente möglich
return 0;
}
|class_h=struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
|class_c=#include "class.h"
#include <stdlib.h> //fuer malloc()
#include <stdio.h> //fuer printf()
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *) malloc(sizeof(struct class));
printf("konstructor called\n");
this->attr1=10;
*me=this;
}
| execCompilerOptions=-Wall class.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Vergleichen von Strukturen ===
Ein Vergleich von Strukturen über den direkten Weg ist nicht möglich. Vielmehr müssen die Strukturelemente händisch verglichen werden:
<syntaxhighlight lang="C">
struct xyz {int inx,y,z;} var1,var2;
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} var1={1,2,3},var2={1,2,3};
int main(int argc,char *argv[]) {
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
printf("Strukturelemente von var1 und var2 identisch\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis
* Bei Rechnerarchitekturen mit nicht ausgerichteter Speicherausrichtung (Alignment) kann ergänzend ein Vergleich über memcmp() erfolgen
=== Speicherplatzbedarf einer Struktur ===
Für jedes Strukturelement wird Speicher entsprechend der Größe des Datentyps reserviert. Der Speicherplatzbedarf der Gesamtstruktur ergibt sich aus der Summe der Strukturelemente:
<syntaxhighlight lang="C">
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
sizeof(var1) //ergibt 12
sizeof(struct xyz) //ergibt 12
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
int main(int argc,char *argv[]) {
printf("sizeof(var1)=%zu Bytes\n",sizeof(var1));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Ermittlung der tatsächlichen Speichergröße einer Struktur erfolgt über den sizeof-Operator:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;} a;
sizeof(a); //=12 OK
sizeof(a.x); //=4 OK
sizeof(struct xyz); //=12 OK
sizeof(struct xyz.x); // KO
//Ist dies dennoch notwendig, so kann dies über den Umweg eines Zeigers
//erfolgen:
sizeof(((struct xyz *)0)->x); //=4 OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x,y,z;
} a;
int main(int argc,char *argv[]) {
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
printf("sizeof(a.x)=%zu Bytes\n",sizeof(a.x));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
printf("sizeof(struct xyz.x)=%zu Bytes\n",sizeof(struct xyz.x));
printf("sizeof(((struct xyz *)0)->x)=%zu Bytes\n",sizeof(((struct xyz *)0)->x));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei Rechnerarchitekturen mit ausgerichteter Speicherausrichtung (Alignment) (siehe {{w|Speicherausrichtung}}) kann der tatsächliche Speicherbedarf größer sein! Hier fügt der Compiler ggf. zwischen den Strukturelemente Füllbytes (Padding Bytes) ein
* Die Reihenfolge der Strukturelemente wird vom Compiler nicht geändert. D.h. die Zuordnung der Speicherstellen zu den Strukturelementen erfolgt in der Definitionsreihenfolge
=== Interne Organisation ===
Compilerintern werden die Strukturelemente über einen Offset dargestellt. Das erste Strukturelement bekommt dabei immer den Offset 0 zugewiesen. Das nachfolgende Element bekommt als Offset die Größe des Datentyps des vorherigen Elementes zugewiesen. Usw.. <br />
Der Compiler setzt den Zugriff auf ein Strukturelement einer (Struktur)Variablen so um, dass er zunächst die Startadresse der Variablen holt und zu dieser den Offset des Strukturelementes addiert. Die Anzahl der zu lesenden/schreiben Bytes ergibt sich aus dem Datentyp des Strukturelementes:
<syntaxhighlight lang="C">
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1; //(Beispielhaft soll var1 die Speicheradressen
//0x100..0x10B belegen). Der Zugriff auf
//die Variable erfolgt immer über die Startadresse
var1.x=7; //Zugriff auf Speicheradresse 0x100+0 (Offset)
var1.y=8; //Zugriff auf Speicheradresse 0x100+4 (Offset)
var1.z=9; //Zugriff auf Speicheradresse 0x100+8 (Offset)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1;
int main(int argc,char *argv[]) {
//Zugriff siehe Compiler
var1.x=7; //mov DWORD PTR var[rip+0],7
var1.y=8; //mov DWORD PTR var[rip+4],7
var1.z=9; //mov DWORD PTR var[rip+8],7
return 0;
} | execCompilerOptions=-Wall|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Offset eines Strukturelementes kann mit dem offsetof-Operator ermittelt werden:
<code>Syntax: offsetof(type,Strukturelement)</code>
Wie beim sizeof-Operator gilt der offsetof-Operator als Konstantenausdruck und der Rückgabedatentyp ist <code>size_t</code>. Zur Nutzung des Operators muss die Header-Datei 'stddef.h' inkludiert werden:
<syntaxhighlight lang="C">
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var1;
offsetof(struct xyz,z) --> 8
offsetof(var1,z) --> KO: Es wird ein Datentyp und
keine Variable erwartet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz{
int x,y,z;
} var1;
int main(int argc,char *argv[]) {
printf("offsetof(struct xyz,x)=%zu Bytes\n",offsetof(struct xyz,x));
printf("offsetof(struct xyz,y)=%zu Bytes\n",offsetof(struct xyz,y));
printf("offsetof(struct xyz,z)=%zu Bytes\n",offsetof(struct xyz,z));
printf("offsetof(var1,z)=%zu Bytes\n",offsetof(var1,z));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Unter Nutzung des offsetof-Operators kann man bei gegebener Adresse eines Strukturelementes auf die Startadresse der zugrundeliegenden Struktur zurückrechnen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1;
int *ptri=&var1.y;
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var={1,2,3};
int *ptri=&var.y;
int main(int argc,char *argv[]) {
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
printf("ptrxyz->x=%d ptrxyz->y=%d ptrxyz->z=%d",ptrxyz->x,ptrxyz->y,ptrxyz->z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dazu wird von der Startadresse des Strukturelementes der Offset abgezogen. Da der offsetof-Operator den Abstand in Bytes zurückgibt, muss der Pointer auf das Strukturelement zuvor ebenfalls in ein 'Byte'-Zeiger gewandelt werden.
Im Linux kernel wird diese Subtraktion über das container_of Makro realisiert:
<syntaxhighlight lang="C">
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
</syntaxhighlight>
Dieses Makro ermöglicht es, bei gegeben Startadresse eines Strukturelementes die Startadresse der zugrundeliegenden Struktur zu berechnen. Anwendung findet dieses Makro bspw. in:
* der objektorientierten Programmierung, um ausgehend vom gegebenen Parent-Element die Startadresse des Child-Elementes zu berechnen:
:<syntaxhighlight lang="C">
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
..
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
printf("parent.attr1=%d parent.att2=%d\n",me->attr1,me->attr2);
printf("child.attr1=%d\n",child->attr1);
}
int main(int argc,char *argv[]) {
struct child obj1;
obj1.attr1=1;
obj1.parent.attr1=2;
obj1.parent.attr2=3;
parent_methode(&obj1.parent);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei verketteten Listen, wenn das Next-Element im Datensatz selbst eingearbeitet ist:
:<syntaxhighlight lang="C">
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(PTR, TYPE, MEMBER) \
((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
vl_t head={NULL};
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
int main(int argc,char *argv[]) {
daten_t obj1={.daten1=1,.daten2=2};
daten_t obj2={.daten1=3,.daten2=4};
vl_addfront(&obj1);
vl_addfront(&obj2);
daten_t *ret=vl_getfront();
printf("%d %d\n",ret->daten1,ret->daten2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Explizites Cast ===
Eine Struktur kann nicht in einen anderen Datentyp und damit auch nicht in einen anderen Strukturdatentyp mit identischen Strukturelementen konvertiert werden:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} xyz;
struct abc {int a,b,c;} abc;
int var;
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} xyz;
struct abc {
int a,b,c;
} abc;
int var;
int main(int argc,char *argv[]) {
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Incomplete Array ===
Das letzte Element einer Struktur kann ein Array ohne Angabe einer Dimensionsgröße sein (Incomplete Array/Flexible Array Member). Bei der Definition einer Variablen von solch einem Datentyp wird in der Tat kein Speicher für das letzte Element reserviert, so dass dies 'händisch' erfolgen muss. Auf das Array kann ungeachtet dessen unproblematisch zugegriffen werden:
<syntaxhighlight lang="C">
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert
//wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert wurde
//Zur Darstellung dieses Sachverhaltes wurde der Sanitizer
//über den Compilerschalter -fsanitize=address aktiviert
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Speicherplatzreservierung für das incomplete Array kann auf zwei verschiedene Arten erfolgen:
* Speicherplatzreservierung für das Incomplete Array über Variableninitialisierung (nur GCC-C und nur im Falle einer globalen Variablen)
:<syntaxhighlight lang="C">
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
int main(int argc,char *argv[]) {
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(ele1)=%zu Bytes\n",sizeof(ele1));
printf("sizeof(ele2)=%zu Bytes\n",sizeof(ele2));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Speicherplatzreservierung für das Incomplete Array über malloc
:<syntaxhighlight lang="C">
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
if(b==NULL)
return printf("malloc failed\n"),1;
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
//zum Beweis Sanitizer über -fsanitize=address eingebunden
free(b);
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Das Incomplete Array bietet sich überall dort an, wo Daten gespeichert werden sollen, deren Größe sich erst zur Laufzeit ergibt.
=== Anwendung ===
Die Nutzung des Datentyps struct empfiehlt sich an vielen Stellen:
* Zusammengehörende Daten zu Kapseln (entsprechend der objektorientierten Programmierung
* Verkette Listen
* Aufgrund der Typsicherheit zur Darstellung von sicherheitskritischen Aufgaben
Siehe Übungsbereich!
=== C++ ===
Der wesentliche Syntax von Strukturen wurde in C++ übernommen. D.h.:
* das abschließende Semikolon
* der Zugriff auf die Strukturelemente
* Speicherplatzreservierung
* die Definition von Variablen mit der Definition des Datentyps
* ...
Ergänzend wurde in C++ der Datentyp class eingeführt, der weitestgehend identisch zu struct ist. Geändert/Hinzugefügt wurden folgende Sachverhalte:
* Classen/Strukturen können Methoden haben
* Operatoren (Zuweisungsoperator, Addition, ...) können überladen werden
* Alle Strukturelemente (und Methoden) einer struct sind per default public
* Alle Attribute (und Methoden) einer Class sind per default private
* Zur Nutzung des Datentyps ist das führende struct nicht notwendig (dies bedingt dann auch, dass der Strukturdatentyp kein separater Namensraum ist)
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var_xyz;
</syntaxhighlight>
* Initialisierungswerte für Strukturelemente und Klassenattribute bei der Datentypbeschreibung angegeben werden können:
:<syntaxhighlight lang="C++">
struct xyz {
int x=3;
int y=1;
int z;
};
xyz var={7}; //var.x=7 var.y=1 var.z=0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x=3;
int y=1;
int z;
};
int main(int argc,char *argv[]) {
xyz var={7}; //var.x=7 var.y=1 var.z=0
printf("var.x=%d var.y=%d var.z=%d\n",var.x,var.y,var.z);
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In C++ kann eine Struktur ebenfalls über 'designated initializers' initialisiert werden. Jedoch muss die Reihenfolge der Initialisierungselement identisch zur Datentypdefinition sein. Auch ist keine Doppeltbenennung erlaubt:
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x,y,z;
};
int main(int argc,char *argv[]) {
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
(void)var1;
(void)var2;
(void)var3;
(void)var4;
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Union ==
Ähnlich wie eine Struktur ist ein Union ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wird. Bei sog. Union beginnen jedoch alle Komponenten nicht wie bei Strukturen an nacheinander folgenden Speicheradressen, sondern an der identischen Speicheradresse, d.h. ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union kann folglich zu einem Zeitpunkt nur ein Element enthalten. Der benötigte Speicherplatz ergibt sich aus der größten Komponente.
<code>Syntax: union Unionname<sub>Opt</sub> {Datentyp Variablenname; …}<sub>Opt</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Schutz/Zugriffssteuerung der Unionelemente ist nicht vorhanden. Es kann in beliebiger Reihenfolge auf die einzelnen Elemente zugegriffen werden.
Die Anwendung ist identisch wie bei Strukturen, so dass im Folgenden nur die Abweichungen zu den Strukturen beschrieben werden.
=== Speicherplatzbedarf und interne Struktur einer Union ===
Die Größe der Union ergibt sich aus dem größtem Unionelement. Alle Unionelemente überlappen sich, so dass der Offset zum Basiselement 0 ist:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird ein kleineres Unionelement belegt und im Anschluss ein größeres Unionelement gelesen, so ist der Inhalt der durch das kleinere Element nicht beschriebenen Speicherstellen undefiniert:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc.a=0x11;
printf("%08x",abc.c);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
};
void foo(int var) {
int lok=var;
printf("Foo(%#08x) called\n",lok);
}
void bar(void) {
union abc abc;
abc.a=0x11;
printf("abc.a=%#02x\n",abc.a);
printf("abc.c=%#08x\n",abc.c);
}
int main(int argc,char *argv[]) {
//Zur Darstellung des Phänomens muss
//erstmal der Stack mit Daten belegt werden!
foo(0x12345678);
bar();
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Union ===
Bei einer Union kann nur ein Element initialisiert werden, d.h. die Initialisierungsliste kann nur einen Wert beinhalten. Ohne explizite Benennung des Unionelementes in der Initialisierungsliste wird das erste Element aus der Datentypbeschreibung initialisiert. Mit expliziter Benennung mittels 'designated initializers' können auch andere Elemente initialisiert werden:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Anwendung ===
Mittels des Datentyps union können diverse Anwendungsfälle abgedeckt werden:
* Über Union lassen sich größere Datentypen in kleinere Datentypen unterteilen, um z.B. einzelne Bytes zu extrahieren:
<syntaxhighlight lang="C">
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union floatu var={1.234};
printf("%f\n",var.var); //Darstellung des Float-Wertes
printf("%x\n",var.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var.byte[0],var.byte[1],var.byte[2],var.byte[3]);
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
union longlong var2={0x123456789ABCDEFULL};
printf("%llx\n",var2.ll);
printf("%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
int main(int argc,char *argv[]) {
union floatu var1={1.234};
printf("var1.var=%f\n",var1.var); //Darstellung des Float-Wertes
printf("var1.hex=%x\n",var1.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("var1.byte[0..3]=%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var1.byte[0],var1.byte[1],var1.byte[2],var1.byte[3]);
union longlong var2={0x123456789ABCDEFULL};
printf("var2.ll=%llx\n",var2.ll);
printf("var2.i[0..1]=%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Ein weiterer Anwendungsfall ergibt sich, wenn in einer Struktur unterschiedliche Datensätze gespeichert werden sollen (siehe {{w|Tagged Union}}):
:<syntaxhighlight lang="C">
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
int main(int argc,char *argv[]) {
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mittels eines Tagged Union kann komfortabel ein Binärbaum realisiert werden:
:<syntaxhighlight lang="C">
//Quelle: https://github.com/Hirrolot/datatype99
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h> //fuer printf()
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Die Eigenschaften des Datentyps union entsprechen den Eigenschaften des Datentyps struct in C++.
== Enum/Aufzählungstyp ==
Nach dem Wikipedia Artikel {{w|Aufzählungstyp}} ist ''ein Aufzählungstyp (englisch enumerated type) ein Datentyp für Variablen mit einer endlichen Wertemenge. Alle zulässigen Werte des Aufzählungstyps werden bei der Deklaration des Datentyps mit einem eindeutigen Namen (Identifikator) definiert, sie sind Symbole.''
<code>Syntax: enum enumname<sub>Opt</sub> {definition-list[=expression]}<sub>Opt</sub> Variablenliste<sub>Opt</sub></code>
Die Anwendung ist identisch wie bei Strukturen, so dass nachfolgend nur die Abweichungen zu den Strukturen beschrieben werden.
=== Datentyp von enum ===
In C entspricht der Datentyp Enum dem Datentyp <code>int</code> so dass Zuweisungen/Vergleiche mit Ganzzahlen möglich sind. Ganzzahloperationen funktionieren ebenso:
<syntaxhighlight lang="C">
enum STATUS {OK,KO=5}; //Definition des Datentyps
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
status++;
status=5.7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum STATUS {OK,KO=5}; //Definition des Datentyps
int main(int argc,char *argv[]) {
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
printf("status == 5\n");
status++;
status=5.7;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Enumelemente ===
Die Elemente der Definitionsliste sind Integerkonstanten. Diese können auch in Kombination mit anderen Datentypen genutzt werden. Auch gibt es keinen gesonderten Namensraum für Elemente der Definitionsliste. Sie 'konkurrieren' folglich mit allen Variablen- und Funktionsnamen:
<syntaxhighlight lang="C">
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
int main(int argc,char *argv[]) {
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der erste Enumelement der Definitionsliste bekommt den Wert 0 zugewiesen. Folgeelemente bekommen den Wert des Vorgängerelementes +1 zugewiesen.
Enumelemente können mit einer Konstanten (und Konstantenausdruck) initialisiert werden:
<syntaxhighlight lang="C">
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
int main(int argc,char *argv[]) {
printf("bill=%d john=%d, fred=%d\n",bill,john,fred);
printf("error=%d warning=%d info=%d ok=%d\n",error,warning,info,ok);
printf("Ostfalia=%d Wolfenbuettel=%d\n",Ostfalia,Wolfenbuettel);
printf("test=%d\n",test);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Es empfiehlt sich, die Enumelemente in GROSSBUCHSTABEN zu schreiben. Hiermit wird gekennzeichnet, dass es sich um Konstanten und nicht um Variablen/Funktionen handelt
=== Anwendung ===
Die Nutzung des Datentyps enum empfiehlt sich überall dort, wo eine Fallunterscheidung notwendig ist:
* Statusrückgabe von Funktionen:
:<syntaxhighlight lang="C">
enum STATUS {OK,MEMORY_OVERFLOW, DIVISION_BY_ZERO};
enum STATUS funct(…) {
return MEMORY_OVERFLOW;
}
</syntaxhighlight>
* Beschreibung der Zustände und der Ereignisse eines Zustandsautomates:
:<syntaxhighlight lang="C">
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Ergänzend zu den Abweichungen bei Structs sind hier weitere Unterscheidungsmerkmale vorhanden:
* Enums stellen einen eigenen Datentyp dar, der nicht mit int kompatible ist. Das bedingt unter anderem, dass einige Operatoren wie z.B. ++ nicht mehr auf Variablen des Datentyps enum angewendet werden. Die Enumelemente als solches sind jedoch kompatibel zum Ganzzahldatentyp:
:<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
int main(int argc,char *argv[]) {
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
printf("RED==2\n");
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
* Auch enums können Methoden besitzen.
* Über Operatorüberladung können z.B. nicht vorhandene Operatoren wie ++/-- ergänzt werden
* Über unscoped/scoped Enumerations wird der 'Namensraum' gesteuert:
:* Unscoped Enumeration (Elemente der Definitionsliste stehen wie bei C im Zugriff)
::<code>Syntax: enum name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE };
Color r = RED;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE };
Color r = RED;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
:* Scoped enumeration (Elemente der Definitionsliste haben einen eigenen 'Namensraum')
::<code>Syntax: enum '''class|struct''' name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
== Bitfelder ==
Nach dem Wikipediaartikel {{w|Bitfeld}} ''bezeichnet in der Informationstechnik und Programmierung ein Bitfeld ein vorzeichenloses Ganzzahldatentyp, in dem einzelne Bits oder Gruppen von Bits aneinandergereiht werden. Es stellt eine Art Verbunddatentyp auf Bit-Ebene dar. Im Gegensatz dazu steht der primitive Datentyp, bei dem der Wert aus allen Stellen gemeinsam gebildet wird.''
Der Syntax entspricht dem struct-Syntax, mit der Ergänzung, dass hinter den Strukturelementen noch die Bitbreite getrennt durch ein Doppelpunkt angegeben wird:
<syntaxhighlight lang="C">
struct time {
unsigned int hour: 5; //0..23 Bits 0..4
unsigned int minute: 6; //0..59 Bits 5..10
Unsigend int second: 6; //0..59 Bits 11..16
} myTime;
</syntaxhighlight>
Als mögliche Datentypen für die Strukturelemente stehen nur die Ganzzahldatentypen <code>int</code>, <code>short</code>, <code>long</code> , <code>long long</code> und <code>char</code> zur Verfügung. Der Datentyp eines Strukturelementes muss mindestens die Anzahl der Bits enthalten, wie diese über die Bitbreite gefordert wird.
Von den Strukturelementen kann keine Adresse bestimmt werden! Auch der <code>offsetf</code> - Operator schlägt fehl.
Der Datentyp entspricht im Wesentlichen einem Ganzzahlzahldatentyp, so dass bei Zugriff auf eine Variable dieses Datentyps eine Ganzzahl gelesen/geschrieben wird. Bei Zugriff auf die einzelnen Strukturelemente werden die entsprechenden Bits dieser Ganzzahlvariablen maskiert, so dass nur die betroffenen Bits geändert werden:
<syntaxhighlight lang="C">
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) | (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) | ((second&0b00001111)<<2);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
//Nachweis am besen über den Maschinensprachevergleich!
int main(int argc,char *argv[]) {
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) {{!}} (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) {{!}} ((second&0b00001111)<<2);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
h=c
}} Öffnen im Compiler Explorer] }}
=== Anwendung===
* Komprimierte Speicherung der Uhrzeit (wie dies z.B. in Realtimeclocks erfolgt)
:<syntaxhighlight lang="C">
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
int main(int argc,char *argv[]) {
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Aufteilung von FloatingPoint Zahlen in seine Komponenten
:<syntaxhighlight lang="C">
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
int main(int argc,char *argv[]) {
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",
(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Bitfelder existieren mit den bekannten Ergänzungen auch in C++.
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
t2n4zaixny72yxoh0cr4ho9muc8jrjx
1090841
1090840
2026-09-15T07:35:51Z
D. Justen
102048
Formatierung geändert
1090841
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C kennt nachfolgende grundlegende Datentypen und Zeiger auf diese Datentypen (siehe auch [[Programmieren in C/C++: Grundlagen# Grundlegende Datentypen und Typsicherheit| Grundlagen:Grundlegende Datentypen und Typsicherheit]])
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| [[#Ganzzahl Datentypen|Ganzzahl]] ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| [[#Gleitkomma Datentypen|Gleitkommazahl]] ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Array|Arrays]] ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| [[#Struktur/Verbundtyp|Strukturen]]/[[#Union|Unions]] ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| [[#Enum/Aufzählungstyp|Aufzählungstyp]] ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Grundlagen #Boolescher-Datentype/Operatoren|Boolescher Datentyp]] ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| [[#Komplexe Zahlen|Komplexe Zahlen]] ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
Bis auf die Datentypen Funktionen, Array und die Zeiger sollen die wesentlichen Aspekte dieser Datentypen im nachfolgenden beschrieben werden.
'''Der grundlegende Datentyp ist <code>int</code>!'''
* Es wird mit nichts Kleinerem gerechnet als mit dem Datentyp <code>int</code> (siehe [[#Implizite Typumwandlung | Implizite Typumwandlung]]) :
:<syntaxhighlight lang="C">
char var1=10,var2=20,var3;
var3=var1+var2; //Addition findet auf Basis des Datentyps int statt
</syntaxhighlight>
* Es gibt zwar den Booleschen Datentyp, dieser entspricht jedoch einem Ganzzahldatentyp und <code>true</code> und <code>false</code> entsprechen den Integerwerten 0 und 1
* Der Aufzählungsdatentyp und seine Aufzählungselemente sind vom Datentyp <code>int</code>
* Bis einschl. C90 wurde bei der Definition von Variablen ohne Angabe des Datentyps, bei Definition einer Funktion ohne Angabe des Datentyps der Übergabeparameter, des Rückgabedatentyps der Datentyp implizit auf int gesetzt ('''implizit int''')
:<syntaxhighlight lang="C">
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}int main(int argc,char *argv[]) {
printf("%d",foo(1,var2));
return 0;
} | execCompilerOptions=-Wall -std=c90|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Ganzzahl Datentypen ==
Grundlegend kennt die Programmiersprache C nur zwei Ganzzahldatentypen:
* Datentyp: <code>int</code>
: Vorzeichenbehafteter (signed) Datentyp, dessen Bitbreite von der Rechnerarchitektur und des Compilers abhängig ist
* Datentyp <code>char</code>
: Datentyp mit einer Mindestbreite von 8-Bit u.A. zur Speicherung von Zeichen typischerweise im ASCII Format. Die C-Spezifikation [C11 6.2.5 Types] lässt es dem Compiler frei, ob <code>char</code> als vorzeichenbehafteter oder vorzeichenloser Datentyp implementiert wird.
: Ergänzend kann der Datentyp <code>char</code> auch zur Speicherung von ganzen Zahlen genutzt werden. In diesem Fall empfiehlt sich, diese explizit als <code>signed</code> und <code>unsiged</code> zu definieren. Wenn nur ASCII Zeichen gespeichert werden, so ist diese Angabe nicht nötig!
Optional können Qualifier dem Datentyp vorangestellt werden:
* <code>unsigned</code> / <code>signed</code> zur Angabe, ob der Inhalt als vorzeichenlose Zahl oder als vorzeichenbehaftete Zahl zu interpretieren ist. Ohne Angabe sind Variablen vom Datentyp <code>int</code> vorzeichenbehaftet
* <code>short</code> / <code>long</code> / <code>long long</code> (letzteres seit C99) als vorangestellten Qualifier zu <code>int</code> zur Vergrößerung/Verkleinerung der Bitbreite. Bei Angabe des Qualifiers ist das Schlüsselwort <code>int</code> optional. Die Beschreibung <code>long long int</code> und <code>long long</code> sind gleichbedeutend!
Als Bitbreite für die Datentypen ist im C-Standard nur ein Mindestbreite definiert. Die genaue Bitbreite hängt von der Rechenbreite des Systems und vom Compiler ab (siehe [C11 6.2.5 Types]):
{| class="wikitable"
|-
! Datentype !! Mindest<br />breite !! Typisch bei 32-Bit<br />Architektur !! Typisch bei 64-Bit<br />Architektur !! printf Format<br />Anweisung
|-
| <code>char</code> || 8 || 8 || 8 || <code>%c</code>
|-
| <code>signed char</code><br /><code>unsigned char</code>|| 8 || 8 || 8 || <code>%hhd</code><br /><code>%hhu</code>
|-
| <code>short</code><br /><code>short int</code>|| 16 || 16 || 16 || <code>%hd</code> / <code>%hu</code>
|-
|<code>int</code>|| 16 || 16/32 || 32 || <code>%d</code> / <code>%u</code>
|-
|<code>long</code><br /><code>long int</code>|| 32 || 32 || 32/64 || <code>%ld</code> / <code>%lu</code>
|-
|<code>long long</code><br /><code>long long int</code>|| 64 || 64 || 64 || <code>%lld</code> / <code>%llu</code>
|}
In der Header-Datei <code>limits.h</code> sind die tatsächlichen Grenzwerte der Datentypen gespeichert:
{| class="wikitable"
|-
! Konstante !! Beschreibung !! Typ. bei 64-Bit Architektur
|-
| <code>CHAR_BIT</code> || Anzahl der Bits in einem Char || 8
|-
| <code>SCHAR_MIN</code> || min. Wert, den der Typ bei signed char aufnehmen kann || -128
|-
| <code>SCHAR_MAX</code> || max. Wert, den der Typ bei signed char aufnehmen kann || 127
|-
| <code>UCHAR_MAX</code> || max. Wert, den der Typ bei unsigned char aufnehmen kann || 255
|-
| <code>CHAR_MIN</code> || min. Wert, den der Typ char aufnehmen kann || 0 oder SCHAR_MIN
|-
| <code>CHAR_MAX</code> || max. Wert, den der Typ char aufnehmen kann || SCHAR_MAX oder UCHAR_MAX
|-
| <code>SHRT_MIN</code> || min. Wert, den der Typ short int annehmen kann || -32.768
|-
| <code>SHRT_MAX</code> || max. Wert, den der Typ short int annehmen kann || 32.767
|-
| <code>USHRT_MAX</code> || max. Wert, den der Typ unsigned short int annehmen kann || 65.535
|-
| <code>INT_MIN</code> || min. Wert, den der Typ int annehmen kann || -2.147.483.648
|-
| <code>INT_MAX</code> || max. Wert, den der Typ int annehmen kann || 2.147.483.647
|-
| <code>UINT_MAX</code> || max. Wert, den der Typ unsigned int aufnehmen kann || 4.294.967.296
|-
| <code>LONG_MIN</code> || min. Wert, den der Typ long int annehmen kann || -2.147.483.648 oder<br />-9.223.372.036.854.775.808
|-
| <code>LONG_MAX</code> || max. Wert, den der Typ long int annehmen kann || 2.147.483.647 oder<br />9.223.372.036.854.775.807
|-
| <code>ULONG_MAX</code> || max. Wert, den der Typ unsigned long int annehmen kann || 4.294.967.296 oder<br />18.446.744.073.709.551.616
|-
| <code>LLONG_MIN</code> || min. Wert, den der Typ long long int annehmen kann || -9.223.372.036.854.775.808
|-
| <code>LLONG_MAX</code> || max. Wert, den der Typ long long int annehmen kann || 9.223.372.036.854.775.807
|-
| <code>ULLONG_MAX</code> || max. Wert, den der Typ unsigned long long int annehmen kann || 18.446.744.073.709.551.615
|}
Aufgrund dessen, dass die Breite der Datentypen von der Rechnerarchitektur und vom Compiler abhängig ist, sind in der Header-Datei <code>stdint.h</code> Aliase für Datentypen enthalten, welche in ihrem Alias die tatsächliche Breite und das Vorzeichens beinhalten:
<syntaxhighlight lang="C">
uint8_t --> unsigned 8-Bit
int8_t --> signed 8-Bit
uint16_t --> unsigned 16-Bit
int16_t --> signed 16-Bit
...
</syntaxhighlight>
Für C++ sehen diese Datentypen wie folgt aus:
<syntaxhighlight lang="C++">
std::intptr_t
std::int8_t std::uint8_t
std::int16_t std::uint16_t
std::int32_t std::uint32_t
Std::int64_t std::uint64_t
</syntaxhighlight>
Zur Erzeugung von portablen/rechnerunabhängigen Programmen empfiehlt sich, diese Datentypen zu nutzen. Die Rechenbreite ist dann unabhängig vom Compiler und Betriebssystem.
== Gleitkomma Datentypen ==
Gleitkommazahlen werden im Computer auf Basis folgender Schreibweise dargestellt (siehe auch: {{w|Gleitkommazahl}}):<br />
<syntaxhighlight lang="C">
Dezimalsystem Dualsystem
12,3456710 = 1234567 * 10^-5 0,110 = 1,1001100110011 * 2^-4
------- -- --------------- --
Mantisse Exponent Mantisse Exponent
</syntaxhighlight>
;Mantisse: Vorzeichenlose ganze Zahl (ggf. mit einer festen Position des Dezimalpunktes=Festkommazahl)
;Exponent: Vorzeichenbehaftete ganze Zahl, welche um einen Bias verschoben ist
;Vorzeichen: Vorzeichen der (vorzeichenlosen) Mantisse
Zur Speicherung im Computer werden das Vorzeichen, die Mantisse und der Exponent getrennt im Binärformat gespeichert, für den Programmierer aber als eine (zusammenhängende) Zahl dargestellt:
[[File:Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse.png|thumb|400px|center|Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse]]
Gleitkommazahlen haben genauso wie ganze Zahlen einen beschränkten Wertebereich:
* Die Anzahl der Bits der Mantisse bestimmen die Anzahl der Nachkommastellen:
:<syntaxhighlight lang="C">
Bei 23-Bit Mantisse ist die max. Zahl 2^-23-1=0,000000119,
welches 6..7 dezimale Stellen entspricht!
</syntaxhighlight>
* Mit dem Exponent kann 'quasi' der kleinste und der größte Wertebereich angegeben werden:
:<syntaxhighlight lang="C">
Bei 8-Bit Exponent mit einem Bias von 127 liegt der Wertebereich des
Exponenten im Bereich von -126 … +127 (Exponent -127 und +127 wird zur
Darstellung weitere Zahlen benötigt).
Die kleinste darstellbare Zahl (unter Vernachlässigung der Nachkommastellen der Mantisse ist:
2^-126=1/2^126≅1,175*10^-38
Die größte darstellbare Zahl ist:
2^127 ≅1,7*10^38
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
float sqrtf(float);
float powf(float,float);
#include <ieee754.h>
#include <complex.h>
union test {
unsigned int i;
float f;
union ieee754_float b;
};
int main(int argc,char *argv[]) {
union test var = {.f=-0.1};
printf("Float=%f Binär=%032b\n",var.f,var.i);
printf("v=0b%b e=0b%08b m=0b(1).%023b\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%10d m=%29d\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%d-%d=%d m=1+%d/2^-23=%f\n",var.b.ieee.negative,
var.b.ieee.exponent,IEEE754_FLOAT_BIAS,var.b.ieee.exponent-IEEE754_FLOAT_BIAS,
var.b.ieee.mantissa,1.0+var.b.ieee.mantissa*1.0/(1<<23));
printf("\n--- Beispiele von Genauigkeitsprobleme im Umgang mit Gleitkommazahlen (hier float) ----\n");
printf("powf(sqrtf(%1.8f),2) = %1.8f\n",2.0f,powf(sqrtf(2.0f),2));
printf("%f + %f = %f\n",2000.0,0.0004,(double)(2000.0f+0.0004f));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Grundlegend kennen die Programmiersprachen C/C++ folgende Gleitkommadatentypen:
* Datentyp: <code>float</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindesten 6 Stellen betragen, so dass der Datentyp typischerweise 32-Bit groß ist
* Datentyp: <code>double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, so dass der Datentyp typischweise 64-Bit Große ist
* Datentyp: <code>long double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, damit könnte dieser Datentyp gleich dem Datentyp <code>double</code> gesetzt werden. In der Tat ist die Datenbreite Rechner- und Compilerabhängig. Einige Compiler setzen diesen Datentyp identisch zu <code>double</code>, bei x86 Prozessoren wird aufgrund der Hardwareunterstützung 80-Bit genutzt (wobei in der Tat der Datentyp dann 16-Byte Speicherplatz beansprucht) und einige Systeme nutzen 128-Bit (wobei hier aufgrund ggf. fehlender Hardwareunterstützung Operationen mit diesem Datentyp per Software emuliert werden) (siehe Wikipedia Artikel {{w|lang=en|Long_double|long double}}).
Die genaue Darstellung (Anzahl der Bits für Mantisse und Exponent, Darstellung von NAN/INF, ….) ist in C nicht spezifiziert und somit compiler- und rechnerabhängig. Zumeist wird mittlerweile die {{w|IEEE 754}} Standardisierung genutzt (Norm wurde von Intel mit der Entwicklung der 8087 FPU entworfen).
Grunddatentypen und der Wertebereich (nach {{w|IEEE 754}})
{| class="wikitable"
|-
! Daten-<br/>type !! Speicher-<br />platz !! Exponent !! Mantisse !! Größte Zahl !! Kleinste Zahl !! Genauigkeit !! printf Format Anweisung
|-
| binary32→<code>float</code> || 4 Byte || 8 bit || 23 bit || ~3,4*10<sup>38</sup> || ~1,2*10<sup>-38</sup> || 7..8 Stellen || ---
|-
| binary64→<code>double</code> || 8 Byte || 11 bit || 52 bit || ~1,8*10<sup>308</sup> || ~2,2*10<sup>-308</sup> || 15..16 Stellen || %f %e %g
|-
| binary64 extended→<code>long double</code> || ≥10 Byte || ≥15 bit || ≥63 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 19..20 Stellen || %Lf %Le %Lg
|-
| binary128→<code>long double</code> || 16 Byte || 15 bit || 112 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 34 Stellen || %Lf %Le %Lg
|}
Die tatsächliche Auflösung der Datentyps kann auf Basis nachfolgender Konstanten, definiert in der Header-Datei <code>float.h</code>, ermittelt werden:
:<syntaxhighlight lang="C">
FLT_DIG --> Anzahl der dezimalen Nachkommastellen für float
DBL_DIG --> Anzahl der dezimalen Nachkommastellen für double
LDBL_DIG --> Anzahl der dezimalen Nachkommastellen für long double
FLT_MIN_10_EXP --> Minimaler Exponent zur Basis 10
DBL_MIN_10_EXP
LDBL_MIN_10_EXP
FLT_MAX_10_EXP --> Maximaler Exponent zur Basis 10
DBL_MAX_10_EXP
LDBL_MAX_10_EXP
LDBL_MANT_DIG --> Anzahl der Bits für die Mantisse
LDBL_MANT_DIG
LDBL_MANT_DIG
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <float.h>
int main(){
printf("FLT_DIG =%u\n",FLT_DIG);
printf("DBL_DIG =%u\n",DBL_DIG);
printf("LDBL_DIG =%u\n",LDBL_DIG);
printf("FLT_MIN_10_EXP =%d\n",FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP =%d\n",DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP=%d\n",LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP =%d\n",FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP =%d\n",DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP=%d\n",LDBL_MAX_10_EXP);
printf("FLT_MANT_DIG =%d\n",FLT_MANT_DIG);
printf("DBL_MANT_DIG =%d\n",DBL_MANT_DIG);
printf("LDBL_MANT_DIG =%d\n",LDBL_MANT_DIG);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Aufgrund des nicht standardisierten Formates sollte ein Gleitkommadatentyp nicht im Binärformat für den Datenaustausch (mit Netzwerk, über Dateien, ..) genutzt werden. Andere Rechnersysteme/Programmiersprachen würde aufgrund der anderen Interpretation andere Zahlenwerte aus den übertragenen/gespeicherten Binärdaten auslesen!
<syntaxhighlight lang="C">
float var1;
write(file_hdl,&var1,sizeof var1); //Schreiben des Binärwertes
//in eine Datei
double var2;
send(socket_hdl,&var2,sizeof var2,0);//Senden des Binärwertes
//über ein Netzwerk
</syntaxhighlight>
Die Standard-C-Library bietet einige mathematische Funktionen wie <code>sin() / cos() / tan() / atan2() / sqrt() / pow() / exp()/…</code> an. Die Prototypen dieser Funktion sind in der Header-Datei <code>math.h</code> beschrieben, so dass diese bei Nutzung dieser Funktion zu inkludieren ist. Ergänzend ist die Shared Library libm.so über den Compilerschalter '-lm' einzubinden:
<syntaxhighlight lang="C">
#include <math.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
double sqrt(double);
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
printf("var1=%f var2=%f\n",var1,var2);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen basieren auf den Datentyp <code>double</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist vom Datentyp <code>double</code>. Die Prototypen sehen wie folgt aus:
<syntaxhighlight lang="C">
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double); //Wertebereich der Rückgabe von -PI/2..+PI/2
double atan2(double,double); //Wertebereich der Rückgabe von -Pi .. +PI
double sqrt(double);
double log(double);
</syntaxhighlight>
Über den Suffix f oder l im Funktionsnamen kann der zugrundeliegende Datentyp auf float (Suffix f) oder long double (Suffix l) geändert werden:
<syntaxhighlight lang="C">
float sinf(float);
long double sinl(long double);
</syntaxhighlight>
Ergänzend zu den Prototypen sind die gebräuchlichen Naturkonstanten in <code>math.h</code> definiert (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
M_E Value of e
M_LOG2E Value of log_2 e
M_LOG10E Value of log_10 e
M_LN2 Value of log_e 2
M_LN10 Value of log_e 10
M_PI Value of π
M_PI_2 Value of π/2
M_PI_4 Value of π/4
M_1_PI Value of 1/π
M_2_PI Value of 2/π
M_2_SQRTPI Value of 2/√π
M_SQRT2 Value of √2
M_SQRT1_2 Value of 1/√2
</syntaxhighlight>
Gleitkommazahlen können nicht nur Zahlenwerte, sondern auch Sonderwerte annehmen. Diese Sonderwerte sind ebenfalls in <code>math.h</code> beschrieben (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
INFINITY A constant expression of type float representing
positive or unsigned infinity, if available; else a
positive constant of type float that overflows at
translation time.
NAN A constant expression of type float representing a
quiet NaN. This macro is only defined if the
implementation supports quiet NaNs for the float type.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <math.h>
//Quelle: https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c
#ifdef NAN
#define NAN_STR "NAN is supported"
#else
#define NAN_STR "NAN is not supported"
#endif
#ifdef INFINITY
#define INFINITY_STR "INFINITY is supported"
#else
#define INFINITY_STR "INFINITY is not supported"
#endif
int main(int argc, char *argv[argc]) {
printf("%s\n%s\n",NAN_STR,INFINITY_STR);
double x=0.0;
double y=1/x;
printf("1/%e -> %e\n",x,y);
if(y==INFINITY)
printf("1) Initinity\n");
if(isinf(y)) //besser
printf("2) Initinity\n");
printf("%llx\n%llx\n\n",*(long long *)&y,INFINITY);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
double z=-(x/x);
printf("%e/%e -> %e\n",x,x,z);
if(z == NAN) //funktioniert nicht
printf("1) Not a Number\n");
if(isnan(z)) //besser
printf("2) Not a Number\n");
if(z != z)
printf("3) Not a Number\n");
printf("%llx\n%llx",*(long long *)&z,NAN);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
return 0;
} | execCompilerOptions=-lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit <code>fesetround()/fegetround()</code> kann gesetzt/gelesen werden, wie mit Ergebnissen umzugehen sind, die nicht exakt darstellbar sind. Mögliche Werte sind 'round to nearest' (default), 'round up', 'round down' und 'round toward zero'.
== Komplexe Zahlen ==
Nach dem Wikipedia Artikel {{w|komplexe Zahlen}} ''stellen komplexe Zahlen eine Erweiterung der reellen Zahlen dar. Ziel der Erweiterung ist es, algebraische Gleichungen wie x<sup>2</sup>+1=0 bzw. x<sup>2</sup>=-1 lösbar zu machen. ... Da die Quadrate aller reellen Zahlen größer oder gleich 0 sind, kann die Lösung der Gleichung x<sup>2</sup>=-1 keine reelle Zahl sein. Man braucht eine ganz neue Zahl, die man üblicherweise i nennt, mit der Eigenschaft i<sup>2</sup>=-1. Diese Zahl i wird als imaginäre Einheit bezeichnet.
Komplexe Zahlen werden nun als Summe a+b*i definiert, wobei a und b reelle Zahlen sind und i die oben definierte imaginäre Einheit ist.''<br />
Der Datentyp für komplexe Zahlen (erst ab C99 enthalten) beinhaltet folglich zwei Gleitkommazahlen, eine für den reelen Teil und eine für den imaginären Teil. Entsprechend den Gleitkommazahlen steht der komplexe Datentyp ebenfalls in drei unterschiedlichen Genauigkeiten zur Verfügung:
{| class="wikitable"
|-
! Datentype !! Speicherplatz
|-
| <code>float _Complex</code> || 2x4Byte
|-
| <code>double _Complex</code><br /><code>_Complex</code> || 2x8Byte
|-
| <code>long double _Complex</code> || 2x10Byte
|}
Wie auch beim Booleschen Datentyp ist in der Header-Datei <code>complex.h</code> für den einfacheren Umgang mit diesem Datentyp das Makro <code>complex</code> als Textersetzung für <code>_Complex</code> gesetzt.
Zur Darstellung von komplexen Konstanten wurde die Gleitkommakonstante um den Suffix i ergänzt. Durch Anhängen von i wird aus dem ansonsten rellen Teil der imaginäre Teil und damit aus der Gleitkommakonstante eine komplexe Gleitkommakonstante:
<syntaxhighlight lang="C">
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Normale Gleitkommavariablen werden als reellen Teil einer komplexen Zahl angesehen. Bei Operationen von Gleitkommazahlen und komplexen Zahlen wird der imaginäre Teil der Gleitkommazahl auf 0 gesetzt. Beim Zuweisen einer komplexen Zahl an eine Gleitkommazahl wird nur der reele Teil 'gelesen'.<br />
Soll eine Gleitkommavariablen zu einem imaginären Teil gewandelt werden, so muss diese bspw mit der Konstanten 1.0i multipliziert werden:
<syntaxhighlight lang="C">
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C-Library bietet diverse mathematische Funktionen wie csin(), ccos(), csqrt(), cpow() und ergänzend Umrechnungsfunktionen von Gleitkommazahlen in komplexe Zahlen (und umgedreht) wie creal(),cimag() ,cabs() für den Umgang mit komplexen Zahlen an:
<syntaxhighlight lang="C">
double _Complex csin(double _Complex);
double _Complex csqrt(double _Complex);
double creal(double _Complex);
double cimag(double _Complex);
</syntaxhighlight>
Zur Nutzung dieser Funktionen muss die Header-Datei <code>complex.h</code> inkludiert und ergänzend die Shared Library libm.so über den Compilerschalter '-lm' eingebunden werden.
<syntaxhighlight lang="C">
#include <complex.h>
//Math-Library mittels Linker-Command '-lm' einbinden
int main(int argc, char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen beruhen auf den Datentyp <code>double _Complex</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist <code>double _Complex</code> resp. <code>double</code> (bei den Umrechnungsfunktionen). Über den Suffix f und l im Funktionsnamen kann der zugrundeliegende Datentyp geändert werden:
<syntaxhighlight lang="C">
float crealf(float _Complex z);
long double creall(long double _Complex z);
</syntaxhighlight>
Hinweis:
* Der Datentyp <code>_Complex</code> und die dazugehörigen mathematischen Funktionen sind in der C-Spezifikation als optional gekennzeichnet.
== Generische mathematische Funktionen ==
In der <code>tgmath.h</code> Header Datei sind für die mathematischen Funktionen Makros enthalten, welche den Datentyp der Übergabeparameter bestimmen und basierend auf den Datentyp die dazugehörige mathematische Funktion aufrufen.
<code>tgmath.h</code> selbst inkludiert <code>math.h</code> und <code>complex.h</code>, so dass diese nicht weiter zu inkludieren sind.
Steht für den Übergabedatentyp keine passende Funktion zu Verfügung, so ist das Verhalten des Makros undefiniert (bspw. wenn ein komplexes Argument an eine Funktion übergeben wird, die nur für Gleitkommazahlen ausgelegt ist <code>ceil(1+2i);</code> )
Folgendes Regelwerk wird angewendet:
* Ist einer der Übergabeparameter imaginär, so ist die ausgewählte Funktion in der Spezifikation der Funktion beschrieben
* Ist einer der Übergabeparameter Komplexe, so wird die Komplexe Variante der Funktion aufgerufen, andernfalls die Gleitkomma Variante
* Ist einer der Übergabeparameter vom Datentyp <code>long double</code>, so wird die <code>long double</code> Variante, bei integer und double die <code>double</code> Variante und andernfalls die <code>float</code> Variante aufgerufen
Beispiel:
<syntaxhighlight lang="C">
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
int main(int argc,char *argv[]) {
foo(1l+1li,2.0l,3.0f,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=c
}} Öffnen im Compiler Explorer] }}
== Boolschescher Datentyp ==
Siehe [[Programmieren in C/C++: Grundlagen#Boolescher-Datentype/Operatoren|Grundlagen: Boolescher-Datentype/Operatoren]]
== void / unvollständiger Datentype ==
Der Datentyp <code>void</code> dient vorrangig dazu, nicht vorhandene Über- und Rückgabewerte von Funktionen anzuzeigen. Eine Variable vom Datentyp <code>void</code> kann nicht angelegt werden. Ein Zeiger vom Datentyp <code>void</code> ist möglich, kann aber nicht dereferenziert werden (siehe Kap. [[Programmieren in C/C++: Zeiger #Void-Zeiger| Zeiger:Void-Zeiger]])
<syntaxhighlight lang="C">
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* <code>sizeof(void)</code> ist nach der C-Spezifikation nicht erlaubt. Dennoch geben viele Compiler hier den Wert 1 zurück!
* Mit einem expliziten Cast auf den Datentyp void wird dem Compiler mitgeteilt, dass diese Variable in Gebrauch ist, der Wert in dieser Operation aber nicht genutzt wird. Hierüber kann die Compilerwarning 'unused Variable' unterbunden werden:
:<syntaxhighlight lang="C">
void func(int par1, int par2) {
int var1=12;
int var2=13;
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int par1, int par2) {
int var1=12;
int var2=13;
int var3=14; //Nicht genutzte Variable
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
printf("Genutzt\n");
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Datentypkonvertierung ==
Für das Rechnen/Vergleichen müssen beide Operatoren vom identischen Datentyp sein! Sind diese nicht identisch, so müssen die Datentypen 'angeglichen' werden. Dies kann einerseits ‚automatisch‘ mittels 'implizierter' Typumwandlung oder ‚manuell‘ mittels ‚expliziter' Typumwandlung erfolgen.<br />
Beim Zuweisungsoperator (inkl. Parameterzuweisung bei Funktionsaufrufen und Funktionsrückgabewerte mittels return) gilt dies ebenso, nur dass hier der Quelldatentyp an den Zieldatentyp angepasst werden muss. Die impliziten Regeln finden hier keine Anwendung.
Hinweis:
* Empfehlenswert ist, die Datentypen der Variablen so zu wählen, dass der Compiler keine implizite Typumwandlung tätigt. Kann dies nicht vermieden werden, so sollte die explizite Typumwandlung genutzt werden (um sich einen möglichen Datenverlust bewusst zu machen)
* Der Datentyp selbst sollte den möglichen Wertebereich der Variablen entsprechen und nicht unnötig groß gewählt werden
:<syntaxhighlight lang="C">
Datentyp zur Speicherung der Stundenzeit:
Wertebereich: 0 ... 23 -> unsigned char
Datentyp zur Speicherung einer Jahreszahl:
Wertebereich: 2000 v.C. ... 4000 n.C -> signed short
Datentyp zur Speicherung einer Temperatur:
Wertebreich: -273,0°C ... 2000,0°C -> float
</syntaxhighlight>
=== Implizite Typumwandlung ===
Diese Regeln wurden so aufgestellt, dass dabei stets ein Datentyp in einen anderen Datentyp mit höherem Wertigkeit umgewandelt wird [C11 6.3.1.8] und [Harbison: S 199]. Bei Ganzzahlen gilt ergänzend folgende (Rangordnung [C11 6.3.1.1]: long long, long, int, short,char,_Bool):
{| class="wikitable"
|-
! Regel/<br />Priorität !! If either operand<br />has Type !! And the other operand<br />has Type !! Converts both to
|-
| 1 (hoch) || long double || any real type || long double
|-
| 2 || double || any real type || double
|-
| 3 || float || any real type || float
|-
| 4 || any unsigned type || any unsigned type || the unsigned type<br/>with the greater rank
|-
| 5 || any signed type || any signed type || the signed type<br/>with the greater rank
|-
| 6 || any unsigned type || a signed type with a equal<br/> or less rank || the unsigned type
|-
| 7 || any unsigned type || a signed type that can represent<br/>all of values of the unsigned type || the signed type
|-
| 8 (niedrig) || any other type || any other type || both operands are<br/> converted to the unsigned <br/>integer type corresponding<br/> to the type of the operand<br/> with the signed<br/> integer type
|}
Ergänzend gilt das Regelwerk zu Integer Promotion, welche Datentypen kleiner als <code>signed int</code> zu <code>int</code> und kleiner als <code>unsigned int</code> zu <code>unsigned int</code> konvertiert (Compiler kann hiervon abweichen, wenn sichergestellt ist, dass kein Datenverlust eintritt).
Regel 6 und 7 sind der nicht klar definierten Bitbreite der ganzzahligen Datentypen geschuldet und versuchen, Konvertierungsverluste zu vermeiden. Sie lesen sich zunächst kryptisch, lassen sich aber einfach am folgenden Beispiel erklären:
<syntaxhighlight lang="C">
Operand 1: unsigned int (hier 32-Bit)
Operand 2: long (hier 32-Bit / 64-Bit)
</syntaxhighlight>
* Im Fall, dass der Datentyp <code>long</code> 64-Bit breit ist, kann dieser problemlos die vorzeichenlose 32-Bit Zahl ohne Konvertierungsverluste repräsentieren, so dass der Zieltype <code>signed long</code> ist (Regel 7)
* Im Fall, dass der Datentyp <code>long</code> 32-Bit breit ist, kann dieser mit seinen Wertebereich von -2.147.483.648 bis +2.147.483.647 nicht den vorzeichenlosen Zahlenbereich von 0…4.294.967.295 darstellen. In diesem Fall hat der unsigned Datentyp einen höheren Rang, so dass als Zieltyp <code>unsigend long</code> gewählt wird (Regel 6)
'''Regel 6 bedeutet die Gefahr eines Konvertierungsverlustes, dessen man sich bewusst sein sollte!''' Diese tritt insb. dann in Kraft, wenn ein Operand vom Typ <code>unsigned long long</code> ist (64-Bit).
Beispiele von impliziten Typumwandlungen:
<syntaxhighlight lang="C">
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
vari=5.0*(int)sin(vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ Wikibooks Formatierung schlägt hier fehlt
double sin(double);
int main(int argc,char *argv[]) {
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
printf("vars=%hd\n",vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
printf("vars=%hd\n",vars);
vari=5.0*(int)sin(vars);
printf("vari=%d\n",vari);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
printf("vari=%d\n",vari);
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im CompilerExplorer können sie sich die impliziten Typumwandlungen anzeigen lassen. Dazu gehen sie bitte wie folgt vor:
:* Im Source-Fenster mit '+Add new' ein Compiler Fenster öffnen
:* Im Compiler-Fenster mit '+Add new' ein 'GCC Tree/RTL' Fenster öffnen
:* Im GCC Tree/RTL-Fenster unter 'Select a pass…' 'original tree' auswählen
Um implizite Typumwandlung besser erkennen zu können, wird oftmals bei Variablennamen die ''' 'Ungarische Notation' ''' angewendet (siehe {{w|Ungarische Notation}}). Aufgrund der besonderen Namensgebung kann der Programmierer ohne großen Aufwand frühzeitig mögliche Typkonflikte erkennen. Der Variablenname setzt sich wie folgt zusammen:
<syntaxhighlight lang="C">
{Präfix}{Datentyp}{Bezeichner}
</syntaxhighlight>
:'''Präfix''': p->Pointer h->Handle i->index c->count f->flag rg->Array
:'''Datentyp''': ch->Character st->string w->word b->byte…
:'''Bezeichner''': Zum Binden der Variable an eine konkrete Aufgabe (keine Unterstriche).
:Bezeichner ist optional, wenn aus Präfix und Datentyp die 'Aufgabe' der Variable direkt sichtbar ist
Beispiele:
<syntaxhighlight lang="C">
char rgchtemp[10]; //Array (Range) vom Datentyp character
int ich; //Index zum Adressieren eines Arrays vom Datentyp
//character
</syntaxhighlight>
=== Explizite Typumwandlung ===
Programmierer erzwingt durch explizite Typumwandlung (auch CASTen genannt) eine Umwandlung eines Datentyps in einen anderen. Dazu wird der Zieldatentyp in runden Klammern vor Quelldatentype geschrieben:
<syntaxhighlight lang="C">
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
In der Rangfolge der Operatoren steht der Cast-Operator unterhalb von bspw. Funktionsaufrufen, Arrayzugriffen aber auch der Dereferenzierung:
{| class="wikitable"
|-
! Priorität !! Symbol !! Assoziativität !! Bedeutung
|-
| 15 || ... || ... || ...
|-
| 14
||
++/-- (Präfix)<br />
+/- (Vorzeichen) <br />
<nowiki>!</nowiki>/~ <br />
&<br />
<nowiki>*</nowiki><br />
(TYP)<br />
...
|| R-L
||
Präfix-Inkrement/Dekrement<br />
Vorzeichen<br />
Logisches/Bitweises Nicht<br />
Adresse<br />
Zeigerdereferenzierung<br />
'''Typumwandlung (Explizites Cast)'''<br />
...
|-
| 13
||
* / %
|| L-R
|| Multiplikation/Division/Modulo
|-
| 12 || ... || ... || ...
|}
Im Zweifel gilt auch hier, den zu wandelnden Typ ergänzend zu klammern.
Hinweis:
* Bedenke, dass die explizite Typumwandlung so aufgestellt sein sollte, dass der Zieldatentyp dem notwendigen Datentyp entspricht. Andernfalls wendet der Compiler ergänzend eine implizierte Typumwandlung an:
:<syntaxhighlight lang="C">
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Mittels expliziter Typumwandlung können Ganzzahl nach Gleitkommazahlen (und andersherum) und Zeiger in einen anderen Zeiger und auf andere Datentypen gewandelt werden. Eine Konvertierung von Arrays, Strukturen, Unions zu anderen Datentypen als sich selbst ist weiterhin nicht möglich:
<syntaxhighlight lang="C">
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei den möglichen Konvertierungen sollte Folgendes berücksichtigt werden:
* '''Vorzeichenlose Ganzzahl''' → '''Vorzeichenlose Ganzzahl''': Wenn der Zieldatentyp größer ist, wird die Zahl durch führende '0' erweitert. Wenn der Zieldatentyp kleiner ist, werde die zu vielen Bitstellen abgeschnitten/verworfen (ggf. Datenverlust)
* '''Vorzeichenbehaftete Ganzzahl''' → '''Vorzeichenbehaftete Ganzzahl''': Wenn der Zieldatentyp größer ist, wird vorzeichenrichtig erweitertet (d.h. das Auffüllen erfolgt auf Basis des Vorzeichens). Wenn der Zieldatentyp kleiner ist, werden auch hier die zu vielen Bits abgeschnitten/verworfen (Vorsicht: Negative Zahlen können dabei in positive Zahlen gewandelt werden)
* '''Gleitkommazahl''' → '''Gleitkommazahl''': Hier wird vereinfacht ausgedrückt sowohl die Mantisse als auch der Exponent einzeln kopiert. Wenn die Zielmantisse kleiner ist, gehen 'Nachkommastellen' verloren. Wenn der Quellexponent einen größeren Wert beinhaltet, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf Unendlich gesetzt. Umgedreht, wenn der Quellexponent kleiner ist, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf 0 gesetzt
* '''Ganzzahl''' → '''Gleitkommazahl''': Hier wird, vereinfacht ausgedrückt, die Ganzzahl in die Mantisse kopiert. Um Datenverluste zu vermeiden, sollte die Bitbreite der Zielmantisse größer gleich der Bitbreite der Ganzzahl sein
* '''Gleitkommazahl''' → '''Ganzzahl''': Im Wesentlichen wird hier die Mantisse übernommen, so dass hier die Bitbreite des Zieldatentyps mindestens der Bitbreite der Mantisse sein sollte
* '''Zeiger''' ↔ '''Ganzzahl''': Die Konvertierung ist möglich. Da bei 64-Bit Systemen der Zeiger 64-Bit und Integer 32-Bit breit ist, meckert ggf. der Compiler. Für solche Fälle existieren die Datentypen 'intptr_t' und 'uintptr_t', über welche sichergestellt ist, dass ein Zeiger in einen Ganzzahldatentyp gespeichert werden kann!
* '''Zeiger''' ↔ '''Gleitkommazahl''': Diese Konvertierung ist nicht möglich!
* '''Struktur/Union''' ↔ '''Ganzzahl/Gleitkommazahl''': Diese Konvertierung ist nicht möglich. Es können nur einzelnen Strukturelemente konvertiert werden, sofern diese vom Typ Ganzzahl/Gleitkommazahl sind
* '''Array''' ↔ '''Ganzzahl/Gleitkommazahl''': Der Arrayname entspricht einen Zeiger, so dass hier ein Zeiger in eine Ganzzahl oder umgedreht konvertiert wird (siehe Zeiger ↔ Ganzzahl)
In C++ gibt es weitere CAST-Operatoren, auf welche hier derzeit noch nicht weiter eingegangen wird!
* Static_cast (Entspricht dem Expliziten Cast)
* Const_cast
* Dynamic_cast
* Reinterpret_cast
== Verbundtyp Struktur/Klasse (nur C++) ==
Nach dem Wikipedia Artikel {{w|Verbund (Datentyp)}} ist ''ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten können wiederum Verbünde enthalten, wodurch auch komplexe Datenstrukturen definiert werden können.<br />
Für jedes Strukturelement wird Speicher reserviert. Alle Strukturelemente liegen hintereinander im Speicher.''
<code>Syntax: struct Strukturname<sub>Opt</sub> {Datentype Strukturelementname; … }<sub>OPT</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Verbund entspricht einer Java Klasse mit dem Unterschied zu C (nicht C++) , dass ein Verbund keine Methoden beinhaltet und keine Zugriffsbeschränkung für die Attribute gesetzt werden können.
Der Syntax erlaubt es, gleichermaßen einen Datentyp (über Strukturname) zu definieren und Variablen von diesem Datentyp (über Variablenliste) anzulegen. Da beide Elemente optional sind, ergeben sich diverse Kombinationsmöglichkeiten:
* Nur Strukturname → Definition eines neuen Datentyps
:<syntaxhighlight lang="C">
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
var1.y=2;
var1.z=1;
printf("var1.x=%d var1.y=%d var1.z=%d\n",var1.x,var1.y,var1.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C: Der Strukturname ist nur mit dem vorangestellten <code>struct</code> gültig. Der Strukturname stellt somit einen eigenen Namensraum, getrennt von dem Namensraum der Variablen/Funktionen, dar. Daher kann ein Strukturname identisch zu einem Variablennamen sein:
:<syntaxhighlight lang="C">
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
xyz2.x=xyz2.y=xyz2.z=1;
printf("xyz2.x=%d xyz2.y=%d xyz2.z=%d\n",xyz2.x,xyz2.y,xyz2.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C++: Der Strukturname ist sowohl mit als auch ohne dem vorangestellten <code>struct</code> gültig. Auch hier stellt der Strukturname einen eigenen Namensraum dar, der jedoch eine niedrigere Priorität als der der Variablen hat:
:<syntaxhighlight lang="C++">
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz beschreibt hier die Variable
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz3 beschreibt hier die Variable
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
* Nur Variablenliste → Definition einer/mehrerer Variablen von einem 'unnamed' Datentyp
:<syntaxhighlight lang="C">
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Angewendet wird die Schreibweise gerne, wenn eine Struktur innerhalb einer Struktur definiert wird und die innere Struktur zur besseren Strukturierung dient:
:<syntaxhighlight lang="C">
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Strukturname und Variablenliste → Definition eines Datentyps und Definition von Variablen. D.h. es können im Nachhinein weitere Variablen von diesem Datentyp angelegt und die hier angelegten Variablen genutzt werden.
:<syntaxhighlight lang="C">
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y; //Nutzung der Variablen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y=1; //Nutzung der Variablen
(void)var1;
(void)ptr1;
(void)ptr2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Kein Strukturname und keine Variablenliste → "Anonymous Struct", d.h. Definition eines 'unnamed' Datentyps, von der ergänzend keine Variable angelegt wird. Anonymus Structs sind nur innerhalb von Strukturen erlaubt/einsetzbar. Hier dienen sie der besseren Strukturierung und ersparen dem Programmierer die Benennung des normalerweise notwendigen Strukturelementes:
:<syntaxhighlight lang="C">
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
(void)var;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Eine Struktur (und auch eine C++ Klasse) wird mit einem Semikolon abgeschlossen
* Eine alternative Beschreibung zu Strukturen finden sie in [https://abstractexpr.com/2023/06/29/structures-in-c-from-basics-to-memory-alignment/ Structures in C: From Basics to Memory Alignment]
=== Strukturelement ===
Innerhalb der Struktur können beliebige Strukturelemente von beliebigen Datentypen angelegt werden. Einzige Voraussetzung, der Datentyp des anzulegenden Strukturelementes muss zuvor definiert worden sein. Ergänzend kann der neue Datentyp auch in der Struktur selbst definiert werden, sofern mit der Definition des Datentyps auch eine Variable angelegt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zugriff auf Strukturelemente ===
Die Programmiersprachen C/C++ unterscheiden zwei 'Zugriffsarten' auf die Strukturelemente, abhängig vom zugrundeliegenden Datentyp des linken Operanden::
* Handelt es sich beim linken Operanden um eine (struct)Variablen, so erfolgt der Zugriff über den Punkt-Operator <code>.</code>:
:<syntaxhighlight lang="C">
struct {
int a,b,c;
} abc;
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct {
int a,b,c;
} abc;
int main(int argc,char *argv[]) {
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c=12;
printf("abc.a=%d abc.b=%d abc.c=%d\n",abc.a,abc.b,abc.c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Handelt es sich beim linken Operanden um einen Zeiger auf eine (struct)Variable, so erfolgt der Zugriff über den Zeiger-Operator <code>-></code>:
:<syntaxhighlight lang="C">
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
int main(int argc,char *argv[]) {
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Werden innerhalb von Strukturen weitere Strukturen und Zeiger auf Strukturen angelegt, so müssen diese Regeln auf jedes innere Strukturelement einzeln angewendet werden:
<syntaxhighlight lang="C">
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
int main(int argc,char *argv[]) {
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Strukturen ===
Mit dem Anlegen einer Strukturvariablen kann diese auch initialisiert werden. Eine 'Vorbelegung' der Strukturelemente bei der Definition der Struktur ist in C nicht möglich.<br />
Die Initialisierung erfolgt über eine Initialisierungsliste (siehe Kap [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]). Innerhalb der Initialisierungsliste stehen die Initialisierungswerte entweder in der Reihenfolge der Datentypdefinition oder werden explizit mit dem ‘.‘ Operator angesprochen (designated initializers). Werden einzelne Strukturelemente ausgelassen, so werden diese mit 0 initialisiert:
<syntaxhighlight lang="C">
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
int main(int argc,char *argv[]) {
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
printf("v1.a=%d v1.b=%d v1.str[0]=%d\n",v1.a,v1.b,v1.str[0]);
printf("v2.a=%d v2.b=%d v2.str[0]=%d\n",v2.a,v2.b,v2.str[0]);
printf("v3.a=%d v3.b=%d v3.str[0]=%d\n",v3.a,v3.b,v3.str[0]);
printf("v4.a=%d v4.b=%d v4.str[0]=%d\n",v4.a,v4.b,v4.str[0]);
printf("v5.a=%d v5.b=%d v5.str[0]=%d\n",v5.a,v5.b,v5.str[0]);
printf("v6.a=%d v6.b=%d v6.str[0]=%d\n",v6.a,v6.b,v6.str[0]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Initialisierung einer Struktur über nachfolgende Art bewirkt etwas anderes, als erwartet:
<syntaxhighlight lang="C">
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
printf("var.a=%d var.b=%d var.c=%d\n",var.a,var.b,var.c);
//Gerne mal den Compiler Wechseln
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der Initialisierungsliste wird über 'var.b=12' und 'var.c=3' die zu diesem Zeitpunkt noch nicht initialisierte Variable var die Elemente b und c initialisiert. Mit dem Werten der Initialisierungsliste (hier {12,3}) wird nachfolgend die Variable erneut initialisiert und 12 dem Strukturelement a und 3 dem Strukturelement b zugewiesen. Abhängig vom Compiler ist das Strukturelement c entweder 3 oder 0.
Bei verschachtelten Strukturen muss entsprechend obiger Aussage für jede innere Struktur eine eigene Initialisierungsliste erstellt werden. Die inneren Initialisierungslisten können entfallen, was jedoch nicht empfohlen wird und ergänzend vom Compiler bei '-Wall' als Warning angemerkt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8}}
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={{.x=5,.y=6},{7,8}},
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8} }
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={ {.x=5,.y=6},{7,8} },
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
int main(int argc,char *argv[]) {
printf("v1.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v1.a, v1.b, v1.xy.x, v1.xy.y, v1.arr[0].x, v1.arr[0].y, v1.arr[1].x, v1.arr[1].y );
printf("v2.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v2.a, v2.b, v2.xy.x, v2.xy.y, v2.arr[0].x, v2.arr[0].y, v2.arr[1].x, v2.arr[1].y );
printf("v3.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v3.a, v3.b, v3.xy.x, v3.xy.y, v3.arr[0].x, v3.arr[0].y, v3.arr[1].x, v3.arr[1].y );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zuweisen/Kopieren von Strukturen ===
Strukturen werden über den Namen als 'ganzes' angesprochen, so dass eine Zuweisung als 'ganzes' möglich ist. Bei bspw. einer 12-Byte großen Struktur werden bei Nutzung der Variable die gesamten 12-Byte gelesen/geändert!
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1,var2;
var1=var2; //12-Bytes kopiert
//--> entspricht memcpy(&var1,&var2,sizeof(xyz));
</syntaxhighlight>
Die Zuweisung als 'ganzes' gilt auch bei der Parameterübergabe und -rückgabe von Funktionen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;};
//Funktionsdefinition
struct xyz function(struct xyz par) {
return (struct xyz){par.z,par.y,par.x};
}
//Funktionsaufruf
struct xyz var=function((struct xyz){1,2,3});
//Mit dem Aufruf der Funktion werden 12-Bytes in die Variable par kopiert
//Mit dem Ende der Funktion werden 12-Bytes in die Variable var kopiert
</syntaxhighlight>
Bedenke, dass bei großen Strukturen das Kopieren Rechenzeit benötigt und folglich vermieden werden sollte! Alternativ sollten Zeiger auf Strukturen über- und zurückgeben werden.
Über Compound Literal (siehe Kap. [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]) kann einer Strukturvariablen als 'ganzes' einen neuen Wert zugewiesen werden:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
var1={.a=7}; //KO, Initialisierungsliste kann hier nicht
//angewendet werden
var1=(struct abc){.a=7}; //Wertezuweisung über Compound Literal möglich
</syntaxhighlight>
Formel gesehen entspricht das Compound Literal einer 'unnamed Variable', die als erstes angelegt und initialisiert wird. Der Inhalt dieser Variablen wird im Anschluss der eigentlichen Variable zugewiesen!
=== Prototyp / Deklaration einer Struktur ===
Soll der Datentyp einer Struktur genutzt werden, der erst an weiter hinten liegenden Stellen im Programm definiert wird, so ist wie bei Variablen/Funktionen ein Prototyp/Deklaration notwendig:
<syntaxhighlight lang="C">
struct abc; //Prototyp der Struktur abc
...
struct abc { int a,b,c;}; //Definition der Struktur abc
</syntaxhighlight>
Die Deklaration sagt einzig aus, dass die Struktur später definiert wird, beinhaltet aber nicht die Strukturelemente. Folglich kann auf Basis dieses Prototyps keine Variable definiert werden, sondern einzig ein Zeiger auf solche eine Struktur:
<syntaxhighlight lang="C">
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Anwendung:
* Struktur, welche auf sich selbst verweist (Verkettete Liste)
:<syntaxhighlight lang="C">
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
int main(int argc,char *argv[]) {
struct vl *head=NULL;
struct vl a={.daten="Ele a"};
struct vl b={.daten="Element b"};
struct vl c={.daten="c-Eleent"};
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL; //Zur Kennzeichnung des letzten Elementes
for(struct vl*ptr=head;ptr;ptr=ptr->next)
printf("'%s'\n",ptr->daten);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Entsprechend der objektorientierten Programmierung, wenn alle Attribute der Klasse private sind:
:{| class="wikitable"
|-
! !! class.h
|-
|
||<syntaxhighlight lang="C">
struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
</syntaxhighlight>
|-
! main.c !! class.c
|-
|<syntaxhighlight lang="C">
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
..
//Kein Zugriff auf
//Strukturelemente möglich
return 0;
}
</syntaxhighlight>
||<syntaxhighlight lang="C">
#include "class.h"
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *)
malloc(sizeof(struct class));
this->attr1=10;
*me=this;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
//..
//Kein Zugriff auf Strukturelemente möglich
return 0;
}
|class_h=struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
|class_c=#include "class.h"
#include <stdlib.h> //fuer malloc()
#include <stdio.h> //fuer printf()
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *) malloc(sizeof(struct class));
printf("konstructor called\n");
this->attr1=10;
*me=this;
}
| execCompilerOptions=-Wall class.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Vergleichen von Strukturen ===
Ein Vergleich von Strukturen über den direkten Weg ist nicht möglich. Vielmehr müssen die Strukturelemente händisch verglichen werden:
<syntaxhighlight lang="C">
struct xyz {int inx,y,z;} var1,var2;
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} var1={1,2,3},var2={1,2,3};
int main(int argc,char *argv[]) {
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
printf("Strukturelemente von var1 und var2 identisch\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis
* Bei Rechnerarchitekturen mit nicht ausgerichteter Speicherausrichtung (Alignment) kann ergänzend ein Vergleich über memcmp() erfolgen
=== Speicherplatzbedarf einer Struktur ===
Für jedes Strukturelement wird Speicher entsprechend der Größe des Datentyps reserviert. Der Speicherplatzbedarf der Gesamtstruktur ergibt sich aus der Summe der Strukturelemente:
<syntaxhighlight lang="C">
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
sizeof(var1) //ergibt 12
sizeof(struct xyz) //ergibt 12
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
int main(int argc,char *argv[]) {
printf("sizeof(var1)=%zu Bytes\n",sizeof(var1));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Ermittlung der tatsächlichen Speichergröße einer Struktur erfolgt über den sizeof-Operator:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;} a;
sizeof(a); //=12 OK
sizeof(a.x); //=4 OK
sizeof(struct xyz); //=12 OK
sizeof(struct xyz.x); // KO
//Ist dies dennoch notwendig, so kann dies über den Umweg eines Zeigers
//erfolgen:
sizeof(((struct xyz *)0)->x); //=4 OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x,y,z;
} a;
int main(int argc,char *argv[]) {
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
printf("sizeof(a.x)=%zu Bytes\n",sizeof(a.x));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
printf("sizeof(struct xyz.x)=%zu Bytes\n",sizeof(struct xyz.x));
printf("sizeof(((struct xyz *)0)->x)=%zu Bytes\n",sizeof(((struct xyz *)0)->x));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei Rechnerarchitekturen mit ausgerichteter Speicherausrichtung (Alignment) (siehe {{w|Speicherausrichtung}}) kann der tatsächliche Speicherbedarf größer sein! Hier fügt der Compiler ggf. zwischen den Strukturelemente Füllbytes (Padding Bytes) ein
* Die Reihenfolge der Strukturelemente wird vom Compiler nicht geändert. D.h. die Zuordnung der Speicherstellen zu den Strukturelementen erfolgt in der Definitionsreihenfolge
=== Interne Organisation ===
Compilerintern werden die Strukturelemente über einen Offset dargestellt. Das erste Strukturelement bekommt dabei immer den Offset 0 zugewiesen. Das nachfolgende Element bekommt als Offset die Größe des Datentyps des vorherigen Elementes zugewiesen. Usw.. <br />
Der Compiler setzt den Zugriff auf ein Strukturelement einer (Struktur)Variablen so um, dass er zunächst die Startadresse der Variablen holt und zu dieser den Offset des Strukturelementes addiert. Die Anzahl der zu lesenden/schreiben Bytes ergibt sich aus dem Datentyp des Strukturelementes:
<syntaxhighlight lang="C">
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1; //(Beispielhaft soll var1 die Speicheradressen
//0x100..0x10B belegen). Der Zugriff auf
//die Variable erfolgt immer über die Startadresse
var1.x=7; //Zugriff auf Speicheradresse 0x100+0 (Offset)
var1.y=8; //Zugriff auf Speicheradresse 0x100+4 (Offset)
var1.z=9; //Zugriff auf Speicheradresse 0x100+8 (Offset)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1;
int main(int argc,char *argv[]) {
//Zugriff siehe Compiler
var1.x=7; //mov DWORD PTR var[rip+0],7
var1.y=8; //mov DWORD PTR var[rip+4],7
var1.z=9; //mov DWORD PTR var[rip+8],7
return 0;
} | execCompilerOptions=-Wall|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Offset eines Strukturelementes kann mit dem offsetof-Operator ermittelt werden:
<code>Syntax: offsetof(type,Strukturelement)</code>
Wie beim sizeof-Operator gilt der offsetof-Operator als Konstantenausdruck und der Rückgabedatentyp ist <code>size_t</code>. Zur Nutzung des Operators muss die Header-Datei 'stddef.h' inkludiert werden:
<syntaxhighlight lang="C">
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var1;
offsetof(struct xyz,z) --> 8
offsetof(var1,z) --> KO: Es wird ein Datentyp und
keine Variable erwartet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz{
int x,y,z;
} var1;
int main(int argc,char *argv[]) {
printf("offsetof(struct xyz,x)=%zu Bytes\n",offsetof(struct xyz,x));
printf("offsetof(struct xyz,y)=%zu Bytes\n",offsetof(struct xyz,y));
printf("offsetof(struct xyz,z)=%zu Bytes\n",offsetof(struct xyz,z));
printf("offsetof(var1,z)=%zu Bytes\n",offsetof(var1,z));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Unter Nutzung des offsetof-Operators kann man bei gegebener Adresse eines Strukturelementes auf die Startadresse der zugrundeliegenden Struktur zurückrechnen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1;
int *ptri=&var1.y;
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var={1,2,3};
int *ptri=&var.y;
int main(int argc,char *argv[]) {
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
printf("ptrxyz->x=%d ptrxyz->y=%d ptrxyz->z=%d",ptrxyz->x,ptrxyz->y,ptrxyz->z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dazu wird von der Startadresse des Strukturelementes der Offset abgezogen. Da der offsetof-Operator den Abstand in Bytes zurückgibt, muss der Pointer auf das Strukturelement zuvor ebenfalls in ein 'Byte'-Zeiger gewandelt werden.
Im Linux kernel wird diese Subtraktion über das container_of Makro realisiert:
<syntaxhighlight lang="C">
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
</syntaxhighlight>
Dieses Makro ermöglicht es, bei gegeben Startadresse eines Strukturelementes die Startadresse der zugrundeliegenden Struktur zu berechnen. Anwendung findet dieses Makro bspw. in:
* der objektorientierten Programmierung, um ausgehend vom gegebenen Parent-Element die Startadresse des Child-Elementes zu berechnen:
:<syntaxhighlight lang="C">
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
..
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
printf("parent.attr1=%d parent.att2=%d\n",me->attr1,me->attr2);
printf("child.attr1=%d\n",child->attr1);
}
int main(int argc,char *argv[]) {
struct child obj1;
obj1.attr1=1;
obj1.parent.attr1=2;
obj1.parent.attr2=3;
parent_methode(&obj1.parent);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei verketteten Listen, wenn das Next-Element im Datensatz selbst eingearbeitet ist:
:<syntaxhighlight lang="C">
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(PTR, TYPE, MEMBER) \
((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
vl_t head={NULL};
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
int main(int argc,char *argv[]) {
daten_t obj1={.daten1=1,.daten2=2};
daten_t obj2={.daten1=3,.daten2=4};
vl_addfront(&obj1);
vl_addfront(&obj2);
daten_t *ret=vl_getfront();
printf("%d %d\n",ret->daten1,ret->daten2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Explizites Cast ===
Eine Struktur kann nicht in einen anderen Datentyp und damit auch nicht in einen anderen Strukturdatentyp mit identischen Strukturelementen konvertiert werden:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} xyz;
struct abc {int a,b,c;} abc;
int var;
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} xyz;
struct abc {
int a,b,c;
} abc;
int var;
int main(int argc,char *argv[]) {
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Incomplete Array ===
Das letzte Element einer Struktur kann ein Array ohne Angabe einer Dimensionsgröße sein (Incomplete Array/Flexible Array Member). Bei der Definition einer Variablen von solch einem Datentyp wird in der Tat kein Speicher für das letzte Element reserviert, so dass dies 'händisch' erfolgen muss. Auf das Array kann ungeachtet dessen unproblematisch zugegriffen werden:
<syntaxhighlight lang="C">
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert
//wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert wurde
//Zur Darstellung dieses Sachverhaltes wurde der Sanitizer
//über den Compilerschalter -fsanitize=address aktiviert
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Speicherplatzreservierung für das incomplete Array kann auf zwei verschiedene Arten erfolgen:
* Speicherplatzreservierung für das Incomplete Array über Variableninitialisierung (nur GCC-C und nur im Falle einer globalen Variablen)
:<syntaxhighlight lang="C">
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
int main(int argc,char *argv[]) {
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(ele1)=%zu Bytes\n",sizeof(ele1));
printf("sizeof(ele2)=%zu Bytes\n",sizeof(ele2));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Speicherplatzreservierung für das Incomplete Array über malloc
:<syntaxhighlight lang="C">
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
if(b==NULL)
return printf("malloc failed\n"),1;
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
//zum Beweis Sanitizer über -fsanitize=address eingebunden
free(b);
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Das Incomplete Array bietet sich überall dort an, wo Daten gespeichert werden sollen, deren Größe sich erst zur Laufzeit ergibt.
=== Anwendung ===
Die Nutzung des Datentyps struct empfiehlt sich an vielen Stellen:
* Zusammengehörende Daten zu Kapseln (entsprechend der objektorientierten Programmierung
* Verkette Listen
* Aufgrund der Typsicherheit zur Darstellung von sicherheitskritischen Aufgaben
Siehe Übungsbereich!
=== C++ ===
Der wesentliche Syntax von Strukturen wurde in C++ übernommen. D.h.:
* das abschließende Semikolon
* der Zugriff auf die Strukturelemente
* Speicherplatzreservierung
* die Definition von Variablen mit der Definition des Datentyps
* ...
Ergänzend wurde in C++ der Datentyp class eingeführt, der weitestgehend identisch zu struct ist. Geändert/Hinzugefügt wurden folgende Sachverhalte:
* Classen/Strukturen können Methoden haben
* Operatoren (Zuweisungsoperator, Addition, ...) können überladen werden
* Alle Strukturelemente (und Methoden) einer struct sind per default public
* Alle Attribute (und Methoden) einer Class sind per default private
* Zur Nutzung des Datentyps ist das führende struct nicht notwendig (dies bedingt dann auch, dass der Strukturdatentyp kein separater Namensraum ist)
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var_xyz;
</syntaxhighlight>
* Initialisierungswerte für Strukturelemente und Klassenattribute bei der Datentypbeschreibung angegeben werden können:
:<syntaxhighlight lang="C++">
struct xyz {
int x=3;
int y=1;
int z;
};
xyz var={7}; //var.x=7 var.y=1 var.z=0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x=3;
int y=1;
int z;
};
int main(int argc,char *argv[]) {
xyz var={7}; //var.x=7 var.y=1 var.z=0
printf("var.x=%d var.y=%d var.z=%d\n",var.x,var.y,var.z);
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In C++ kann eine Struktur ebenfalls über 'designated initializers' initialisiert werden. Jedoch muss die Reihenfolge der Initialisierungselement identisch zur Datentypdefinition sein. Auch ist keine Doppeltbenennung erlaubt:
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x,y,z;
};
int main(int argc,char *argv[]) {
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
(void)var1;
(void)var2;
(void)var3;
(void)var4;
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Union ==
Ähnlich wie eine Struktur ist ein Union ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wird. Bei sog. Union beginnen jedoch alle Komponenten nicht wie bei Strukturen an nacheinander folgenden Speicheradressen, sondern an der identischen Speicheradresse, d.h. ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union kann folglich zu einem Zeitpunkt nur ein Element enthalten. Der benötigte Speicherplatz ergibt sich aus der größten Komponente.
<code>Syntax: union Unionname<sub>Opt</sub> {Datentyp Variablenname; …}<sub>Opt</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Schutz/Zugriffssteuerung der Unionelemente ist nicht vorhanden. Es kann in beliebiger Reihenfolge auf die einzelnen Elemente zugegriffen werden.
Die Anwendung ist identisch wie bei Strukturen, so dass im Folgenden nur die Abweichungen zu den Strukturen beschrieben werden.
=== Speicherplatzbedarf und interne Struktur einer Union ===
Die Größe der Union ergibt sich aus dem größtem Unionelement. Alle Unionelemente überlappen sich, so dass der Offset zum Basiselement 0 ist:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird ein kleineres Unionelement belegt und im Anschluss ein größeres Unionelement gelesen, so ist der Inhalt der durch das kleinere Element nicht beschriebenen Speicherstellen undefiniert:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc.a=0x11;
printf("%08x",abc.c);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
};
void foo(int var) {
int lok=var;
printf("Foo(%#08x) called\n",lok);
}
void bar(void) {
union abc abc;
abc.a=0x11;
printf("abc.a=%#02x\n",abc.a);
printf("abc.c=%#08x\n",abc.c);
}
int main(int argc,char *argv[]) {
//Zur Darstellung des Phänomens muss
//erstmal der Stack mit Daten belegt werden!
foo(0x12345678);
bar();
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Union ===
Bei einer Union kann nur ein Element initialisiert werden, d.h. die Initialisierungsliste kann nur einen Wert beinhalten. Ohne explizite Benennung des Unionelementes in der Initialisierungsliste wird das erste Element aus der Datentypbeschreibung initialisiert. Mit expliziter Benennung mittels 'designated initializers' können auch andere Elemente initialisiert werden:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Anwendung ===
Mittels des Datentyps union können diverse Anwendungsfälle abgedeckt werden:
* Über Union lassen sich größere Datentypen in kleinere Datentypen unterteilen, um z.B. einzelne Bytes zu extrahieren:
<syntaxhighlight lang="C">
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union floatu var={1.234};
printf("%f\n",var.var); //Darstellung des Float-Wertes
printf("%x\n",var.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var.byte[0],var.byte[1],var.byte[2],var.byte[3]);
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
union longlong var2={0x123456789ABCDEFULL};
printf("%llx\n",var2.ll);
printf("%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
int main(int argc,char *argv[]) {
union floatu var1={1.234};
printf("var1.var=%f\n",var1.var); //Darstellung des Float-Wertes
printf("var1.hex=%x\n",var1.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("var1.byte[0..3]=%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var1.byte[0],var1.byte[1],var1.byte[2],var1.byte[3]);
union longlong var2={0x123456789ABCDEFULL};
printf("var2.ll=%llx\n",var2.ll);
printf("var2.i[0..1]=%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Ein weiterer Anwendungsfall ergibt sich, wenn in einer Struktur unterschiedliche Datensätze gespeichert werden sollen (siehe {{w|Tagged Union}}):
:<syntaxhighlight lang="C">
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
int main(int argc,char *argv[]) {
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mittels eines Tagged Union kann komfortabel ein Binärbaum realisiert werden:
:<syntaxhighlight lang="C">
//Quelle: https://github.com/Hirrolot/datatype99
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h> //fuer printf()
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Die Eigenschaften des Datentyps union entsprechen den Eigenschaften des Datentyps struct in C++.
== Enum/Aufzählungstyp ==
Nach dem Wikipedia Artikel {{w|Aufzählungstyp}} ist ''ein Aufzählungstyp (englisch enumerated type) ein Datentyp für Variablen mit einer endlichen Wertemenge. Alle zulässigen Werte des Aufzählungstyps werden bei der Deklaration des Datentyps mit einem eindeutigen Namen (Identifikator) definiert, sie sind Symbole.''
<code>Syntax: enum enumname<sub>Opt</sub> {definition-list[=expression]}<sub>Opt</sub> Variablenliste<sub>Opt</sub></code>
Die Anwendung ist identisch wie bei Strukturen, so dass nachfolgend nur die Abweichungen zu den Strukturen beschrieben werden.
=== Datentyp von enum ===
In C entspricht der Datentyp Enum dem Datentyp <code>int</code> so dass Zuweisungen/Vergleiche mit Ganzzahlen möglich sind. Ganzzahloperationen funktionieren ebenso:
<syntaxhighlight lang="C">
enum STATUS {OK,KO=5}; //Definition des Datentyps
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
status++;
status=5.7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum STATUS {OK,KO=5}; //Definition des Datentyps
int main(int argc,char *argv[]) {
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
printf("status == 5\n");
status++;
status=5.7;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Enumelemente ===
Die Elemente der Definitionsliste sind Integerkonstanten. Diese können auch in Kombination mit anderen Datentypen genutzt werden. Auch gibt es keinen gesonderten Namensraum für Elemente der Definitionsliste. Sie 'konkurrieren' folglich mit allen Variablen- und Funktionsnamen:
<syntaxhighlight lang="C">
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
int main(int argc,char *argv[]) {
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der erste Enumelement der Definitionsliste bekommt den Wert 0 zugewiesen. Folgeelemente bekommen den Wert des Vorgängerelementes +1 zugewiesen.
Enumelemente können mit einer Konstanten (und Konstantenausdruck) initialisiert werden:
<syntaxhighlight lang="C">
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
int main(int argc,char *argv[]) {
printf("bill=%d john=%d, fred=%d\n",bill,john,fred);
printf("error=%d warning=%d info=%d ok=%d\n",error,warning,info,ok);
printf("Ostfalia=%d Wolfenbuettel=%d\n",Ostfalia,Wolfenbuettel);
printf("test=%d\n",test);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Es empfiehlt sich, die Enumelemente in GROSSBUCHSTABEN zu schreiben. Hiermit wird gekennzeichnet, dass es sich um Konstanten und nicht um Variablen/Funktionen handelt
=== Anwendung ===
Die Nutzung des Datentyps enum empfiehlt sich überall dort, wo eine Fallunterscheidung notwendig ist:
* Statusrückgabe von Funktionen:
:<syntaxhighlight lang="C">
enum STATUS {OK,MEMORY_OVERFLOW, DIVISION_BY_ZERO};
enum STATUS funct(…) {
return MEMORY_OVERFLOW;
}
</syntaxhighlight>
* Beschreibung der Zustände und der Ereignisse eines Zustandsautomates:
:<syntaxhighlight lang="C">
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Ergänzend zu den Abweichungen bei Structs sind hier weitere Unterscheidungsmerkmale vorhanden:
* Enums stellen einen eigenen Datentyp dar, der nicht mit int kompatible ist. Das bedingt unter anderem, dass einige Operatoren wie z.B. ++ nicht mehr auf Variablen des Datentyps enum angewendet werden. Die Enumelemente als solches sind jedoch kompatibel zum Ganzzahldatentyp:
:<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
int main(int argc,char *argv[]) {
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
printf("RED==2\n");
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
* Auch enums können Methoden besitzen.
* Über Operatorüberladung können z.B. nicht vorhandene Operatoren wie ++/-- ergänzt werden
* Über unscoped/scoped Enumerations wird der 'Namensraum' gesteuert:
:* Unscoped Enumeration (Elemente der Definitionsliste stehen wie bei C im Zugriff)
::<code>Syntax: enum name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE };
Color r = RED;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE };
Color r = RED;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
:* Scoped enumeration (Elemente der Definitionsliste haben einen eigenen 'Namensraum')
::<code>Syntax: enum '''class|struct''' name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
== Bitfelder ==
Nach dem Wikipediaartikel {{w|Bitfeld}} ''bezeichnet in der Informationstechnik und Programmierung ein Bitfeld ein vorzeichenloses Ganzzahldatentyp, in dem einzelne Bits oder Gruppen von Bits aneinandergereiht werden. Es stellt eine Art Verbunddatentyp auf Bit-Ebene dar. Im Gegensatz dazu steht der primitive Datentyp, bei dem der Wert aus allen Stellen gemeinsam gebildet wird.''
Der Syntax entspricht dem struct-Syntax, mit der Ergänzung, dass hinter den Strukturelementen noch die Bitbreite getrennt durch ein Doppelpunkt angegeben wird:
<syntaxhighlight lang="C">
struct time {
unsigned int hour: 5; //0..23 Bits 0..4
unsigned int minute: 6; //0..59 Bits 5..10
Unsigend int second: 6; //0..59 Bits 11..16
} myTime;
</syntaxhighlight>
Als mögliche Datentypen für die Strukturelemente stehen nur die Ganzzahldatentypen <code>int</code>, <code>short</code>, <code>long</code> , <code>long long</code> und <code>char</code> zur Verfügung. Der Datentyp eines Strukturelementes muss mindestens die Anzahl der Bits enthalten, wie diese über die Bitbreite gefordert wird.
Von den Strukturelementen kann keine Adresse bestimmt werden! Auch der <code>offsetf</code> - Operator schlägt fehl.
Der Datentyp entspricht im Wesentlichen einem Ganzzahlzahldatentyp, so dass bei Zugriff auf eine Variable dieses Datentyps eine Ganzzahl gelesen/geschrieben wird. Bei Zugriff auf die einzelnen Strukturelemente werden die entsprechenden Bits dieser Ganzzahlvariablen maskiert, so dass nur die betroffenen Bits geändert werden:
<syntaxhighlight lang="C">
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) | (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) | ((second&0b00001111)<<2);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
//Nachweis am besen über den Maschinensprachevergleich!
int main(int argc,char *argv[]) {
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) {{!}} (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) {{!}} ((second&0b00001111)<<2);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
h=c
}} Öffnen im Compiler Explorer] }}
=== Anwendung===
* Komprimierte Speicherung der Uhrzeit (wie dies z.B. in Realtimeclocks erfolgt)
:<syntaxhighlight lang="C">
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
int main(int argc,char *argv[]) {
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Aufteilung von FloatingPoint Zahlen in seine Komponenten
:<syntaxhighlight lang="C">
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
int main(int argc,char *argv[]) {
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",
(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Bitfelder existieren mit den bekannten Ergänzungen auch in C++.
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
fcz3y8au2ba52zsh7sj63rlrs1mqzr2
1090842
1090841
2026-09-15T07:59:07Z
D. Justen
102048
Aussagen klarer formuliert
1090842
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C kennt nachfolgende grundlegende Datentypen und Zeiger auf diese Datentypen (siehe auch [[Programmieren in C/C++: Grundlagen# Grundlegende Datentypen und Typsicherheit| Grundlagen:Grundlegende Datentypen und Typsicherheit]])
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| [[#Ganzzahl Datentypen|Ganzzahl]] ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| [[#Gleitkomma Datentypen|Gleitkommazahl]] ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Array|Arrays]] ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| [[#Struktur/Verbundtyp|Strukturen]]/[[#Union|Unions]] ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| [[#Enum/Aufzählungstyp|Aufzählungstyp]] ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Grundlagen #Boolescher-Datentype/Operatoren|Boolescher Datentyp]] ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| [[#Komplexe Zahlen|Komplexe Zahlen]] ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
Bis auf die Datentypen Funktionen, Array und die Zeiger sollen die wesentlichen Aspekte dieser Datentypen im nachfolgenden beschrieben werden.
'''Der grundlegende Datentyp ist <code>int</code>!'''
* Es wird mit nichts Kleinerem gerechnet als mit dem Datentyp <code>int</code> (siehe [[#Implizite Typumwandlung | Implizite Typumwandlung]]) :
:<syntaxhighlight lang="C">
char var1=10,var2=20,var3;
var3=var1+var2; //Addition findet auf Basis des Datentyps int statt
</syntaxhighlight>
* Es gibt zwar den Booleschen Datentyp, dieser entspricht jedoch einem Ganzzahldatentyp und <code>true</code> und <code>false</code> entsprechen den Integerwerten 0 und 1
* Der Aufzählungsdatentyp und seine Aufzählungselemente sind vom Datentyp <code>int</code>
* Bis einschl. C90 wurde bei der Definition von Variablen ohne Angabe des Datentyps, bei Definition einer Funktion ohne Angabe des Datentyps der Übergabeparameter, des Rückgabedatentyps der Datentyp implizit auf int gesetzt ('''implizit int''')
:<syntaxhighlight lang="C">
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}int main(int argc,char *argv[]) {
printf("%d",foo(1,var2));
return 0;
} | execCompilerOptions=-Wall -std=c90|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Ganzzahl Datentypen ==
Grundlegend kennt die Programmiersprache C nur zwei Ganzzahldatentypen:
* Datentyp: <code>int</code>
: Vorzeichenbehafteter (signed) Datentyp, dessen Bitbreite von der Rechnerarchitektur und des Compilers abhängig ist
* Datentyp <code>char</code>
: Datentyp mit einer Mindestbreite von 8-Bit u.A. zur Speicherung von Zeichen typischerweise im ASCII Format. Die C-Spezifikation [C11 6.2.5 Types] lässt es dem Compiler frei, ob <code>char</code> als vorzeichenbehafteter oder vorzeichenloser Datentyp implementiert wird.
: Ergänzend kann der Datentyp <code>char</code> auch zur Speicherung von ganzen Zahlen genutzt werden. In diesem Fall empfiehlt sich, diese explizit als <code>signed</code> und <code>unsiged</code> zu definieren. Wenn nur ASCII Zeichen gespeichert werden, so ist diese Angabe nicht nötig!
Optional können Qualifier dem Datentyp vorangestellt werden:
* <code>unsigned</code> / <code>signed</code> zur Angabe, ob der Inhalt als vorzeichenlose Zahl oder als vorzeichenbehaftete Zahl zu interpretieren ist. Ohne Angabe sind Variablen vom Datentyp <code>int</code> vorzeichenbehaftet
* <code>short</code> / <code>long</code> / <code>long long</code> (letzteres seit C99) als vorangestellten Qualifier zu <code>int</code> zur Vergrößerung/Verkleinerung der Bitbreite. Bei Angabe des Qualifiers ist das Schlüsselwort <code>int</code> optional. Die Beschreibung <code>long long int</code> und <code>long long</code> sind gleichbedeutend!
Als Bitbreite für die Datentypen ist im C-Standard nur ein Mindestbreite definiert. Die genaue Bitbreite hängt von der Rechenbreite des Systems und vom Compiler ab (siehe [C11 6.2.5 Types]):
{| class="wikitable"
|-
! Datentype !! Mindest<br />breite !! Typisch bei 32-Bit<br />Architektur !! Typisch bei 64-Bit<br />Architektur !! printf Format<br />Anweisung
|-
| <code>char</code> || 8 || 8 || 8 || <code>%c</code>
|-
| <code>signed char</code><br /><code>unsigned char</code>|| 8 || 8 || 8 || <code>%hhd</code><br /><code>%hhu</code>
|-
| <code>short</code><br /><code>short int</code>|| 16 || 16 || 16 || <code>%hd</code> / <code>%hu</code>
|-
|<code>int</code>|| 16 || 16/32 || 32 || <code>%d</code> / <code>%u</code>
|-
|<code>long</code><br /><code>long int</code>|| 32 || 32 || 32/64 || <code>%ld</code> / <code>%lu</code>
|-
|<code>long long</code><br /><code>long long int</code>|| 64 || 64 || 64 || <code>%lld</code> / <code>%llu</code>
|}
In der Header-Datei <code>limits.h</code> sind die tatsächlichen Grenzwerte der Datentypen gespeichert:
{| class="wikitable"
|-
! Konstante !! Beschreibung !! Typ. bei 64-Bit Architektur
|-
| <code>CHAR_BIT</code> || Anzahl der Bits in einem Char || 8
|-
| <code>SCHAR_MIN</code> || min. Wert, den der Typ bei signed char aufnehmen kann || -128
|-
| <code>SCHAR_MAX</code> || max. Wert, den der Typ bei signed char aufnehmen kann || 127
|-
| <code>UCHAR_MAX</code> || max. Wert, den der Typ bei unsigned char aufnehmen kann || 255
|-
| <code>CHAR_MIN</code> || min. Wert, den der Typ char aufnehmen kann || 0 oder SCHAR_MIN
|-
| <code>CHAR_MAX</code> || max. Wert, den der Typ char aufnehmen kann || SCHAR_MAX oder UCHAR_MAX
|-
| <code>SHRT_MIN</code> || min. Wert, den der Typ short int annehmen kann || -32.768
|-
| <code>SHRT_MAX</code> || max. Wert, den der Typ short int annehmen kann || 32.767
|-
| <code>USHRT_MAX</code> || max. Wert, den der Typ unsigned short int annehmen kann || 65.535
|-
| <code>INT_MIN</code> || min. Wert, den der Typ int annehmen kann || -2.147.483.648
|-
| <code>INT_MAX</code> || max. Wert, den der Typ int annehmen kann || 2.147.483.647
|-
| <code>UINT_MAX</code> || max. Wert, den der Typ unsigned int aufnehmen kann || 4.294.967.296
|-
| <code>LONG_MIN</code> || min. Wert, den der Typ long int annehmen kann || -2.147.483.648 oder<br />-9.223.372.036.854.775.808
|-
| <code>LONG_MAX</code> || max. Wert, den der Typ long int annehmen kann || 2.147.483.647 oder<br />9.223.372.036.854.775.807
|-
| <code>ULONG_MAX</code> || max. Wert, den der Typ unsigned long int annehmen kann || 4.294.967.296 oder<br />18.446.744.073.709.551.616
|-
| <code>LLONG_MIN</code> || min. Wert, den der Typ long long int annehmen kann || -9.223.372.036.854.775.808
|-
| <code>LLONG_MAX</code> || max. Wert, den der Typ long long int annehmen kann || 9.223.372.036.854.775.807
|-
| <code>ULLONG_MAX</code> || max. Wert, den der Typ unsigned long long int annehmen kann || 18.446.744.073.709.551.615
|}
Aufgrund dessen, dass die Breite der Datentypen von der Rechnerarchitektur und vom Compiler abhängig ist, sind in der Header-Datei <code>stdint.h</code> Aliase für Datentypen enthalten, welche in ihrem Alias die tatsächliche Breite und das Vorzeichens beinhalten:
<syntaxhighlight lang="C">
uint8_t --> unsigned 8-Bit
int8_t --> signed 8-Bit
uint16_t --> unsigned 16-Bit
int16_t --> signed 16-Bit
...
</syntaxhighlight>
In C++ sind diese Aliase im <code>std</code> namespace definiert:
<syntaxhighlight lang="C++">
std::intptr_t
std::int8_t std::uint8_t
std::int16_t std::uint16_t
std::int32_t std::uint32_t
Std::int64_t std::uint64_t
</syntaxhighlight>
Zur Erzeugung von portablen/rechnerunabhängigen Programmen empfiehlt sich, diese Datentypen zu nutzen. Die Rechenbreite ist dann unabhängig vom Compiler und Betriebssystem.
== Gleitkomma Datentypen ==
Gleitkommazahlen werden im Computer auf Basis folgender Schreibweise dargestellt (siehe auch: {{w|Gleitkommazahl}}):<br />
<syntaxhighlight lang="C">
Dezimalsystem Dualsystem
12,3456710 = 1234567 * 10^-5 0,110 = 1,1001100110011 * 2^-4
------- -- --------------- --
Mantisse Exponent Mantisse Exponent
</syntaxhighlight>
;Mantisse: Vorzeichenlose ganze Zahl (ggf. mit einer festen Position des Dezimalpunktes=Festkommazahl)
;Exponent: Vorzeichenbehaftete ganze Zahl, welche um einen Bias verschoben ist
;Vorzeichen: Vorzeichen der (vorzeichenlosen) Mantisse
Zur Speicherung im Computer werden das Vorzeichen, die Mantisse und der Exponent getrennt im Binärformat gespeichert, für den Programmierer aber als eine (zusammenhängende) Zahl dargestellt:
[[File:Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse.png|thumb|400px|center|Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse]]
Gleitkommazahlen haben genauso wie ganze Zahlen einen beschränkten Wertebereich:
* Die Anzahl der Bits der Mantisse bestimmen die Anzahl der Nachkommastellen:
:<syntaxhighlight lang="C">
Bei 23-Bit Mantisse ist die max. Zahl 2^-23-1=0,000000119,
welches 6..7 dezimale Stellen entspricht!
</syntaxhighlight>
* Mit dem Exponent kann 'quasi' der kleinste und der größte Wertebereich angegeben werden:
:<syntaxhighlight lang="C">
Bei 8-Bit Exponent mit einem Bias von 127 liegt der Wertebereich des
Exponenten im Bereich von -126 … +127 (Exponent -127 und +127 wird zur
Darstellung weitere Zahlen benötigt).
Die kleinste darstellbare Zahl (unter Vernachlässigung der Nachkommastellen der Mantisse ist:
2^-126=1/2^126≅1,175*10^-38
Die größte darstellbare Zahl ist:
2^127 ≅1,7*10^38
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
float sqrtf(float);
float powf(float,float);
#include <ieee754.h>
#include <complex.h>
union test {
unsigned int i;
float f;
union ieee754_float b;
};
int main(int argc,char *argv[]) {
union test var = {.f=-0.1};
printf("Float=%f Binär=%032b\n",var.f,var.i);
printf("v=0b%b e=0b%08b m=0b(1).%023b\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%10d m=%29d\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%d-%d=%d m=1+%d/2^-23=%f\n",var.b.ieee.negative,
var.b.ieee.exponent,IEEE754_FLOAT_BIAS,var.b.ieee.exponent-IEEE754_FLOAT_BIAS,
var.b.ieee.mantissa,1.0+var.b.ieee.mantissa*1.0/(1<<23));
printf("\n--- Beispiele von Genauigkeitsprobleme im Umgang mit Gleitkommazahlen (hier float) ----\n");
printf("powf(sqrtf(%1.8f),2) = %1.8f\n",2.0f,powf(sqrtf(2.0f),2));
printf("%f + %f = %f\n",2000.0,0.0004,(double)(2000.0f+0.0004f));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Grundlegend kennen die Programmiersprachen C/C++ folgende Gleitkommadatentypen:
* Datentyp: <code>float</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindesten 6 Stellen betragen, so dass der Datentyp typischerweise 32-Bit groß ist
* Datentyp: <code>double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, so dass der Datentyp typischweise 64-Bit Große ist
* Datentyp: <code>long double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, damit könnte dieser Datentyp gleich dem Datentyp <code>double</code> gesetzt werden. In der Tat ist die Datenbreite Rechner- und Compilerabhängig. Einige Compiler setzen diesen Datentyp identisch zu <code>double</code>, bei x86 Prozessoren wird aufgrund der Hardwareunterstützung 80-Bit genutzt (wobei in der Tat der Datentyp dann 16-Byte Speicherplatz beansprucht) und einige Systeme nutzen 128-Bit (wobei hier aufgrund ggf. fehlender Hardwareunterstützung Operationen mit diesem Datentyp per Software emuliert werden) (siehe Wikipedia Artikel {{w|lang=en|Long_double|long double}}).
Die genaue Darstellung (Anzahl der Bits für Mantisse und Exponent, Darstellung von NAN/INF, ….) ist in C nicht spezifiziert und somit compiler- und rechnerabhängig. Zumeist wird mittlerweile die {{w|IEEE 754}} Standardisierung genutzt (Norm wurde von Intel mit der Entwicklung der 8087 FPU entworfen).
Grunddatentypen und der Wertebereich (nach {{w|IEEE 754}})
{| class="wikitable"
|-
! Daten-<br/>type !! Speicher-<br />platz !! Exponent !! Mantisse !! Größte Zahl !! Kleinste Zahl !! Genauigkeit !! printf Format Anweisung
|-
| binary32→<code>float</code> || 4 Byte || 8 bit || 23 bit || ~3,4*10<sup>38</sup> || ~1,2*10<sup>-38</sup> || 7..8 Stellen || ---
|-
| binary64→<code>double</code> || 8 Byte || 11 bit || 52 bit || ~1,8*10<sup>308</sup> || ~2,2*10<sup>-308</sup> || 15..16 Stellen || %f %e %g
|-
| binary64 extended→<code>long double</code> || ≥10 Byte || ≥15 bit || ≥63 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 19..20 Stellen || %Lf %Le %Lg
|-
| binary128→<code>long double</code> || 16 Byte || 15 bit || 112 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 34 Stellen || %Lf %Le %Lg
|}
Die tatsächliche Auflösung der Datentyps kann auf Basis nachfolgender Konstanten, definiert in der Header-Datei <code>float.h</code>, ermittelt werden:
:<syntaxhighlight lang="C">
FLT_DIG --> Anzahl der dezimalen Nachkommastellen für float
DBL_DIG --> Anzahl der dezimalen Nachkommastellen für double
LDBL_DIG --> Anzahl der dezimalen Nachkommastellen für long double
FLT_MIN_10_EXP --> Minimaler Exponent zur Basis 10
DBL_MIN_10_EXP
LDBL_MIN_10_EXP
FLT_MAX_10_EXP --> Maximaler Exponent zur Basis 10
DBL_MAX_10_EXP
LDBL_MAX_10_EXP
LDBL_MANT_DIG --> Anzahl der Bits für die Mantisse
LDBL_MANT_DIG
LDBL_MANT_DIG
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <float.h>
int main(){
printf("FLT_DIG =%u\n",FLT_DIG);
printf("DBL_DIG =%u\n",DBL_DIG);
printf("LDBL_DIG =%u\n",LDBL_DIG);
printf("FLT_MIN_10_EXP =%d\n",FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP =%d\n",DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP=%d\n",LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP =%d\n",FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP =%d\n",DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP=%d\n",LDBL_MAX_10_EXP);
printf("FLT_MANT_DIG =%d\n",FLT_MANT_DIG);
printf("DBL_MANT_DIG =%d\n",DBL_MANT_DIG);
printf("LDBL_MANT_DIG =%d\n",LDBL_MANT_DIG);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Aufgrund des nicht standardisierten Formates sollte ein Gleitkommadatentyp nicht im Binärformat für den Datenaustausch (mit Netzwerk, über Dateien, ..) genutzt werden. Andere Rechnersysteme/Programmiersprachen würde aufgrund der anderen Interpretation andere Zahlenwerte aus den übertragenen/gespeicherten Binärdaten auslesen!
<syntaxhighlight lang="C">
float var1;
write(file_hdl,&var1,sizeof var1); //Schreiben des Binärwertes
//in eine Datei
double var2;
send(socket_hdl,&var2,sizeof var2,0);//Senden des Binärwertes
//über ein Netzwerk
</syntaxhighlight>
Die Standard-C-Library bietet einige mathematische Funktionen wie <code>sin() / cos() / tan() / atan2() / sqrt() / pow() / exp()/…</code> an. Die Prototypen dieser Funktion sind in der Header-Datei <code>math.h</code> beschrieben, so dass diese bei Nutzung dieser Funktion zu inkludieren ist. Ergänzend ist die Shared Library libm.so über den Compilerschalter '-lm' einzubinden:
<syntaxhighlight lang="C">
#include <math.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
double sqrt(double);
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
printf("var1=%f var2=%f\n",var1,var2);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen basieren auf den Datentyp <code>double</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist vom Datentyp <code>double</code>. Die Prototypen sehen wie folgt aus:
<syntaxhighlight lang="C">
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double); //Wertebereich der Rückgabe von -PI/2..+PI/2
double atan2(double,double); //Wertebereich der Rückgabe von -Pi .. +PI
double sqrt(double);
double log(double);
</syntaxhighlight>
Über den Suffix f oder l im Funktionsnamen kann der zugrundeliegende Datentyp auf float (Suffix f) oder long double (Suffix l) geändert werden:
<syntaxhighlight lang="C">
float sinf(float);
long double sinl(long double);
</syntaxhighlight>
Ergänzend zu den Prototypen sind die gebräuchlichen Naturkonstanten in <code>math.h</code> definiert (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
M_E Value of e
M_LOG2E Value of log_2 e
M_LOG10E Value of log_10 e
M_LN2 Value of log_e 2
M_LN10 Value of log_e 10
M_PI Value of π
M_PI_2 Value of π/2
M_PI_4 Value of π/4
M_1_PI Value of 1/π
M_2_PI Value of 2/π
M_2_SQRTPI Value of 2/√π
M_SQRT2 Value of √2
M_SQRT1_2 Value of 1/√2
</syntaxhighlight>
Gleitkommazahlen können nicht nur Zahlenwerte, sondern auch Sonderwerte annehmen. Diese Sonderwerte sind ebenfalls in <code>math.h</code> beschrieben (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
INFINITY A constant expression of type float representing
positive or unsigned infinity, if available; else a
positive constant of type float that overflows at
translation time.
NAN A constant expression of type float representing a
quiet NaN. This macro is only defined if the
implementation supports quiet NaNs for the float type.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <math.h>
//Quelle: https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c
#ifdef NAN
#define NAN_STR "NAN is supported"
#else
#define NAN_STR "NAN is not supported"
#endif
#ifdef INFINITY
#define INFINITY_STR "INFINITY is supported"
#else
#define INFINITY_STR "INFINITY is not supported"
#endif
int main(int argc, char *argv[argc]) {
printf("%s\n%s\n",NAN_STR,INFINITY_STR);
double x=0.0;
double y=1/x;
printf("1/%e -> %e\n",x,y);
if(y==INFINITY)
printf("1) Initinity\n");
if(isinf(y)) //besser
printf("2) Initinity\n");
printf("%llx\n%llx\n\n",*(long long *)&y,INFINITY);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
double z=-(x/x);
printf("%e/%e -> %e\n",x,x,z);
if(z == NAN) //funktioniert nicht
printf("1) Not a Number\n");
if(isnan(z)) //besser
printf("2) Not a Number\n");
if(z != z)
printf("3) Not a Number\n");
printf("%llx\n%llx",*(long long *)&z,NAN);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
return 0;
} | execCompilerOptions=-lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit <code>fesetround()/fegetround()</code> kann gesetzt/gelesen werden, wie mit Ergebnissen umzugehen sind, die nicht exakt darstellbar sind. Mögliche Werte sind 'round to nearest' (default), 'round up', 'round down' und 'round toward zero'.
== Komplexe Zahlen ==
Nach dem Wikipedia Artikel {{w|komplexe Zahlen}} ''stellen komplexe Zahlen eine Erweiterung der reellen Zahlen dar. Ziel der Erweiterung ist es, algebraische Gleichungen wie x<sup>2</sup>+1=0 bzw. x<sup>2</sup>=-1 lösbar zu machen. ... Da die Quadrate aller reellen Zahlen größer oder gleich 0 sind, kann die Lösung der Gleichung x<sup>2</sup>=-1 keine reelle Zahl sein. Man braucht eine ganz neue Zahl, die man üblicherweise i nennt, mit der Eigenschaft i<sup>2</sup>=-1. Diese Zahl i wird als imaginäre Einheit bezeichnet.
Komplexe Zahlen werden nun als Summe a+b*i definiert, wobei a und b reelle Zahlen sind und i die oben definierte imaginäre Einheit ist.''<br />
Der Datentyp für komplexe Zahlen (erst ab C99 enthalten) beinhaltet folglich zwei Gleitkommazahlen, eine für den reelen Teil und eine für den imaginären Teil. Entsprechend den Gleitkommazahlen steht der komplexe Datentyp ebenfalls in drei unterschiedlichen Genauigkeiten zur Verfügung:
{| class="wikitable"
|-
! Datentype !! Speicherplatz
|-
| <code>float _Complex</code> || 2x4Byte
|-
| <code>double _Complex</code><br /><code>_Complex</code> || 2x8Byte
|-
| <code>long double _Complex</code> || 2x10Byte
|}
Wie auch beim Booleschen Datentyp ist in der Header-Datei <code>complex.h</code> für den einfacheren Umgang mit diesem Datentyp das Makro <code>complex</code> als Textersetzung für <code>_Complex</code> gesetzt.
Zur Darstellung von komplexen Konstanten wurde die Gleitkommakonstante um den Suffix i ergänzt. Durch Anhängen von i wird aus dem ansonsten rellen Teil der imaginäre Teil und damit aus der Gleitkommakonstante eine komplexe Gleitkommakonstante:
<syntaxhighlight lang="C">
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Normale Gleitkommavariablen werden als reellen Teil einer komplexen Zahl angesehen. Bei Operationen von Gleitkommazahlen und komplexen Zahlen wird der imaginäre Teil der Gleitkommazahl auf 0 gesetzt. Beim Zuweisen einer komplexen Zahl an eine Gleitkommazahl wird nur der reele Teil 'gelesen'.<br />
Soll eine Gleitkommavariablen zu einem imaginären Teil gewandelt werden, so muss diese bspw mit der Konstanten 1.0i multipliziert werden:
<syntaxhighlight lang="C">
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C-Library bietet diverse mathematische Funktionen wie csin(), ccos(), csqrt(), cpow() und ergänzend Umrechnungsfunktionen von Gleitkommazahlen in komplexe Zahlen (und umgedreht) wie creal(),cimag() ,cabs() für den Umgang mit komplexen Zahlen an:
<syntaxhighlight lang="C">
double _Complex csin(double _Complex);
double _Complex csqrt(double _Complex);
double creal(double _Complex);
double cimag(double _Complex);
</syntaxhighlight>
Zur Nutzung dieser Funktionen muss die Header-Datei <code>complex.h</code> inkludiert und ergänzend die Shared Library libm.so über den Compilerschalter '-lm' eingebunden werden.
<syntaxhighlight lang="C">
#include <complex.h>
//Math-Library mittels Linker-Command '-lm' einbinden
int main(int argc, char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen beruhen auf den Datentyp <code>double _Complex</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist <code>double _Complex</code> resp. <code>double</code> (bei den Umrechnungsfunktionen). Über den Suffix f und l im Funktionsnamen kann der zugrundeliegende Datentyp geändert werden:
<syntaxhighlight lang="C">
float crealf(float _Complex z);
long double creall(long double _Complex z);
</syntaxhighlight>
Hinweis:
* Der Datentyp <code>_Complex</code> und die dazugehörigen mathematischen Funktionen sind in der C-Spezifikation als optional gekennzeichnet.
== Generische mathematische Funktionen ==
In der <code>tgmath.h</code> Header Datei sind für die mathematischen Funktionen Makros enthalten, welche den Datentyp der Übergabeparameter bestimmen und basierend auf den Datentyp die dazugehörige mathematische Funktion aufrufen.
<code>tgmath.h</code> selbst inkludiert <code>math.h</code> und <code>complex.h</code>, so dass diese nicht weiter zu inkludieren sind.
Steht für den Übergabedatentyp keine passende Funktion zu Verfügung, so ist das Verhalten des Makros undefiniert (bspw. wenn ein komplexes Argument an eine Funktion übergeben wird, die nur für Gleitkommazahlen ausgelegt ist <code>ceil(1+2i);</code> )
Folgendes Regelwerk wird angewendet:
* Ist einer der Übergabeparameter imaginär, so ist die ausgewählte Funktion in der Spezifikation der Funktion beschrieben
* Ist einer der Übergabeparameter Komplexe, so wird die Komplexe Variante der Funktion aufgerufen, andernfalls die Gleitkomma Variante
* Ist einer der Übergabeparameter vom Datentyp <code>long double</code>, so wird die <code>long double</code> Variante, bei integer und double die <code>double</code> Variante und andernfalls die <code>float</code> Variante aufgerufen
Beispiel:
<syntaxhighlight lang="C">
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
int main(int argc,char *argv[]) {
foo(1l+1li,2.0l,3.0f,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=c
}} Öffnen im Compiler Explorer] }}
== Boolschescher Datentyp ==
Siehe [[Programmieren in C/C++: Grundlagen#Boolescher-Datentype/Operatoren|Grundlagen: Boolescher-Datentype/Operatoren]]
== void / unvollständiger Datentype ==
Der Datentyp <code>void</code> dient vorrangig dazu, nicht vorhandene Über- und Rückgabewerte von Funktionen anzuzeigen. Eine Variable vom Datentyp <code>void</code> kann nicht angelegt werden. Ein Zeiger vom Datentyp <code>void</code> ist möglich, kann aber nicht dereferenziert werden (siehe Kap. [[Programmieren in C/C++: Zeiger #Void-Zeiger| Zeiger:Void-Zeiger]])
<syntaxhighlight lang="C">
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* <code>sizeof(void)</code> ist nach der C-Spezifikation nicht erlaubt. Dennoch geben viele Compiler hier den Wert 1 zurück!
* Mit einem expliziten Cast auf den Datentyp void wird dem Compiler mitgeteilt, dass diese Variable in Gebrauch ist, der Wert in dieser Operation aber nicht genutzt wird. Hierüber kann die Compilerwarning 'unused Variable' unterbunden werden:
:<syntaxhighlight lang="C">
void func(int par1, int par2) {
int var1=12;
int var2=13;
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int par1, int par2) {
int var1=12;
int var2=13;
int var3=14; //Nicht genutzte Variable
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
printf("Genutzt\n");
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Datentypkonvertierung ==
Für das Rechnen/Vergleichen müssen beide Operatoren vom identischen Datentyp sein! Sind diese nicht identisch, so müssen die Datentypen 'angeglichen' werden. Dies kann einerseits ‚automatisch‘ mittels 'implizierter' Typumwandlung oder ‚manuell‘ mittels ‚expliziter' Typumwandlung erfolgen.<br />
Beim Zuweisungsoperator (inkl. Parameterzuweisung bei Funktionsaufrufen und Funktionsrückgabewerte mittels return) gilt dies ebenso, nur dass hier der Quelldatentyp an den Zieldatentyp angepasst werden muss. Die impliziten Regeln finden hier keine Anwendung.
Hinweis:
* Empfehlenswert ist, die Datentypen der Variablen so zu wählen, dass der Compiler keine implizite Typumwandlung tätigt. Kann dies nicht vermieden werden, so sollte die explizite Typumwandlung genutzt werden (um sich einen möglichen Datenverlust bewusst zu machen)
* Der Datentyp selbst sollte den möglichen Wertebereich der Variablen entsprechen und nicht unnötig groß gewählt werden
:<syntaxhighlight lang="C">
Datentyp zur Speicherung der Stundenzeit:
Wertebereich: 0 ... 23 -> unsigned char
Datentyp zur Speicherung einer Jahreszahl:
Wertebereich: 2000 v.C. ... 4000 n.C -> signed short
Datentyp zur Speicherung einer Temperatur:
Wertebreich: -273,0°C ... 2000,0°C -> float
</syntaxhighlight>
=== Implizite Typumwandlung ===
Diese Regeln wurden so aufgestellt, dass dabei stets ein Datentyp in einen anderen Datentyp mit höherem Wertigkeit umgewandelt wird [C11 6.3.1.8] und [Harbison: S 199]. Bei Ganzzahlen gilt ergänzend folgende (Rangordnung [C11 6.3.1.1]: long long, long, int, short,char,_Bool):
{| class="wikitable"
|-
! Regel/<br />Priorität !! If either operand<br />has Type !! And the other operand<br />has Type !! Converts both to
|-
| 1 (hoch) || long double || any real type || long double
|-
| 2 || double || any real type || double
|-
| 3 || float || any real type || float
|-
| 4 || any unsigned type || any unsigned type || the unsigned type<br/>with the greater rank
|-
| 5 || any signed type || any signed type || the signed type<br/>with the greater rank
|-
| 6 || any unsigned type || a signed type with a equal<br/> or less rank || the unsigned type
|-
| 7 || any unsigned type || a signed type that can represent<br/>all of values of the unsigned type || the signed type
|-
| 8 (niedrig) || any other type || any other type || both operands are<br/> converted to the unsigned <br/>integer type corresponding<br/> to the type of the operand<br/> with the signed<br/> integer type
|}
Ergänzend gilt das Regelwerk zu Integer Promotion, welche Datentypen kleiner als <code>signed int</code> zu <code>int</code> und kleiner als <code>unsigned int</code> zu <code>unsigned int</code> konvertiert (Compiler kann hiervon abweichen, wenn sichergestellt ist, dass kein Datenverlust eintritt).
Regel 6 und 7 sind der nicht klar definierten Bitbreite der ganzzahligen Datentypen geschuldet und versuchen, Konvertierungsverluste zu vermeiden. Sie lesen sich zunächst kryptisch, lassen sich aber einfach am folgenden Beispiel erklären:
<syntaxhighlight lang="C">
Operand 1: unsigned int (hier 32-Bit)
Operand 2: long (hier 32-Bit / 64-Bit)
</syntaxhighlight>
* Im Fall, dass der Datentyp <code>long</code> 64-Bit breit ist, kann dieser problemlos die vorzeichenlose 32-Bit Zahl ohne Konvertierungsverluste repräsentieren, so dass der Zieltype <code>signed long</code> ist (Regel 7)
* Im Fall, dass der Datentyp <code>long</code> 32-Bit breit ist, kann dieser mit seinen Wertebereich von -2.147.483.648 bis +2.147.483.647 nicht den vorzeichenlosen Zahlenbereich von 0…4.294.967.295 darstellen. In diesem Fall hat der unsigned Datentyp einen höheren Rang, so dass als Zieltyp <code>unsigend long</code> gewählt wird (Regel 6)
'''Regel 6 bedeutet die Gefahr eines Konvertierungsverlustes, dessen man sich bewusst sein sollte!''' Diese tritt insb. dann in Kraft, wenn ein Operand vom Typ <code>unsigned long long</code> ist (64-Bit).
Beispiele von impliziten Typumwandlungen:
<syntaxhighlight lang="C">
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
vari=5.0*(int)sin(vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ Wikibooks Formatierung schlägt hier fehlt
double sin(double);
int main(int argc,char *argv[]) {
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
printf("vars=%hd\n",vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
printf("vars=%hd\n",vars);
vari=5.0*(int)sin(vars);
printf("vari=%d\n",vari);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
printf("vari=%d\n",vari);
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im CompilerExplorer können sie sich die impliziten Typumwandlungen anzeigen lassen. Dazu gehen sie bitte wie folgt vor:
:* Im Source-Fenster mit '+Add new' ein Compiler Fenster öffnen
:* Im Compiler-Fenster mit '+Add new' ein 'GCC Tree/RTL' Fenster öffnen
:* Im GCC Tree/RTL-Fenster unter 'Select a pass…' 'original tree' auswählen
Um implizite Typumwandlung besser erkennen zu können, wird oftmals bei Variablennamen die ''' 'Ungarische Notation' ''' angewendet (siehe {{w|Ungarische Notation}}). Aufgrund der besonderen Namensgebung kann der Programmierer ohne großen Aufwand frühzeitig mögliche Typkonflikte erkennen. Der Variablenname setzt sich wie folgt zusammen:
<syntaxhighlight lang="C">
{Präfix}{Datentyp}{Bezeichner}
</syntaxhighlight>
:'''Präfix''': p->Pointer h->Handle i->index c->count f->flag rg->Array
:'''Datentyp''': ch->Character st->string w->word b->byte…
:'''Bezeichner''': Zum Binden der Variable an eine konkrete Aufgabe (keine Unterstriche).
:Bezeichner ist optional, wenn aus Präfix und Datentyp die 'Aufgabe' der Variable direkt sichtbar ist
Beispiele:
<syntaxhighlight lang="C">
char rgchtemp[10]; //Array (Range) vom Datentyp character
int ich; //Index zum Adressieren eines Arrays vom Datentyp
//character
</syntaxhighlight>
=== Explizite Typumwandlung ===
Programmierer erzwingt durch explizite Typumwandlung (auch CASTen genannt) eine Umwandlung eines Datentyps in einen anderen. Dazu wird der Zieldatentyp in runden Klammern vor Quelldatentype geschrieben:
<syntaxhighlight lang="C">
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
In der Rangfolge der Operatoren steht der Cast-Operator unterhalb von bspw. Funktionsaufrufen, Arrayzugriffen aber auch der Dereferenzierung:
{| class="wikitable"
|-
! Priorität !! Symbol !! Assoziativität !! Bedeutung
|-
| 15 || ... || ... || ...
|-
| 14
||
++/-- (Präfix)<br />
+/- (Vorzeichen) <br />
<nowiki>!</nowiki>/~ <br />
&<br />
<nowiki>*</nowiki><br />
(TYP)<br />
...
|| R-L
||
Präfix-Inkrement/Dekrement<br />
Vorzeichen<br />
Logisches/Bitweises Nicht<br />
Adresse<br />
Zeigerdereferenzierung<br />
'''Typumwandlung (Explizites Cast)'''<br />
...
|-
| 13
||
* / %
|| L-R
|| Multiplikation/Division/Modulo
|-
| 12 || ... || ... || ...
|}
Im Zweifel gilt auch hier, den zu wandelnden Typ ergänzend zu klammern.
Hinweis:
* Bedenke, dass die explizite Typumwandlung so aufgestellt sein sollte, dass der Zieldatentyp dem notwendigen Datentyp entspricht. Andernfalls wendet der Compiler ergänzend eine implizierte Typumwandlung an:
:<syntaxhighlight lang="C">
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Mittels expliziter Typumwandlung können Ganzzahl nach Gleitkommazahlen (und andersherum) und Zeiger in einen anderen Zeiger und auf andere Datentypen gewandelt werden. Eine Konvertierung von Arrays, Strukturen, Unions zu anderen Datentypen als sich selbst ist weiterhin nicht möglich:
<syntaxhighlight lang="C">
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei den möglichen Konvertierungen sollte Folgendes berücksichtigt werden:
* '''Vorzeichenlose Ganzzahl''' → '''Vorzeichenlose Ganzzahl''': Wenn der Zieldatentyp größer ist, wird die Zahl durch führende '0' erweitert. Wenn der Zieldatentyp kleiner ist, werde die zu vielen Bitstellen abgeschnitten/verworfen (ggf. Datenverlust)
* '''Vorzeichenbehaftete Ganzzahl''' → '''Vorzeichenbehaftete Ganzzahl''': Wenn der Zieldatentyp größer ist, wird vorzeichenrichtig erweitertet (d.h. das Auffüllen erfolgt auf Basis des Vorzeichens). Wenn der Zieldatentyp kleiner ist, werden auch hier die zu vielen Bits abgeschnitten/verworfen (Vorsicht: Negative Zahlen können dabei in positive Zahlen gewandelt werden)
* '''Gleitkommazahl''' → '''Gleitkommazahl''': Hier wird vereinfacht ausgedrückt sowohl die Mantisse als auch der Exponent einzeln kopiert. Wenn die Zielmantisse kleiner ist, gehen 'Nachkommastellen' verloren. Wenn der Quellexponent einen größeren Wert beinhaltet, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf Unendlich gesetzt. Umgedreht, wenn der Quellexponent kleiner ist, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf 0 gesetzt
* '''Ganzzahl''' → '''Gleitkommazahl''': Hier wird, vereinfacht ausgedrückt, die Ganzzahl in die Mantisse kopiert. Um Datenverluste zu vermeiden, sollte die Bitbreite der Zielmantisse größer gleich der Bitbreite der Ganzzahl sein
* '''Gleitkommazahl''' → '''Ganzzahl''': Im Wesentlichen wird hier die Mantisse übernommen, so dass hier die Bitbreite des Zieldatentyps mindestens der Bitbreite der Mantisse sein sollte
* '''Zeiger''' ↔ '''Ganzzahl''': Die Konvertierung ist möglich. Da bei 64-Bit Systemen der Zeiger 64-Bit und Integer 32-Bit breit ist, meckert ggf. der Compiler. Für solche Fälle existieren die Datentypen 'intptr_t' und 'uintptr_t', über welche sichergestellt ist, dass ein Zeiger in einen Ganzzahldatentyp gespeichert werden kann!
* '''Zeiger''' ↔ '''Gleitkommazahl''': Diese Konvertierung ist nicht möglich!
* '''Struktur/Union''' ↔ '''Ganzzahl/Gleitkommazahl''': Diese Konvertierung ist nicht möglich. Es können nur einzelnen Strukturelemente konvertiert werden, sofern diese vom Typ Ganzzahl/Gleitkommazahl sind
* '''Array''' ↔ '''Ganzzahl/Gleitkommazahl''': Der Arrayname entspricht einen Zeiger, so dass hier ein Zeiger in eine Ganzzahl oder umgedreht konvertiert wird (siehe Zeiger ↔ Ganzzahl)
In C++ gibt es weitere CAST-Operatoren, auf welche hier derzeit noch nicht weiter eingegangen wird!
* Static_cast (Entspricht dem Expliziten Cast)
* Const_cast
* Dynamic_cast
* Reinterpret_cast
== Verbundtyp Struktur/Klasse (nur C++) ==
Nach dem Wikipedia Artikel {{w|Verbund (Datentyp)}} ist ''ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten können wiederum Verbünde enthalten, wodurch auch komplexe Datenstrukturen definiert werden können.<br />
Für jedes Strukturelement wird Speicher reserviert. Alle Strukturelemente liegen hintereinander im Speicher.''
<code>Syntax: struct Strukturname<sub>Opt</sub> {Datentype Strukturelementname; … }<sub>OPT</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Verbund entspricht einer Java Klasse mit dem Unterschied zu C (nicht C++) , dass ein Verbund keine Methoden beinhaltet und keine Zugriffsbeschränkung für die Attribute gesetzt werden können.
Der Syntax erlaubt es, gleichermaßen einen Datentyp (über Strukturname) zu definieren und Variablen von diesem Datentyp (über Variablenliste) anzulegen. Da beide Elemente optional sind, ergeben sich diverse Kombinationsmöglichkeiten:
* Nur Strukturname → Definition eines neuen Datentyps
:<syntaxhighlight lang="C">
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
var1.y=2;
var1.z=1;
printf("var1.x=%d var1.y=%d var1.z=%d\n",var1.x,var1.y,var1.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C: Der Strukturname ist nur mit dem vorangestellten <code>struct</code> gültig. Der Strukturname stellt somit einen eigenen Namensraum, getrennt von dem Namensraum der Variablen/Funktionen, dar. Daher kann ein Strukturname identisch zu einem Variablennamen sein:
:<syntaxhighlight lang="C">
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
xyz2.x=xyz2.y=xyz2.z=1;
printf("xyz2.x=%d xyz2.y=%d xyz2.z=%d\n",xyz2.x,xyz2.y,xyz2.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C++: Der Strukturname ist sowohl mit als auch ohne dem vorangestellten <code>struct</code> gültig. Auch hier stellt der Strukturname einen eigenen Namensraum dar, der jedoch eine niedrigere Priorität als der der Variablen hat:
:<syntaxhighlight lang="C++">
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz beschreibt hier die Variable
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz3 beschreibt hier die Variable
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
* Nur Variablenliste → Definition einer/mehrerer Variablen von einem 'unnamed' Datentyp
:<syntaxhighlight lang="C">
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Angewendet wird die Schreibweise gerne, wenn eine Struktur innerhalb einer Struktur definiert wird und die innere Struktur zur besseren Strukturierung dient:
:<syntaxhighlight lang="C">
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Strukturname und Variablenliste → Definition eines Datentyps und Definition von Variablen. D.h. es können im Nachhinein weitere Variablen von diesem Datentyp angelegt und die hier angelegten Variablen genutzt werden.
:<syntaxhighlight lang="C">
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y; //Nutzung der Variablen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y=1; //Nutzung der Variablen
(void)var1;
(void)ptr1;
(void)ptr2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Kein Strukturname und keine Variablenliste → "Anonymous Struct", d.h. Definition eines 'unnamed' Datentyps, von der ergänzend keine Variable angelegt wird. Anonymus Structs sind nur innerhalb von Strukturen erlaubt/einsetzbar. Hier dienen sie der besseren Strukturierung und ersparen dem Programmierer die Benennung des normalerweise notwendigen Strukturelementes:
:<syntaxhighlight lang="C">
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
(void)var;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Eine Struktur (und auch eine C++ Klasse) wird mit einem Semikolon abgeschlossen
* Eine alternative Beschreibung zu Strukturen finden sie in [https://abstractexpr.com/2023/06/29/structures-in-c-from-basics-to-memory-alignment/ Structures in C: From Basics to Memory Alignment]
=== Strukturelement ===
Innerhalb der Struktur können beliebige Strukturelemente von beliebigen Datentypen angelegt werden. Einzige Voraussetzung, der Datentyp des anzulegenden Strukturelementes muss zuvor definiert worden sein. Ergänzend kann der neue Datentyp auch in der Struktur selbst definiert werden, sofern mit der Definition des Datentyps auch eine Variable angelegt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zugriff auf Strukturelemente ===
Die Programmiersprachen C/C++ unterscheiden zwei 'Zugriffsarten' auf die Strukturelemente, abhängig vom zugrundeliegenden Datentyp des linken Operanden::
* Handelt es sich beim linken Operanden um eine (struct)Variablen, so erfolgt der Zugriff über den Punkt-Operator <code>.</code>:
:<syntaxhighlight lang="C">
struct {
int a,b,c;
} abc;
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct {
int a,b,c;
} abc;
int main(int argc,char *argv[]) {
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c=12;
printf("abc.a=%d abc.b=%d abc.c=%d\n",abc.a,abc.b,abc.c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Handelt es sich beim linken Operanden um einen Zeiger auf eine (struct)Variable, so erfolgt der Zugriff über den Zeiger-Operator <code>-></code>:
:<syntaxhighlight lang="C">
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
int main(int argc,char *argv[]) {
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Werden innerhalb von Strukturen weitere Strukturen und Zeiger auf Strukturen angelegt, so müssen diese Regeln auf jedes innere Strukturelement einzeln angewendet werden:
<syntaxhighlight lang="C">
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
int main(int argc,char *argv[]) {
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Strukturen ===
Mit dem Anlegen einer Strukturvariablen kann diese auch initialisiert werden. Eine 'Vorbelegung' der Strukturelemente bei der Definition der Struktur ist in C nicht möglich.<br />
Die Initialisierung erfolgt über eine Initialisierungsliste (siehe Kap [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]). Innerhalb der Initialisierungsliste stehen die Initialisierungswerte entweder in der Reihenfolge der Datentypdefinition oder werden explizit mit dem ‘.‘ Operator angesprochen (designated initializers). Werden einzelne Strukturelemente ausgelassen, so werden diese mit 0 initialisiert:
<syntaxhighlight lang="C">
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
int main(int argc,char *argv[]) {
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
printf("v1.a=%d v1.b=%d v1.str[0]=%d\n",v1.a,v1.b,v1.str[0]);
printf("v2.a=%d v2.b=%d v2.str[0]=%d\n",v2.a,v2.b,v2.str[0]);
printf("v3.a=%d v3.b=%d v3.str[0]=%d\n",v3.a,v3.b,v3.str[0]);
printf("v4.a=%d v4.b=%d v4.str[0]=%d\n",v4.a,v4.b,v4.str[0]);
printf("v5.a=%d v5.b=%d v5.str[0]=%d\n",v5.a,v5.b,v5.str[0]);
printf("v6.a=%d v6.b=%d v6.str[0]=%d\n",v6.a,v6.b,v6.str[0]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Initialisierung einer Struktur über nachfolgende Art bewirkt etwas anderes, als erwartet:
<syntaxhighlight lang="C">
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
printf("var.a=%d var.b=%d var.c=%d\n",var.a,var.b,var.c);
//Gerne mal den Compiler Wechseln
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der Initialisierungsliste wird über 'var.b=12' und 'var.c=3' die zu diesem Zeitpunkt noch nicht initialisierte Variable var die Elemente b und c initialisiert. Mit dem Werten der Initialisierungsliste (hier {12,3}) wird nachfolgend die Variable erneut initialisiert und 12 dem Strukturelement a und 3 dem Strukturelement b zugewiesen. Abhängig vom Compiler ist das Strukturelement c entweder 3 oder 0.
Bei verschachtelten Strukturen muss entsprechend obiger Aussage für jede innere Struktur eine eigene Initialisierungsliste erstellt werden. Die inneren Initialisierungslisten können entfallen, was jedoch nicht empfohlen wird und ergänzend vom Compiler bei '-Wall' als Warning angemerkt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8}}
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={{.x=5,.y=6},{7,8}},
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8} }
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={ {.x=5,.y=6},{7,8} },
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
int main(int argc,char *argv[]) {
printf("v1.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v1.a, v1.b, v1.xy.x, v1.xy.y, v1.arr[0].x, v1.arr[0].y, v1.arr[1].x, v1.arr[1].y );
printf("v2.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v2.a, v2.b, v2.xy.x, v2.xy.y, v2.arr[0].x, v2.arr[0].y, v2.arr[1].x, v2.arr[1].y );
printf("v3.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v3.a, v3.b, v3.xy.x, v3.xy.y, v3.arr[0].x, v3.arr[0].y, v3.arr[1].x, v3.arr[1].y );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zuweisen/Kopieren von Strukturen ===
Strukturen werden über den Namen als 'ganzes' angesprochen, so dass eine Zuweisung als 'ganzes' möglich ist. Bei bspw. einer 12-Byte großen Struktur werden bei Nutzung der Variable die gesamten 12-Byte gelesen/geändert!
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1,var2;
var1=var2; //12-Bytes kopiert
//--> entspricht memcpy(&var1,&var2,sizeof(xyz));
</syntaxhighlight>
Die Zuweisung als 'ganzes' gilt auch bei der Parameterübergabe und -rückgabe von Funktionen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;};
//Funktionsdefinition
struct xyz function(struct xyz par) {
return (struct xyz){par.z,par.y,par.x};
}
//Funktionsaufruf
struct xyz var=function((struct xyz){1,2,3});
//Mit dem Aufruf der Funktion werden 12-Bytes in die Variable par kopiert
//Mit dem Ende der Funktion werden 12-Bytes in die Variable var kopiert
</syntaxhighlight>
Bedenke, dass bei großen Strukturen das Kopieren Rechenzeit benötigt und folglich vermieden werden sollte! Alternativ sollten Zeiger auf Strukturen über- und zurückgeben werden.
Über Compound Literal (siehe Kap. [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]) kann einer Strukturvariablen als 'ganzes' einen neuen Wert zugewiesen werden:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
var1={.a=7}; //KO, Initialisierungsliste kann hier nicht
//angewendet werden
var1=(struct abc){.a=7}; //Wertezuweisung über Compound Literal möglich
</syntaxhighlight>
Formel gesehen entspricht das Compound Literal einer 'unnamed Variable', die als erstes angelegt und initialisiert wird. Der Inhalt dieser Variablen wird im Anschluss der eigentlichen Variable zugewiesen!
=== Prototyp / Deklaration einer Struktur ===
Soll der Datentyp einer Struktur genutzt werden, der erst an weiter hinten liegenden Stellen im Programm definiert wird, so ist wie bei Variablen/Funktionen ein Prototyp/Deklaration notwendig:
<syntaxhighlight lang="C">
struct abc; //Prototyp der Struktur abc
...
struct abc { int a,b,c;}; //Definition der Struktur abc
</syntaxhighlight>
Die Deklaration sagt einzig aus, dass die Struktur später definiert wird, beinhaltet aber nicht die Strukturelemente. Folglich kann auf Basis dieses Prototyps keine Variable definiert werden, sondern einzig ein Zeiger auf solche eine Struktur:
<syntaxhighlight lang="C">
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Anwendung:
* Struktur, welche auf sich selbst verweist (Verkettete Liste)
:<syntaxhighlight lang="C">
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
int main(int argc,char *argv[]) {
struct vl *head=NULL;
struct vl a={.daten="Ele a"};
struct vl b={.daten="Element b"};
struct vl c={.daten="c-Eleent"};
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL; //Zur Kennzeichnung des letzten Elementes
for(struct vl*ptr=head;ptr;ptr=ptr->next)
printf("'%s'\n",ptr->daten);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Entsprechend der objektorientierten Programmierung, wenn alle Attribute der Klasse private sind:
:{| class="wikitable"
|-
! !! class.h
|-
|
||<syntaxhighlight lang="C">
struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
</syntaxhighlight>
|-
! main.c !! class.c
|-
|<syntaxhighlight lang="C">
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
..
//Kein Zugriff auf
//Strukturelemente möglich
return 0;
}
</syntaxhighlight>
||<syntaxhighlight lang="C">
#include "class.h"
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *)
malloc(sizeof(struct class));
this->attr1=10;
*me=this;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
//..
//Kein Zugriff auf Strukturelemente möglich
return 0;
}
|class_h=struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
|class_c=#include "class.h"
#include <stdlib.h> //fuer malloc()
#include <stdio.h> //fuer printf()
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *) malloc(sizeof(struct class));
printf("konstructor called\n");
this->attr1=10;
*me=this;
}
| execCompilerOptions=-Wall class.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Vergleichen von Strukturen ===
Ein Vergleich von Strukturen über den direkten Weg ist nicht möglich. Vielmehr müssen die Strukturelemente händisch verglichen werden:
<syntaxhighlight lang="C">
struct xyz {int inx,y,z;} var1,var2;
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} var1={1,2,3},var2={1,2,3};
int main(int argc,char *argv[]) {
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
printf("Strukturelemente von var1 und var2 identisch\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis
* Bei Rechnerarchitekturen mit nicht ausgerichteter Speicherausrichtung (Alignment) kann ergänzend ein Vergleich über memcmp() erfolgen
=== Speicherplatzbedarf einer Struktur ===
Für jedes Strukturelement wird Speicher entsprechend der Größe des Datentyps reserviert. Der Speicherplatzbedarf der Gesamtstruktur ergibt sich aus der Summe der Strukturelemente:
<syntaxhighlight lang="C">
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
sizeof(var1) //ergibt 12
sizeof(struct xyz) //ergibt 12
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
int main(int argc,char *argv[]) {
printf("sizeof(var1)=%zu Bytes\n",sizeof(var1));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Ermittlung der tatsächlichen Speichergröße einer Struktur erfolgt über den sizeof-Operator:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;} a;
sizeof(a); //=12 OK
sizeof(a.x); //=4 OK
sizeof(struct xyz); //=12 OK
sizeof(struct xyz.x); // KO
//Ist dies dennoch notwendig, so kann dies über den Umweg eines Zeigers
//erfolgen:
sizeof(((struct xyz *)0)->x); //=4 OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x,y,z;
} a;
int main(int argc,char *argv[]) {
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
printf("sizeof(a.x)=%zu Bytes\n",sizeof(a.x));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
printf("sizeof(struct xyz.x)=%zu Bytes\n",sizeof(struct xyz.x));
printf("sizeof(((struct xyz *)0)->x)=%zu Bytes\n",sizeof(((struct xyz *)0)->x));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei Rechnerarchitekturen mit ausgerichteter Speicherausrichtung (Alignment) (siehe {{w|Speicherausrichtung}}) kann der tatsächliche Speicherbedarf größer sein! Hier fügt der Compiler ggf. zwischen den Strukturelemente Füllbytes (Padding Bytes) ein
* Die Reihenfolge der Strukturelemente wird vom Compiler nicht geändert. D.h. die Zuordnung der Speicherstellen zu den Strukturelementen erfolgt in der Definitionsreihenfolge
=== Interne Organisation ===
Compilerintern werden die Strukturelemente über einen Offset dargestellt. Das erste Strukturelement bekommt dabei immer den Offset 0 zugewiesen. Das nachfolgende Element bekommt als Offset die Größe des Datentyps des vorherigen Elementes zugewiesen. Usw.. <br />
Der Compiler setzt den Zugriff auf ein Strukturelement einer (Struktur)Variablen so um, dass er zunächst die Startadresse der Variablen holt und zu dieser den Offset des Strukturelementes addiert. Die Anzahl der zu lesenden/schreiben Bytes ergibt sich aus dem Datentyp des Strukturelementes:
<syntaxhighlight lang="C">
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1; //(Beispielhaft soll var1 die Speicheradressen
//0x100..0x10B belegen). Der Zugriff auf
//die Variable erfolgt immer über die Startadresse
var1.x=7; //Zugriff auf Speicheradresse 0x100+0 (Offset)
var1.y=8; //Zugriff auf Speicheradresse 0x100+4 (Offset)
var1.z=9; //Zugriff auf Speicheradresse 0x100+8 (Offset)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1;
int main(int argc,char *argv[]) {
//Zugriff siehe Compiler
var1.x=7; //mov DWORD PTR var[rip+0],7
var1.y=8; //mov DWORD PTR var[rip+4],7
var1.z=9; //mov DWORD PTR var[rip+8],7
return 0;
} | execCompilerOptions=-Wall|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Offset eines Strukturelementes kann mit dem offsetof-Operator ermittelt werden:
<code>Syntax: offsetof(type,Strukturelement)</code>
Wie beim sizeof-Operator gilt der offsetof-Operator als Konstantenausdruck und der Rückgabedatentyp ist <code>size_t</code>. Zur Nutzung des Operators muss die Header-Datei 'stddef.h' inkludiert werden:
<syntaxhighlight lang="C">
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var1;
offsetof(struct xyz,z) --> 8
offsetof(var1,z) --> KO: Es wird ein Datentyp und
keine Variable erwartet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz{
int x,y,z;
} var1;
int main(int argc,char *argv[]) {
printf("offsetof(struct xyz,x)=%zu Bytes\n",offsetof(struct xyz,x));
printf("offsetof(struct xyz,y)=%zu Bytes\n",offsetof(struct xyz,y));
printf("offsetof(struct xyz,z)=%zu Bytes\n",offsetof(struct xyz,z));
printf("offsetof(var1,z)=%zu Bytes\n",offsetof(var1,z));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Unter Nutzung des offsetof-Operators kann man bei gegebener Adresse eines Strukturelementes auf die Startadresse der zugrundeliegenden Struktur zurückrechnen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1;
int *ptri=&var1.y;
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var={1,2,3};
int *ptri=&var.y;
int main(int argc,char *argv[]) {
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
printf("ptrxyz->x=%d ptrxyz->y=%d ptrxyz->z=%d",ptrxyz->x,ptrxyz->y,ptrxyz->z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dazu wird von der Startadresse des Strukturelementes der Offset abgezogen. Da der offsetof-Operator den Abstand in Bytes zurückgibt, muss der Pointer auf das Strukturelement zuvor ebenfalls in ein 'Byte'-Zeiger gewandelt werden.
Im Linux kernel wird diese Subtraktion über das container_of Makro realisiert:
<syntaxhighlight lang="C">
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
</syntaxhighlight>
Dieses Makro ermöglicht es, bei gegeben Startadresse eines Strukturelementes die Startadresse der zugrundeliegenden Struktur zu berechnen. Anwendung findet dieses Makro bspw. in:
* der objektorientierten Programmierung, um ausgehend vom gegebenen Parent-Element die Startadresse des Child-Elementes zu berechnen:
:<syntaxhighlight lang="C">
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
..
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
printf("parent.attr1=%d parent.att2=%d\n",me->attr1,me->attr2);
printf("child.attr1=%d\n",child->attr1);
}
int main(int argc,char *argv[]) {
struct child obj1;
obj1.attr1=1;
obj1.parent.attr1=2;
obj1.parent.attr2=3;
parent_methode(&obj1.parent);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei verketteten Listen, wenn das Next-Element im Datensatz selbst eingearbeitet ist:
:<syntaxhighlight lang="C">
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(PTR, TYPE, MEMBER) \
((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
vl_t head={NULL};
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
int main(int argc,char *argv[]) {
daten_t obj1={.daten1=1,.daten2=2};
daten_t obj2={.daten1=3,.daten2=4};
vl_addfront(&obj1);
vl_addfront(&obj2);
daten_t *ret=vl_getfront();
printf("%d %d\n",ret->daten1,ret->daten2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Explizites Cast ===
Eine Struktur kann nicht in einen anderen Datentyp und damit auch nicht in einen anderen Strukturdatentyp mit identischen Strukturelementen konvertiert werden:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} xyz;
struct abc {int a,b,c;} abc;
int var;
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} xyz;
struct abc {
int a,b,c;
} abc;
int var;
int main(int argc,char *argv[]) {
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Incomplete Array ===
Das letzte Element einer Struktur kann ein Array ohne Angabe einer Dimensionsgröße sein (Incomplete Array/Flexible Array Member). Bei der Definition einer Variablen von solch einem Datentyp wird in der Tat kein Speicher für das letzte Element reserviert, so dass dies 'händisch' erfolgen muss. Auf das Array kann ungeachtet dessen unproblematisch zugegriffen werden:
<syntaxhighlight lang="C">
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert
//wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert wurde
//Zur Darstellung dieses Sachverhaltes wurde der Sanitizer
//über den Compilerschalter -fsanitize=address aktiviert
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Speicherplatzreservierung für das incomplete Array kann auf zwei verschiedene Arten erfolgen:
* Speicherplatzreservierung für das Incomplete Array über Variableninitialisierung (nur GCC-C und nur im Falle einer globalen Variablen)
:<syntaxhighlight lang="C">
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
int main(int argc,char *argv[]) {
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(ele1)=%zu Bytes\n",sizeof(ele1));
printf("sizeof(ele2)=%zu Bytes\n",sizeof(ele2));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Speicherplatzreservierung für das Incomplete Array über malloc
:<syntaxhighlight lang="C">
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
if(b==NULL)
return printf("malloc failed\n"),1;
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
//zum Beweis Sanitizer über -fsanitize=address eingebunden
free(b);
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Das Incomplete Array bietet sich überall dort an, wo Daten gespeichert werden sollen, deren Größe sich erst zur Laufzeit ergibt.
=== Anwendung ===
Die Nutzung des Datentyps struct empfiehlt sich an vielen Stellen:
* Zusammengehörende Daten zu Kapseln (entsprechend der objektorientierten Programmierung
* Verkette Listen
* Aufgrund der Typsicherheit zur Darstellung von sicherheitskritischen Aufgaben
Siehe Übungsbereich!
=== C++ ===
Der wesentliche Syntax von Strukturen wurde in C++ übernommen. D.h.:
* das abschließende Semikolon
* der Zugriff auf die Strukturelemente
* Speicherplatzreservierung
* die Definition von Variablen mit der Definition des Datentyps
* ...
Ergänzend wurde in C++ der Datentyp class eingeführt, der weitestgehend identisch zu struct ist. Geändert/Hinzugefügt wurden folgende Sachverhalte:
* Classen/Strukturen können Methoden haben
* Operatoren (Zuweisungsoperator, Addition, ...) können überladen werden
* Alle Strukturelemente (und Methoden) einer struct sind per default public
* Alle Attribute (und Methoden) einer Class sind per default private
* Zur Nutzung des Datentyps ist das führende struct nicht notwendig (dies bedingt dann auch, dass der Strukturdatentyp kein separater Namensraum ist)
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var_xyz;
</syntaxhighlight>
* Initialisierungswerte für Strukturelemente und Klassenattribute bei der Datentypbeschreibung angegeben werden können:
:<syntaxhighlight lang="C++">
struct xyz {
int x=3;
int y=1;
int z;
};
xyz var={7}; //var.x=7 var.y=1 var.z=0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x=3;
int y=1;
int z;
};
int main(int argc,char *argv[]) {
xyz var={7}; //var.x=7 var.y=1 var.z=0
printf("var.x=%d var.y=%d var.z=%d\n",var.x,var.y,var.z);
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In C++ kann eine Struktur ebenfalls über 'designated initializers' initialisiert werden. Jedoch muss die Reihenfolge der Initialisierungselement identisch zur Datentypdefinition sein. Auch ist keine Doppeltbenennung erlaubt:
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x,y,z;
};
int main(int argc,char *argv[]) {
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
(void)var1;
(void)var2;
(void)var3;
(void)var4;
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Union ==
Ähnlich wie eine Struktur ist ein Union ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wird. Bei sog. Union beginnen jedoch alle Komponenten nicht wie bei Strukturen an nacheinander folgenden Speicheradressen, sondern an der identischen Speicheradresse, d.h. ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union kann folglich zu einem Zeitpunkt nur ein Element enthalten. Der benötigte Speicherplatz ergibt sich aus der größten Komponente.
<code>Syntax: union Unionname<sub>Opt</sub> {Datentyp Variablenname; …}<sub>Opt</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Schutz/Zugriffssteuerung der Unionelemente ist nicht vorhanden. Es kann in beliebiger Reihenfolge auf die einzelnen Elemente zugegriffen werden.
Die Anwendung ist identisch wie bei Strukturen, so dass im Folgenden nur die Abweichungen zu den Strukturen beschrieben werden.
=== Speicherplatzbedarf und interne Struktur einer Union ===
Die Größe der Union ergibt sich aus dem größtem Unionelement. Alle Unionelemente überlappen sich, so dass der Offset zum Basiselement 0 ist:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird ein kleineres Unionelement belegt und im Anschluss ein größeres Unionelement gelesen, so ist der Inhalt der durch das kleinere Element nicht beschriebenen Speicherstellen undefiniert:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc.a=0x11;
printf("%08x",abc.c);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
};
void foo(int var) {
int lok=var;
printf("Foo(%#08x) called\n",lok);
}
void bar(void) {
union abc abc;
abc.a=0x11;
printf("abc.a=%#02x\n",abc.a);
printf("abc.c=%#08x\n",abc.c);
}
int main(int argc,char *argv[]) {
//Zur Darstellung des Phänomens muss
//erstmal der Stack mit Daten belegt werden!
foo(0x12345678);
bar();
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Union ===
Bei einer Union kann nur ein Element initialisiert werden, d.h. die Initialisierungsliste kann nur einen Wert beinhalten. Ohne explizite Benennung des Unionelementes in der Initialisierungsliste wird das erste Element aus der Datentypbeschreibung initialisiert. Mit expliziter Benennung mittels 'designated initializers' können auch andere Elemente initialisiert werden:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Anwendung ===
Mittels des Datentyps union können diverse Anwendungsfälle abgedeckt werden:
* Über Union lassen sich größere Datentypen in kleinere Datentypen unterteilen, um z.B. einzelne Bytes zu extrahieren:
<syntaxhighlight lang="C">
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union floatu var={1.234};
printf("%f\n",var.var); //Darstellung des Float-Wertes
printf("%x\n",var.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var.byte[0],var.byte[1],var.byte[2],var.byte[3]);
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
union longlong var2={0x123456789ABCDEFULL};
printf("%llx\n",var2.ll);
printf("%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
int main(int argc,char *argv[]) {
union floatu var1={1.234};
printf("var1.var=%f\n",var1.var); //Darstellung des Float-Wertes
printf("var1.hex=%x\n",var1.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("var1.byte[0..3]=%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var1.byte[0],var1.byte[1],var1.byte[2],var1.byte[3]);
union longlong var2={0x123456789ABCDEFULL};
printf("var2.ll=%llx\n",var2.ll);
printf("var2.i[0..1]=%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Ein weiterer Anwendungsfall ergibt sich, wenn in einer Struktur unterschiedliche Datensätze gespeichert werden sollen (siehe {{w|Tagged Union}}):
:<syntaxhighlight lang="C">
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
int main(int argc,char *argv[]) {
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mittels eines Tagged Union kann komfortabel ein Binärbaum realisiert werden:
:<syntaxhighlight lang="C">
//Quelle: https://github.com/Hirrolot/datatype99
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h> //fuer printf()
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Die Eigenschaften des Datentyps union entsprechen den Eigenschaften des Datentyps struct in C++.
== Enum/Aufzählungstyp ==
Nach dem Wikipedia Artikel {{w|Aufzählungstyp}} ist ''ein Aufzählungstyp (englisch enumerated type) ein Datentyp für Variablen mit einer endlichen Wertemenge. Alle zulässigen Werte des Aufzählungstyps werden bei der Deklaration des Datentyps mit einem eindeutigen Namen (Identifikator) definiert, sie sind Symbole.''
<code>Syntax: enum enumname<sub>Opt</sub> {definition-list[=expression]}<sub>Opt</sub> Variablenliste<sub>Opt</sub></code>
Die Anwendung ist identisch wie bei Strukturen, so dass nachfolgend nur die Abweichungen zu den Strukturen beschrieben werden.
=== Datentyp von enum ===
In C entspricht der Datentyp Enum dem Datentyp <code>int</code> so dass Zuweisungen/Vergleiche mit Ganzzahlen möglich sind. Ganzzahloperationen funktionieren ebenso:
<syntaxhighlight lang="C">
enum STATUS {OK,KO=5}; //Definition des Datentyps
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
status++;
status=5.7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum STATUS {OK,KO=5}; //Definition des Datentyps
int main(int argc,char *argv[]) {
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
printf("status == 5\n");
status++;
status=5.7;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Enumelemente ===
Die Elemente der Definitionsliste sind Integerkonstanten. Diese können auch in Kombination mit anderen Datentypen genutzt werden. Auch gibt es keinen gesonderten Namensraum für Elemente der Definitionsliste. Sie 'konkurrieren' folglich mit allen Variablen- und Funktionsnamen:
<syntaxhighlight lang="C">
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
int main(int argc,char *argv[]) {
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der erste Enumelement der Definitionsliste bekommt den Wert 0 zugewiesen. Folgeelemente bekommen den Wert des Vorgängerelementes +1 zugewiesen.
Enumelemente können mit einer Konstanten (und Konstantenausdruck) initialisiert werden:
<syntaxhighlight lang="C">
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
int main(int argc,char *argv[]) {
printf("bill=%d john=%d, fred=%d\n",bill,john,fred);
printf("error=%d warning=%d info=%d ok=%d\n",error,warning,info,ok);
printf("Ostfalia=%d Wolfenbuettel=%d\n",Ostfalia,Wolfenbuettel);
printf("test=%d\n",test);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Es empfiehlt sich, die Enumelemente in GROSSBUCHSTABEN zu schreiben. Hiermit wird gekennzeichnet, dass es sich um Konstanten und nicht um Variablen/Funktionen handelt
=== Anwendung ===
Die Nutzung des Datentyps enum empfiehlt sich überall dort, wo eine Fallunterscheidung notwendig ist:
* Statusrückgabe von Funktionen:
:<syntaxhighlight lang="C">
enum STATUS {OK,MEMORY_OVERFLOW, DIVISION_BY_ZERO};
enum STATUS funct(…) {
return MEMORY_OVERFLOW;
}
</syntaxhighlight>
* Beschreibung der Zustände und der Ereignisse eines Zustandsautomates:
:<syntaxhighlight lang="C">
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Ergänzend zu den Abweichungen bei Structs sind hier weitere Unterscheidungsmerkmale vorhanden:
* Enums stellen einen eigenen Datentyp dar, der nicht mit int kompatible ist. Das bedingt unter anderem, dass einige Operatoren wie z.B. ++ nicht mehr auf Variablen des Datentyps enum angewendet werden. Die Enumelemente als solches sind jedoch kompatibel zum Ganzzahldatentyp:
:<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
int main(int argc,char *argv[]) {
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
printf("RED==2\n");
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
* Auch enums können Methoden besitzen.
* Über Operatorüberladung können z.B. nicht vorhandene Operatoren wie ++/-- ergänzt werden
* Über unscoped/scoped Enumerations wird der 'Namensraum' gesteuert:
:* Unscoped Enumeration (Elemente der Definitionsliste stehen wie bei C im Zugriff)
::<code>Syntax: enum name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE };
Color r = RED;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE };
Color r = RED;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
:* Scoped enumeration (Elemente der Definitionsliste haben einen eigenen 'Namensraum')
::<code>Syntax: enum '''class|struct''' name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
== Bitfelder ==
Nach dem Wikipediaartikel {{w|Bitfeld}} ''bezeichnet in der Informationstechnik und Programmierung ein Bitfeld ein vorzeichenloses Ganzzahldatentyp, in dem einzelne Bits oder Gruppen von Bits aneinandergereiht werden. Es stellt eine Art Verbunddatentyp auf Bit-Ebene dar. Im Gegensatz dazu steht der primitive Datentyp, bei dem der Wert aus allen Stellen gemeinsam gebildet wird.''
Der Syntax entspricht dem struct-Syntax, mit der Ergänzung, dass hinter den Strukturelementen noch die Bitbreite getrennt durch ein Doppelpunkt angegeben wird:
<syntaxhighlight lang="C">
struct time {
unsigned int hour: 5; //0..23 Bits 0..4
unsigned int minute: 6; //0..59 Bits 5..10
Unsigend int second: 6; //0..59 Bits 11..16
} myTime;
</syntaxhighlight>
Als mögliche Datentypen für die Strukturelemente stehen nur die Ganzzahldatentypen <code>int</code>, <code>short</code>, <code>long</code> , <code>long long</code> und <code>char</code> zur Verfügung. Der Datentyp eines Strukturelementes muss mindestens die Anzahl der Bits enthalten, wie diese über die Bitbreite gefordert wird.
Von den Strukturelementen kann keine Adresse bestimmt werden! Auch der <code>offsetf</code> - Operator schlägt fehl.
Der Datentyp entspricht im Wesentlichen einem Ganzzahlzahldatentyp, so dass bei Zugriff auf eine Variable dieses Datentyps eine Ganzzahl gelesen/geschrieben wird. Bei Zugriff auf die einzelnen Strukturelemente werden die entsprechenden Bits dieser Ganzzahlvariablen maskiert, so dass nur die betroffenen Bits geändert werden:
<syntaxhighlight lang="C">
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) | (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) | ((second&0b00001111)<<2);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
//Nachweis am besen über den Maschinensprachevergleich!
int main(int argc,char *argv[]) {
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) {{!}} (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) {{!}} ((second&0b00001111)<<2);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
h=c
}} Öffnen im Compiler Explorer] }}
=== Anwendung===
* Komprimierte Speicherung der Uhrzeit (wie dies z.B. in Realtimeclocks erfolgt)
:<syntaxhighlight lang="C">
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
int main(int argc,char *argv[]) {
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Aufteilung von FloatingPoint Zahlen in seine Komponenten
:<syntaxhighlight lang="C">
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
int main(int argc,char *argv[]) {
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",
(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Bitfelder existieren mit den bekannten Ergänzungen auch in C++.
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
iw2rwpp4p1d0wsjt51bfvtx21i2czfz
1090843
1090842
2026-09-15T08:07:10Z
D. Justen
102048
Aussagen klarer formuliert
1090843
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C kennt nachfolgende grundlegende Datentypen und Zeiger auf diese Datentypen (siehe auch [[Programmieren in C/C++: Grundlagen# Grundlegende Datentypen und Typsicherheit| Grundlagen:Grundlegende Datentypen und Typsicherheit]])
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| [[#Ganzzahl Datentypen|Ganzzahl]] ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| [[#Gleitkomma Datentypen|Gleitkommazahl]] ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Array|Arrays]] ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| [[#Struktur/Verbundtyp|Strukturen]]/[[#Union|Unions]] ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| [[#Enum/Aufzählungstyp|Aufzählungstyp]] ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Grundlagen #Boolescher-Datentype/Operatoren|Boolescher Datentyp]] ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| [[#Komplexe Zahlen|Komplexe Zahlen]] ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
Bis auf die Datentypen Funktionen, Array und die Zeiger sollen die wesentlichen Aspekte dieser Datentypen im nachfolgenden beschrieben werden.
'''Der grundlegende Datentyp ist <code>int</code>!'''
* Es wird mit nichts Kleinerem gerechnet als mit dem Datentyp <code>int</code> (siehe [[#Implizite Typumwandlung | Implizite Typumwandlung]]) :
:<syntaxhighlight lang="C">
char var1=10,var2=20,var3;
var3=var1+var2; //Addition findet auf Basis des Datentyps int statt
</syntaxhighlight>
* Es gibt zwar den Booleschen Datentyp, dieser entspricht jedoch einem Ganzzahldatentyp und <code>true</code> und <code>false</code> entsprechen den Integerwerten 0 und 1
* Der Aufzählungsdatentyp und seine Aufzählungselemente sind vom Datentyp <code>int</code>
* Bis einschl. C90 wurde bei der Definition von Variablen ohne Angabe des Datentyps, bei Definition einer Funktion ohne Angabe des Datentyps der Übergabeparameter, des Rückgabedatentyps der Datentyp implizit auf int gesetzt ('''implizit int''')
:<syntaxhighlight lang="C">
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}int main(int argc,char *argv[]) {
printf("%d",foo(1,var2));
return 0;
} | execCompilerOptions=-Wall -std=c90|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Ganzzahl Datentypen ==
Grundlegend kennt die Programmiersprache C nur zwei Ganzzahldatentypen:
* Datentyp: <code>int</code>
: Vorzeichenbehafteter (signed) Datentyp, dessen Bitbreite von der Rechnerarchitektur und des Compilers abhängig ist
* Datentyp <code>char</code>
: Datentyp mit einer Mindestbreite von 8-Bit u.A. zur Speicherung von Zeichen typischerweise im ASCII Format. Die C-Spezifikation [C11 6.2.5 Types] lässt es dem Compiler frei, ob <code>char</code> als vorzeichenbehafteter oder vorzeichenloser Datentyp implementiert wird.
: Ergänzend kann der Datentyp <code>char</code> auch zur Speicherung von ganzen Zahlen genutzt werden. In diesem Fall empfiehlt sich, diese explizit als <code>signed</code> und <code>unsiged</code> zu definieren. Wenn nur ASCII Zeichen gespeichert werden, so ist diese Angabe nicht nötig!
Optional können Qualifier dem Datentyp vorangestellt werden:
* <code>unsigned</code> / <code>signed</code> zur Angabe, ob der Inhalt als vorzeichenlose Zahl oder als vorzeichenbehaftete Zahl zu interpretieren ist. Ohne Angabe sind Variablen vom Datentyp <code>int</code> vorzeichenbehaftet
* <code>short</code> / <code>long</code> / <code>long long</code> (letzteres seit C99) als vorangestellten Qualifier zu <code>int</code> zur Vergrößerung/Verkleinerung der Bitbreite. Bei Angabe des Qualifiers ist das Schlüsselwort <code>int</code> optional. Die Beschreibung <code>long long int</code> und <code>long long</code> sind gleichbedeutend!
Als Bitbreite für die Datentypen ist im C-Standard nur ein Mindestbreite definiert. Die genaue Bitbreite hängt von der Rechenbreite des Systems und vom Compiler ab (siehe [C11 6.2.5 Types]):
{| class="wikitable"
|-
! Datentype !! Mindest<br />breite !! Typisch bei 32-Bit<br />Architektur !! Typisch bei 64-Bit<br />Architektur !! printf Format<br />Anweisung
|-
| <code>char</code> || 8 || 8 || 8 || <code>%c</code>
|-
| <code>signed char</code><br /><code>unsigned char</code>|| 8 || 8 || 8 || <code>%hhd</code><br /><code>%hhu</code>
|-
| <code>short</code><br /><code>short int</code>|| 16 || 16 || 16 || <code>%hd</code> / <code>%hu</code>
|-
|<code>int</code>|| 16 || 16/32 || 32 || <code>%d</code> / <code>%u</code>
|-
|<code>long</code><br /><code>long int</code>|| 32 || 32 || 32/64 || <code>%ld</code> / <code>%lu</code>
|-
|<code>long long</code><br /><code>long long int</code>|| 64 || 64 || 64 || <code>%lld</code> / <code>%llu</code>
|}
In der Header-Datei <code>limits.h</code> sind die tatsächlichen Grenzwerte der Datentypen gespeichert:
{| class="wikitable"
|-
! Konstante !! Beschreibung !! Typ. bei 64-Bit Architektur
|-
| <code>CHAR_BIT</code> || Anzahl der Bits in einem Char || 8
|-
| <code>SCHAR_MIN</code> || min. Wert, den der Typ bei signed char aufnehmen kann || -128
|-
| <code>SCHAR_MAX</code> || max. Wert, den der Typ bei signed char aufnehmen kann || 127
|-
| <code>UCHAR_MAX</code> || max. Wert, den der Typ bei unsigned char aufnehmen kann || 255
|-
| <code>CHAR_MIN</code> || min. Wert, den der Typ char aufnehmen kann || 0 oder SCHAR_MIN
|-
| <code>CHAR_MAX</code> || max. Wert, den der Typ char aufnehmen kann || SCHAR_MAX oder UCHAR_MAX
|-
| <code>SHRT_MIN</code> || min. Wert, den der Typ short int annehmen kann || -32.768
|-
| <code>SHRT_MAX</code> || max. Wert, den der Typ short int annehmen kann || 32.767
|-
| <code>USHRT_MAX</code> || max. Wert, den der Typ unsigned short int annehmen kann || 65.535
|-
| <code>INT_MIN</code> || min. Wert, den der Typ int annehmen kann || -2.147.483.648
|-
| <code>INT_MAX</code> || max. Wert, den der Typ int annehmen kann || 2.147.483.647
|-
| <code>UINT_MAX</code> || max. Wert, den der Typ unsigned int aufnehmen kann || 4.294.967.296
|-
| <code>LONG_MIN</code> || min. Wert, den der Typ long int annehmen kann || -2.147.483.648 oder<br />-9.223.372.036.854.775.808
|-
| <code>LONG_MAX</code> || max. Wert, den der Typ long int annehmen kann || 2.147.483.647 oder<br />9.223.372.036.854.775.807
|-
| <code>ULONG_MAX</code> || max. Wert, den der Typ unsigned long int annehmen kann || 4.294.967.296 oder<br />18.446.744.073.709.551.616
|-
| <code>LLONG_MIN</code> || min. Wert, den der Typ long long int annehmen kann || -9.223.372.036.854.775.808
|-
| <code>LLONG_MAX</code> || max. Wert, den der Typ long long int annehmen kann || 9.223.372.036.854.775.807
|-
| <code>ULLONG_MAX</code> || max. Wert, den der Typ unsigned long long int annehmen kann || 18.446.744.073.709.551.615
|}
Aufgrund dessen, dass die Breite der Datentypen von der Rechnerarchitektur und vom Compiler abhängig ist, sind in der Header-Datei <code>stdint.h</code> Aliase für Datentypen enthalten, welche in ihrem Alias die tatsächliche Breite und das Vorzeichens beinhalten:
<syntaxhighlight lang="C">
uint8_t --> unsigned 8-Bit
int8_t --> signed 8-Bit
uint16_t --> unsigned 16-Bit
int16_t --> signed 16-Bit
...
</syntaxhighlight>
In C++ sind diese Aliase im <code>std</code> namespace definiert:
<syntaxhighlight lang="C++">
std::intptr_t
std::int8_t std::uint8_t
std::int16_t std::uint16_t
std::int32_t std::uint32_t
Std::int64_t std::uint64_t
</syntaxhighlight>
Zur Erzeugung von portablen/rechnerunabhängigen Programmen empfiehlt sich, diese Datentypen zu nutzen. Die Rechenbreite ist dann unabhängig vom Compiler und Betriebssystem.
== Gleitkomma Datentypen ==
Gleitkommazahlen werden im Computer auf Basis folgender Schreibweise dargestellt (siehe auch: {{w|Gleitkommazahl}}):<br />
<syntaxhighlight lang="C">
Dezimalsystem Dualsystem
12,3456710 = 1234567 * 10^-5 0,110 = 1,1001100110011 * 2^-4
------- -- --------------- --
Mantisse Exponent Mantisse Exponent
</syntaxhighlight>
;Mantisse: Vorzeichenlose ganze Zahl (ggf. mit einer festen Position des Dezimalpunktes=Festkommazahl)
;Exponent: Vorzeichenbehaftete ganze Zahl, welche um einen Bias verschoben ist
;Vorzeichen: Vorzeichen der (vorzeichenlosen) Mantisse
Zur Speicherung im Computer werden das Vorzeichen, die Mantisse und der Exponent getrennt im Binärformat gespeichert, für den Programmierer aber als eine (zusammenhängende) Zahl dargestellt:
[[File:Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse.png|thumb|400px|center|Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse]]
Gleitkommazahlen haben genauso wie ganze Zahlen einen beschränkten Wertebereich:
* Die Anzahl der Bits der Mantisse bestimmen die Anzahl der Nachkommastellen:
:<syntaxhighlight lang="C">
Bei 23-Bit Mantisse ist die max. Zahl 2^-23-1=0,000000119,
welches 6..7 dezimale Stellen entspricht!
</syntaxhighlight>
* Mit dem Exponent kann 'quasi' der kleinste und der größte Wertebereich angegeben werden:
:<syntaxhighlight lang="C">
Bei 8-Bit Exponent mit einem Bias von 127 liegt der Wertebereich des
Exponenten im Bereich von -126 … +127 (Exponent -127 und +127 wird zur
Darstellung weitere Zahlen benötigt).
Die kleinste darstellbare Zahl (unter Vernachlässigung der Nachkommastellen der Mantisse ist:
2^-126=1/2^126≅1,175*10^-38
Die größte darstellbare Zahl ist:
2^127 ≅1,7*10^38
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
float sqrtf(float);
float powf(float,float);
#include <ieee754.h>
#include <complex.h>
union test {
unsigned int i;
float f;
union ieee754_float b;
};
int main(int argc,char *argv[]) {
union test var = {.f=-0.1};
printf("Float=%f Binär=%032b\n",var.f,var.i);
printf("v=0b%b e=0b%08b m=0b(1).%023b\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%10d m=%29d\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%d-%d=%d m=1+%d/2^-23=%f\n",var.b.ieee.negative,
var.b.ieee.exponent,IEEE754_FLOAT_BIAS,var.b.ieee.exponent-IEEE754_FLOAT_BIAS,
var.b.ieee.mantissa,1.0+var.b.ieee.mantissa*1.0/(1<<23));
printf("\n--- Beispiele von Genauigkeitsprobleme im Umgang mit Gleitkommazahlen (hier float) ----\n");
printf("powf(sqrtf(%1.8f),2) = %1.8f\n",2.0f,powf(sqrtf(2.0f),2));
printf("%f + %f = %f\n",2000.0,0.0004,(double)(2000.0f+0.0004f));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Grundlegend kennen die Programmiersprachen C/C++ folgende Gleitkommadatentypen:
* Datentyp: <code>float</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindesten 6 Stellen betragen, so dass der Datentyp typischerweise 32-Bit groß ist
* Datentyp: <code>double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, so dass der Datentyp typischweise 64-Bit Große ist
* Datentyp: <code>long double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, damit könnte dieser Datentyp gleich dem Datentyp <code>double</code> gesetzt werden. In der Tat ist die Datenbreite Rechner- und Compilerabhängig. Einige Compiler setzen diesen Datentyp identisch zu <code>double</code>, bei x86 Prozessoren wird aufgrund der Hardwareunterstützung 80-Bit genutzt (wobei in der Tat der Datentyp aufgrund von alignment dann 16-Byte Speicherplatz beansprucht) und einige Systeme nutzen 128-Bit (wobei hier aufgrund ggf. fehlender Hardwareunterstützung Operationen mit diesem Datentyp per Software emuliert werden) (siehe Wikipedia Artikel {{w|lang=en|Long_double|long double}}).
Die genaue Darstellung (Anzahl der Bits für Mantisse und Exponent, Darstellung von NAN/INF, ….) ist in C nicht spezifiziert und somit compiler- und rechnerabhängig. Zumeist wird mittlerweile die {{w|IEEE 754}} Standardisierung genutzt (Norm wurde von Intel mit der Entwicklung der 8087 FPU entworfen).
Grunddatentypen und der Wertebereich (nach {{w|IEEE 754}})
{| class="wikitable"
|-
! Daten-<br/>type !! Speicher-<br />platz !! Exponent !! Mantisse !! Größte Zahl !! Kleinste Zahl !! Genauigkeit !! printf Format Anweisung
|-
| binary32→<code>float</code> || 4 Byte || 8 bit || 23 bit || ~3,4*10<sup>38</sup> || ~1,2*10<sup>-38</sup> || 7..8 Stellen || ---
|-
| binary64→<code>double</code> || 8 Byte || 11 bit || 52 bit || ~1,8*10<sup>308</sup> || ~2,2*10<sup>-308</sup> || 15..16 Stellen || %f %e %g
|-
| binary64 extended→<code>long double</code> || ≥10 Byte || ≥15 bit || ≥63 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 19..20 Stellen || %Lf %Le %Lg
|-
| binary128→<code>long double</code> || 16 Byte || 15 bit || 112 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 34 Stellen || %Lf %Le %Lg
|}
Die tatsächliche Auflösung der Datentyps kann auf Basis nachfolgender Konstanten, definiert in der Header-Datei <code>float.h</code>, ermittelt werden:
:<syntaxhighlight lang="C">
FLT_DIG --> Anzahl der dezimalen Nachkommastellen für float
DBL_DIG --> Anzahl der dezimalen Nachkommastellen für double
LDBL_DIG --> Anzahl der dezimalen Nachkommastellen für long double
FLT_MIN_10_EXP --> Minimaler Exponent zur Basis 10
DBL_MIN_10_EXP
LDBL_MIN_10_EXP
FLT_MAX_10_EXP --> Maximaler Exponent zur Basis 10
DBL_MAX_10_EXP
LDBL_MAX_10_EXP
LDBL_MANT_DIG --> Anzahl der Bits für die Mantisse
LDBL_MANT_DIG
LDBL_MANT_DIG
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <float.h>
int main(){
printf("FLT_DIG =%u\n",FLT_DIG);
printf("DBL_DIG =%u\n",DBL_DIG);
printf("LDBL_DIG =%u\n",LDBL_DIG);
printf("FLT_MIN_10_EXP =%d\n",FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP =%d\n",DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP=%d\n",LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP =%d\n",FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP =%d\n",DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP=%d\n",LDBL_MAX_10_EXP);
printf("FLT_MANT_DIG =%d\n",FLT_MANT_DIG);
printf("DBL_MANT_DIG =%d\n",DBL_MANT_DIG);
printf("LDBL_MANT_DIG =%d\n",LDBL_MANT_DIG);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Aufgrund des nicht standardisierten Formates sollte ein Gleitkommadatentyp nicht im Binärformat für den Datenaustausch (mit Netzwerk, über Dateien, ..) genutzt werden. Andere Rechnersysteme/Programmiersprachen würde aufgrund der anderen Interpretation andere Zahlenwerte aus den übertragenen/gespeicherten Binärdaten auslesen!
<syntaxhighlight lang="C">
float var1;
write(file_hdl,&var1,sizeof var1); //Schreiben des Binärwertes
//in eine Datei
double var2;
send(socket_hdl,&var2,sizeof var2,0);//Senden des Binärwertes
//über ein Netzwerk
</syntaxhighlight>
Die Standard-C-Library bietet einige mathematische Funktionen wie <code>sin() / cos() / tan() / atan2() / sqrt() / pow() / exp()/…</code> an. Die Prototypen dieser Funktion sind in der Header-Datei <code>math.h</code> beschrieben, so dass diese bei Nutzung dieser Funktion zu inkludieren ist. Ergänzend ist die Shared Library libm.so über den Compilerschalter '-lm' einzubinden:
<syntaxhighlight lang="C">
#include <math.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
double sqrt(double);
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
printf("var1=%f var2=%f\n",var1,var2);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen basieren auf den Datentyp <code>double</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist vom Datentyp <code>double</code>. Die Prototypen sehen wie folgt aus:
<syntaxhighlight lang="C">
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double); //Wertebereich der Rückgabe von -PI/2..+PI/2
double atan2(double,double); //Wertebereich der Rückgabe von -Pi .. +PI
double sqrt(double);
double log(double);
</syntaxhighlight>
Über den Suffix f oder l im Funktionsnamen kann der zugrundeliegende Datentyp auf float (Suffix f) oder long double (Suffix l) geändert werden:
<syntaxhighlight lang="C">
float sinf(float);
long double sinl(long double);
</syntaxhighlight>
Ergänzend zu den Prototypen sind die gebräuchlichen Naturkonstanten in <code>math.h</code> definiert (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
M_E Value of e
M_LOG2E Value of log_2 e
M_LOG10E Value of log_10 e
M_LN2 Value of log_e 2
M_LN10 Value of log_e 10
M_PI Value of π
M_PI_2 Value of π/2
M_PI_4 Value of π/4
M_1_PI Value of 1/π
M_2_PI Value of 2/π
M_2_SQRTPI Value of 2/√π
M_SQRT2 Value of √2
M_SQRT1_2 Value of 1/√2
</syntaxhighlight>
Gleitkommazahlen können nicht nur Zahlenwerte, sondern auch Sonderwerte annehmen. Diese Sonderwerte sind ebenfalls in <code>math.h</code> beschrieben (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
INFINITY A constant expression of type float representing
positive or unsigned infinity, if available; else a
positive constant of type float that overflows at
translation time.
NAN A constant expression of type float representing a
quiet NaN. This macro is only defined if the
implementation supports quiet NaNs for the float type.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <math.h>
//Quelle: https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c
#ifdef NAN
#define NAN_STR "NAN is supported"
#else
#define NAN_STR "NAN is not supported"
#endif
#ifdef INFINITY
#define INFINITY_STR "INFINITY is supported"
#else
#define INFINITY_STR "INFINITY is not supported"
#endif
int main(int argc, char *argv[argc]) {
printf("%s\n%s\n",NAN_STR,INFINITY_STR);
double x=0.0;
double y=1/x;
printf("1/%e -> %e\n",x,y);
if(y==INFINITY)
printf("1) Initinity\n");
if(isinf(y)) //besser
printf("2) Initinity\n");
printf("%llx\n%llx\n\n",*(long long *)&y,INFINITY);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
double z=-(x/x);
printf("%e/%e -> %e\n",x,x,z);
if(z == NAN) //funktioniert nicht
printf("1) Not a Number\n");
if(isnan(z)) //besser
printf("2) Not a Number\n");
if(z != z)
printf("3) Not a Number\n");
printf("%llx\n%llx",*(long long *)&z,NAN);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
return 0;
} | execCompilerOptions=-lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit <code>fesetround()/fegetround()</code> kann gesetzt/gelesen werden, wie mit Ergebnissen umzugehen sind, die nicht exakt darstellbar sind. Mögliche Werte sind 'round to nearest' (default), 'round up', 'round down' und 'round toward zero'.
== Komplexe Zahlen ==
Nach dem Wikipedia Artikel {{w|komplexe Zahlen}} ''stellen komplexe Zahlen eine Erweiterung der reellen Zahlen dar. Ziel der Erweiterung ist es, algebraische Gleichungen wie x<sup>2</sup>+1=0 bzw. x<sup>2</sup>=-1 lösbar zu machen. ... Da die Quadrate aller reellen Zahlen größer oder gleich 0 sind, kann die Lösung der Gleichung x<sup>2</sup>=-1 keine reelle Zahl sein. Man braucht eine ganz neue Zahl, die man üblicherweise i nennt, mit der Eigenschaft i<sup>2</sup>=-1. Diese Zahl i wird als imaginäre Einheit bezeichnet.
Komplexe Zahlen werden nun als Summe a+b*i definiert, wobei a und b reelle Zahlen sind und i die oben definierte imaginäre Einheit ist.''<br />
Der Datentyp für komplexe Zahlen (erst ab C99 enthalten) beinhaltet folglich zwei Gleitkommazahlen, eine für den reelen Teil und eine für den imaginären Teil. Entsprechend den Gleitkommazahlen steht der komplexe Datentyp ebenfalls in drei unterschiedlichen Genauigkeiten zur Verfügung:
{| class="wikitable"
|-
! Datentype !! Speicherplatz
|-
| <code>float _Complex</code> || 2x4Byte
|-
| <code>double _Complex</code><br /><code>_Complex</code> || 2x8Byte
|-
| <code>long double _Complex</code> || 2x10Byte
|}
Wie auch beim Booleschen Datentyp ist in der Header-Datei <code>complex.h</code> für den einfacheren Umgang mit diesem Datentyp das Makro <code>complex</code> als Textersetzung für <code>_Complex</code> gesetzt.
Zur Darstellung von komplexen Konstanten wurde die Gleitkommakonstante um den Suffix i ergänzt. Durch Anhängen von i wird aus dem ansonsten rellen Teil der imaginäre Teil und damit aus der Gleitkommakonstante eine komplexe Gleitkommakonstante:
<syntaxhighlight lang="C">
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Normale Gleitkommavariablen werden als reellen Teil einer komplexen Zahl angesehen. Bei Operationen von Gleitkommazahlen und komplexen Zahlen wird der imaginäre Teil der Gleitkommazahl auf 0 gesetzt. Beim Zuweisen einer komplexen Zahl an eine Gleitkommazahl wird nur der reele Teil 'gelesen'.<br />
Soll eine Gleitkommavariablen zu einem imaginären Teil gewandelt werden, so muss diese bspw mit der Konstanten 1.0i multipliziert werden:
<syntaxhighlight lang="C">
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C-Library bietet diverse mathematische Funktionen wie csin(), ccos(), csqrt(), cpow() und ergänzend Umrechnungsfunktionen von Gleitkommazahlen in komplexe Zahlen (und umgedreht) wie creal(),cimag() ,cabs() für den Umgang mit komplexen Zahlen an:
<syntaxhighlight lang="C">
double _Complex csin(double _Complex);
double _Complex csqrt(double _Complex);
double creal(double _Complex);
double cimag(double _Complex);
</syntaxhighlight>
Zur Nutzung dieser Funktionen muss die Header-Datei <code>complex.h</code> inkludiert und ergänzend die Shared Library libm.so über den Compilerschalter '-lm' eingebunden werden.
<syntaxhighlight lang="C">
#include <complex.h>
//Math-Library mittels Linker-Command '-lm' einbinden
int main(int argc, char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen beruhen auf den Datentyp <code>double _Complex</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist <code>double _Complex</code> resp. <code>double</code> (bei den Umrechnungsfunktionen). Über den Suffix f und l im Funktionsnamen kann der zugrundeliegende Datentyp geändert werden:
<syntaxhighlight lang="C">
float crealf(float _Complex z);
long double creall(long double _Complex z);
</syntaxhighlight>
Hinweis:
* Der Datentyp <code>_Complex</code> und die dazugehörigen mathematischen Funktionen sind in der C-Spezifikation als optional gekennzeichnet.
== Generische mathematische Funktionen ==
In der <code>tgmath.h</code> Header Datei sind für die mathematischen Funktionen Makros enthalten, welche den Datentyp der Übergabeparameter bestimmen und basierend auf den Datentyp die dazugehörige mathematische Funktion aufrufen.
<code>tgmath.h</code> selbst inkludiert <code>math.h</code> und <code>complex.h</code>, so dass diese nicht weiter zu inkludieren sind.
Steht für den Übergabedatentyp keine passende Funktion zu Verfügung, so ist das Verhalten des Makros undefiniert (bspw. wenn ein komplexes Argument an eine Funktion übergeben wird, die nur für Gleitkommazahlen ausgelegt ist <code>ceil(1+2i);</code> )
Folgendes Regelwerk wird angewendet:
* Ist einer der Übergabeparameter imaginär, so ist die ausgewählte Funktion in der Spezifikation der Funktion beschrieben
* Ist einer der Übergabeparameter Komplexe, so wird die Komplexe Variante der Funktion aufgerufen, andernfalls die Gleitkomma Variante
* Ist einer der Übergabeparameter vom Datentyp <code>long double</code>, so wird die <code>long double</code> Variante, bei integer und double die <code>double</code> Variante und andernfalls die <code>float</code> Variante aufgerufen
Beispiel:
<syntaxhighlight lang="C">
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
int main(int argc,char *argv[]) {
foo(1l+1li,2.0l,3.0f,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=c
}} Öffnen im Compiler Explorer] }}
== Boolschescher Datentyp ==
Siehe [[Programmieren in C/C++: Grundlagen#Boolescher-Datentype/Operatoren|Grundlagen: Boolescher-Datentype/Operatoren]]
== void / unvollständiger Datentype ==
Der Datentyp <code>void</code> dient vorrangig dazu, nicht vorhandene Über- und Rückgabewerte von Funktionen anzuzeigen. Eine Variable vom Datentyp <code>void</code> kann nicht angelegt werden. Ein Zeiger vom Datentyp <code>void</code> ist möglich, kann aber nicht dereferenziert werden (siehe Kap. [[Programmieren in C/C++: Zeiger #Void-Zeiger| Zeiger:Void-Zeiger]])
<syntaxhighlight lang="C">
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* <code>sizeof(void)</code> ist nach der C-Spezifikation nicht erlaubt. Dennoch geben viele Compiler hier den Wert 1 zurück!
* Mit einem expliziten Cast auf den Datentyp void wird dem Compiler mitgeteilt, dass diese Variable in Gebrauch ist, der Wert in dieser Operation aber nicht genutzt wird. Hierüber kann die Compilerwarning 'unused Variable' unterbunden werden:
:<syntaxhighlight lang="C">
void func(int par1, int par2) {
int var1=12;
int var2=13;
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int par1, int par2) {
int var1=12;
int var2=13;
int var3=14; //Nicht genutzte Variable
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
printf("Genutzt\n");
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Datentypkonvertierung ==
Für das Rechnen/Vergleichen müssen beide Operatoren vom identischen Datentyp sein! Sind diese nicht identisch, so müssen die Datentypen 'angeglichen' werden. Dies kann einerseits ‚automatisch‘ mittels 'implizierter' Typumwandlung oder ‚manuell‘ mittels ‚expliziter' Typumwandlung erfolgen.<br />
Beim Zuweisungsoperator (inkl. Parameterzuweisung bei Funktionsaufrufen und Funktionsrückgabewerte mittels return) gilt dies ebenso, nur dass hier der Quelldatentyp an den Zieldatentyp angepasst werden muss. Die impliziten Regeln finden hier keine Anwendung.
Hinweis:
* Empfehlenswert ist, die Datentypen der Variablen so zu wählen, dass der Compiler keine implizite Typumwandlung tätigt. Kann dies nicht vermieden werden, so sollte die explizite Typumwandlung genutzt werden (um sich einen möglichen Datenverlust bewusst zu machen)
* Der Datentyp selbst sollte den möglichen Wertebereich der Variablen entsprechen und nicht unnötig groß gewählt werden
:<syntaxhighlight lang="C">
Datentyp zur Speicherung der Stundenzeit:
Wertebereich: 0 ... 23 -> unsigned char
Datentyp zur Speicherung einer Jahreszahl:
Wertebereich: 2000 v.C. ... 4000 n.C -> signed short
Datentyp zur Speicherung einer Temperatur:
Wertebreich: -273,0°C ... 2000,0°C -> float
</syntaxhighlight>
=== Implizite Typumwandlung ===
Diese Regeln wurden so aufgestellt, dass dabei stets ein Datentyp in einen anderen Datentyp mit höherem Wertigkeit umgewandelt wird [C11 6.3.1.8] und [Harbison: S 199]. Bei Ganzzahlen gilt ergänzend folgende (Rangordnung [C11 6.3.1.1]: long long, long, int, short,char,_Bool):
{| class="wikitable"
|-
! Regel/<br />Priorität !! If either operand<br />has Type !! And the other operand<br />has Type !! Converts both to
|-
| 1 (hoch) || long double || any real type || long double
|-
| 2 || double || any real type || double
|-
| 3 || float || any real type || float
|-
| 4 || any unsigned type || any unsigned type || the unsigned type<br/>with the greater rank
|-
| 5 || any signed type || any signed type || the signed type<br/>with the greater rank
|-
| 6 || any unsigned type || a signed type with a equal<br/> or less rank || the unsigned type
|-
| 7 || any unsigned type || a signed type that can represent<br/>all of values of the unsigned type || the signed type
|-
| 8 (niedrig) || any other type || any other type || both operands are<br/> converted to the unsigned <br/>integer type corresponding<br/> to the type of the operand<br/> with the signed<br/> integer type
|}
Ergänzend gilt das Regelwerk zu Integer Promotion, welche Datentypen kleiner als <code>signed int</code> zu <code>int</code> und kleiner als <code>unsigned int</code> zu <code>unsigned int</code> konvertiert (Compiler kann hiervon abweichen, wenn sichergestellt ist, dass kein Datenverlust eintritt).
Regel 6 und 7 sind der nicht klar definierten Bitbreite der ganzzahligen Datentypen geschuldet und versuchen, Konvertierungsverluste zu vermeiden. Sie lesen sich zunächst kryptisch, lassen sich aber einfach am folgenden Beispiel erklären:
<syntaxhighlight lang="C">
Operand 1: unsigned int (hier 32-Bit)
Operand 2: long (hier 32-Bit / 64-Bit)
</syntaxhighlight>
* Im Fall, dass der Datentyp <code>long</code> 64-Bit breit ist, kann dieser problemlos die vorzeichenlose 32-Bit Zahl ohne Konvertierungsverluste repräsentieren, so dass der Zieltype <code>signed long</code> ist (Regel 7)
* Im Fall, dass der Datentyp <code>long</code> 32-Bit breit ist, kann dieser mit seinen Wertebereich von -2.147.483.648 bis +2.147.483.647 nicht den vorzeichenlosen Zahlenbereich von 0…4.294.967.295 darstellen. In diesem Fall hat der unsigned Datentyp einen höheren Rang, so dass als Zieltyp <code>unsigend long</code> gewählt wird (Regel 6)
'''Regel 6 bedeutet die Gefahr eines Konvertierungsverlustes, dessen man sich bewusst sein sollte!''' Diese tritt insb. dann in Kraft, wenn ein Operand vom Typ <code>unsigned long long</code> ist (64-Bit).
Beispiele von impliziten Typumwandlungen:
<syntaxhighlight lang="C">
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
vari=5.0*(int)sin(vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ Wikibooks Formatierung schlägt hier fehlt
double sin(double);
int main(int argc,char *argv[]) {
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
printf("vars=%hd\n",vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
printf("vars=%hd\n",vars);
vari=5.0*(int)sin(vars);
printf("vari=%d\n",vari);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
printf("vari=%d\n",vari);
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im CompilerExplorer können sie sich die impliziten Typumwandlungen anzeigen lassen. Dazu gehen sie bitte wie folgt vor:
:* Im Source-Fenster mit '+Add new' ein Compiler Fenster öffnen
:* Im Compiler-Fenster mit '+Add new' ein 'GCC Tree/RTL' Fenster öffnen
:* Im GCC Tree/RTL-Fenster unter 'Select a pass…' 'original tree' auswählen
Um implizite Typumwandlung besser erkennen zu können, wird oftmals bei Variablennamen die ''' 'Ungarische Notation' ''' angewendet (siehe {{w|Ungarische Notation}}). Aufgrund der besonderen Namensgebung kann der Programmierer ohne großen Aufwand frühzeitig mögliche Typkonflikte erkennen. Der Variablenname setzt sich wie folgt zusammen:
<syntaxhighlight lang="C">
{Präfix}{Datentyp}{Bezeichner}
</syntaxhighlight>
:'''Präfix''': p->Pointer h->Handle i->index c->count f->flag rg->Array
:'''Datentyp''': ch->Character st->string w->word b->byte…
:'''Bezeichner''': Zum Binden der Variable an eine konkrete Aufgabe (keine Unterstriche).
:Bezeichner ist optional, wenn aus Präfix und Datentyp die 'Aufgabe' der Variable direkt sichtbar ist
Beispiele:
<syntaxhighlight lang="C">
char rgchtemp[10]; //Array (Range) vom Datentyp character
int ich; //Index zum Adressieren eines Arrays vom Datentyp
//character
</syntaxhighlight>
=== Explizite Typumwandlung ===
Programmierer erzwingt durch explizite Typumwandlung (auch CASTen genannt) eine Umwandlung eines Datentyps in einen anderen. Dazu wird der Zieldatentyp in runden Klammern vor Quelldatentype geschrieben:
<syntaxhighlight lang="C">
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
In der Rangfolge der Operatoren steht der Cast-Operator unterhalb von bspw. Funktionsaufrufen, Arrayzugriffen aber auch der Dereferenzierung:
{| class="wikitable"
|-
! Priorität !! Symbol !! Assoziativität !! Bedeutung
|-
| 15 || ... || ... || ...
|-
| 14
||
++/-- (Präfix)<br />
+/- (Vorzeichen) <br />
<nowiki>!</nowiki>/~ <br />
&<br />
<nowiki>*</nowiki><br />
(TYP)<br />
...
|| R-L
||
Präfix-Inkrement/Dekrement<br />
Vorzeichen<br />
Logisches/Bitweises Nicht<br />
Adresse<br />
Zeigerdereferenzierung<br />
'''Typumwandlung (Explizites Cast)'''<br />
...
|-
| 13
||
* / %
|| L-R
|| Multiplikation/Division/Modulo
|-
| 12 || ... || ... || ...
|}
Im Zweifel gilt auch hier, den zu wandelnden Typ ergänzend zu klammern.
Hinweis:
* Bedenke, dass die explizite Typumwandlung so aufgestellt sein sollte, dass der Zieldatentyp dem notwendigen Datentyp entspricht. Andernfalls wendet der Compiler ergänzend eine implizierte Typumwandlung an:
:<syntaxhighlight lang="C">
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Mittels expliziter Typumwandlung können Ganzzahl nach Gleitkommazahlen (und andersherum) und Zeiger in einen anderen Zeiger und auf andere Datentypen gewandelt werden. Eine Konvertierung von Arrays, Strukturen, Unions zu anderen Datentypen als sich selbst ist weiterhin nicht möglich:
<syntaxhighlight lang="C">
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei den möglichen Konvertierungen sollte Folgendes berücksichtigt werden:
* '''Vorzeichenlose Ganzzahl''' → '''Vorzeichenlose Ganzzahl''': Wenn der Zieldatentyp größer ist, wird die Zahl durch führende '0' erweitert. Wenn der Zieldatentyp kleiner ist, werde die zu vielen Bitstellen abgeschnitten/verworfen (ggf. Datenverlust)
* '''Vorzeichenbehaftete Ganzzahl''' → '''Vorzeichenbehaftete Ganzzahl''': Wenn der Zieldatentyp größer ist, wird vorzeichenrichtig erweitertet (d.h. das Auffüllen erfolgt auf Basis des Vorzeichens). Wenn der Zieldatentyp kleiner ist, werden auch hier die zu vielen Bits abgeschnitten/verworfen (Vorsicht: Negative Zahlen können dabei in positive Zahlen gewandelt werden)
* '''Gleitkommazahl''' → '''Gleitkommazahl''': Hier wird vereinfacht ausgedrückt sowohl die Mantisse als auch der Exponent einzeln kopiert. Wenn die Zielmantisse kleiner ist, gehen 'Nachkommastellen' verloren. Wenn der Quellexponent einen größeren Wert beinhaltet, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf Unendlich gesetzt. Umgedreht, wenn der Quellexponent kleiner ist, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf 0 gesetzt
* '''Ganzzahl''' → '''Gleitkommazahl''': Hier wird, vereinfacht ausgedrückt, die Ganzzahl in die Mantisse kopiert. Um Datenverluste zu vermeiden, sollte die Bitbreite der Zielmantisse größer gleich der Bitbreite der Ganzzahl sein
* '''Gleitkommazahl''' → '''Ganzzahl''': Im Wesentlichen wird hier die Mantisse übernommen, so dass hier die Bitbreite des Zieldatentyps mindestens der Bitbreite der Mantisse sein sollte
* '''Zeiger''' ↔ '''Ganzzahl''': Die Konvertierung ist möglich. Da bei 64-Bit Systemen der Zeiger 64-Bit und Integer 32-Bit breit ist, meckert ggf. der Compiler. Für solche Fälle existieren die Datentypen 'intptr_t' und 'uintptr_t', über welche sichergestellt ist, dass ein Zeiger in einen Ganzzahldatentyp gespeichert werden kann!
* '''Zeiger''' ↔ '''Gleitkommazahl''': Diese Konvertierung ist nicht möglich!
* '''Struktur/Union''' ↔ '''Ganzzahl/Gleitkommazahl''': Diese Konvertierung ist nicht möglich. Es können nur einzelnen Strukturelemente konvertiert werden, sofern diese vom Typ Ganzzahl/Gleitkommazahl sind
* '''Array''' ↔ '''Ganzzahl/Gleitkommazahl''': Der Arrayname entspricht einen Zeiger, so dass hier ein Zeiger in eine Ganzzahl oder umgedreht konvertiert wird (siehe Zeiger ↔ Ganzzahl)
In C++ gibt es weitere CAST-Operatoren, auf welche hier derzeit noch nicht weiter eingegangen wird!
* Static_cast (Entspricht dem Expliziten Cast)
* Const_cast
* Dynamic_cast
* Reinterpret_cast
== Verbundtyp Struktur/Klasse (nur C++) ==
Nach dem Wikipedia Artikel {{w|Verbund (Datentyp)}} ist ''ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten können wiederum Verbünde enthalten, wodurch auch komplexe Datenstrukturen definiert werden können.<br />
Für jedes Strukturelement wird Speicher reserviert. Alle Strukturelemente liegen hintereinander im Speicher.''
<code>Syntax: struct Strukturname<sub>Opt</sub> {Datentype Strukturelementname; … }<sub>OPT</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Verbund entspricht einer Java Klasse mit dem Unterschied zu C (nicht C++) , dass ein Verbund keine Methoden beinhaltet und keine Zugriffsbeschränkung für die Attribute gesetzt werden können.
Der Syntax erlaubt es, gleichermaßen einen Datentyp (über Strukturname) zu definieren und Variablen von diesem Datentyp (über Variablenliste) anzulegen. Da beide Elemente optional sind, ergeben sich diverse Kombinationsmöglichkeiten:
* Nur Strukturname → Definition eines neuen Datentyps
:<syntaxhighlight lang="C">
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
var1.y=2;
var1.z=1;
printf("var1.x=%d var1.y=%d var1.z=%d\n",var1.x,var1.y,var1.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C: Der Strukturname ist nur mit dem vorangestellten <code>struct</code> gültig. Der Strukturname stellt somit einen eigenen Namensraum, getrennt von dem Namensraum der Variablen/Funktionen, dar. Daher kann ein Strukturname identisch zu einem Variablennamen sein:
:<syntaxhighlight lang="C">
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
xyz2.x=xyz2.y=xyz2.z=1;
printf("xyz2.x=%d xyz2.y=%d xyz2.z=%d\n",xyz2.x,xyz2.y,xyz2.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C++: Der Strukturname ist sowohl mit als auch ohne dem vorangestellten <code>struct</code> gültig. Auch hier stellt der Strukturname einen eigenen Namensraum dar, der jedoch eine niedrigere Priorität als der der Variablen hat:
:<syntaxhighlight lang="C++">
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz beschreibt hier die Variable
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz3 beschreibt hier die Variable
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
* Nur Variablenliste → Definition einer/mehrerer Variablen von einem 'unnamed' Datentyp
:<syntaxhighlight lang="C">
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Angewendet wird die Schreibweise gerne, wenn eine Struktur innerhalb einer Struktur definiert wird und die innere Struktur zur besseren Strukturierung dient:
:<syntaxhighlight lang="C">
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Strukturname und Variablenliste → Definition eines Datentyps und Definition von Variablen. D.h. es können im Nachhinein weitere Variablen von diesem Datentyp angelegt und die hier angelegten Variablen genutzt werden.
:<syntaxhighlight lang="C">
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y; //Nutzung der Variablen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y=1; //Nutzung der Variablen
(void)var1;
(void)ptr1;
(void)ptr2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Kein Strukturname und keine Variablenliste → "Anonymous Struct", d.h. Definition eines 'unnamed' Datentyps, von der ergänzend keine Variable angelegt wird. Anonymus Structs sind nur innerhalb von Strukturen erlaubt/einsetzbar. Hier dienen sie der besseren Strukturierung und ersparen dem Programmierer die Benennung des normalerweise notwendigen Strukturelementes:
:<syntaxhighlight lang="C">
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
(void)var;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Eine Struktur (und auch eine C++ Klasse) wird mit einem Semikolon abgeschlossen
* Eine alternative Beschreibung zu Strukturen finden sie in [https://abstractexpr.com/2023/06/29/structures-in-c-from-basics-to-memory-alignment/ Structures in C: From Basics to Memory Alignment]
=== Strukturelement ===
Innerhalb der Struktur können beliebige Strukturelemente von beliebigen Datentypen angelegt werden. Einzige Voraussetzung, der Datentyp des anzulegenden Strukturelementes muss zuvor definiert worden sein. Ergänzend kann der neue Datentyp auch in der Struktur selbst definiert werden, sofern mit der Definition des Datentyps auch eine Variable angelegt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zugriff auf Strukturelemente ===
Die Programmiersprachen C/C++ unterscheiden zwei 'Zugriffsarten' auf die Strukturelemente, abhängig vom zugrundeliegenden Datentyp des linken Operanden::
* Handelt es sich beim linken Operanden um eine (struct)Variablen, so erfolgt der Zugriff über den Punkt-Operator <code>.</code>:
:<syntaxhighlight lang="C">
struct {
int a,b,c;
} abc;
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct {
int a,b,c;
} abc;
int main(int argc,char *argv[]) {
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c=12;
printf("abc.a=%d abc.b=%d abc.c=%d\n",abc.a,abc.b,abc.c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Handelt es sich beim linken Operanden um einen Zeiger auf eine (struct)Variable, so erfolgt der Zugriff über den Zeiger-Operator <code>-></code>:
:<syntaxhighlight lang="C">
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
int main(int argc,char *argv[]) {
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Werden innerhalb von Strukturen weitere Strukturen und Zeiger auf Strukturen angelegt, so müssen diese Regeln auf jedes innere Strukturelement einzeln angewendet werden:
<syntaxhighlight lang="C">
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
int main(int argc,char *argv[]) {
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Strukturen ===
Mit dem Anlegen einer Strukturvariablen kann diese auch initialisiert werden. Eine 'Vorbelegung' der Strukturelemente bei der Definition der Struktur ist in C nicht möglich.<br />
Die Initialisierung erfolgt über eine Initialisierungsliste (siehe Kap [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]). Innerhalb der Initialisierungsliste stehen die Initialisierungswerte entweder in der Reihenfolge der Datentypdefinition oder werden explizit mit dem ‘.‘ Operator angesprochen (designated initializers). Werden einzelne Strukturelemente ausgelassen, so werden diese mit 0 initialisiert:
<syntaxhighlight lang="C">
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
int main(int argc,char *argv[]) {
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
printf("v1.a=%d v1.b=%d v1.str[0]=%d\n",v1.a,v1.b,v1.str[0]);
printf("v2.a=%d v2.b=%d v2.str[0]=%d\n",v2.a,v2.b,v2.str[0]);
printf("v3.a=%d v3.b=%d v3.str[0]=%d\n",v3.a,v3.b,v3.str[0]);
printf("v4.a=%d v4.b=%d v4.str[0]=%d\n",v4.a,v4.b,v4.str[0]);
printf("v5.a=%d v5.b=%d v5.str[0]=%d\n",v5.a,v5.b,v5.str[0]);
printf("v6.a=%d v6.b=%d v6.str[0]=%d\n",v6.a,v6.b,v6.str[0]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Initialisierung einer Struktur über nachfolgende Art bewirkt etwas anderes, als erwartet:
<syntaxhighlight lang="C">
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
printf("var.a=%d var.b=%d var.c=%d\n",var.a,var.b,var.c);
//Gerne mal den Compiler Wechseln
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der Initialisierungsliste wird über 'var.b=12' und 'var.c=3' die zu diesem Zeitpunkt noch nicht initialisierte Variable var die Elemente b und c initialisiert. Mit dem Werten der Initialisierungsliste (hier {12,3}) wird nachfolgend die Variable erneut initialisiert und 12 dem Strukturelement a und 3 dem Strukturelement b zugewiesen. Abhängig vom Compiler ist das Strukturelement c entweder 3 oder 0.
Bei verschachtelten Strukturen muss entsprechend obiger Aussage für jede innere Struktur eine eigene Initialisierungsliste erstellt werden. Die inneren Initialisierungslisten können entfallen, was jedoch nicht empfohlen wird und ergänzend vom Compiler bei '-Wall' als Warning angemerkt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8}}
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={{.x=5,.y=6},{7,8}},
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8} }
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={ {.x=5,.y=6},{7,8} },
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
int main(int argc,char *argv[]) {
printf("v1.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v1.a, v1.b, v1.xy.x, v1.xy.y, v1.arr[0].x, v1.arr[0].y, v1.arr[1].x, v1.arr[1].y );
printf("v2.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v2.a, v2.b, v2.xy.x, v2.xy.y, v2.arr[0].x, v2.arr[0].y, v2.arr[1].x, v2.arr[1].y );
printf("v3.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v3.a, v3.b, v3.xy.x, v3.xy.y, v3.arr[0].x, v3.arr[0].y, v3.arr[1].x, v3.arr[1].y );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zuweisen/Kopieren von Strukturen ===
Strukturen werden über den Namen als 'ganzes' angesprochen, so dass eine Zuweisung als 'ganzes' möglich ist. Bei bspw. einer 12-Byte großen Struktur werden bei Nutzung der Variable die gesamten 12-Byte gelesen/geändert!
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1,var2;
var1=var2; //12-Bytes kopiert
//--> entspricht memcpy(&var1,&var2,sizeof(xyz));
</syntaxhighlight>
Die Zuweisung als 'ganzes' gilt auch bei der Parameterübergabe und -rückgabe von Funktionen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;};
//Funktionsdefinition
struct xyz function(struct xyz par) {
return (struct xyz){par.z,par.y,par.x};
}
//Funktionsaufruf
struct xyz var=function((struct xyz){1,2,3});
//Mit dem Aufruf der Funktion werden 12-Bytes in die Variable par kopiert
//Mit dem Ende der Funktion werden 12-Bytes in die Variable var kopiert
</syntaxhighlight>
Bedenke, dass bei großen Strukturen das Kopieren Rechenzeit benötigt und folglich vermieden werden sollte! Alternativ sollten Zeiger auf Strukturen über- und zurückgeben werden.
Über Compound Literal (siehe Kap. [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]) kann einer Strukturvariablen als 'ganzes' einen neuen Wert zugewiesen werden:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
var1={.a=7}; //KO, Initialisierungsliste kann hier nicht
//angewendet werden
var1=(struct abc){.a=7}; //Wertezuweisung über Compound Literal möglich
</syntaxhighlight>
Formel gesehen entspricht das Compound Literal einer 'unnamed Variable', die als erstes angelegt und initialisiert wird. Der Inhalt dieser Variablen wird im Anschluss der eigentlichen Variable zugewiesen!
=== Prototyp / Deklaration einer Struktur ===
Soll der Datentyp einer Struktur genutzt werden, der erst an weiter hinten liegenden Stellen im Programm definiert wird, so ist wie bei Variablen/Funktionen ein Prototyp/Deklaration notwendig:
<syntaxhighlight lang="C">
struct abc; //Prototyp der Struktur abc
...
struct abc { int a,b,c;}; //Definition der Struktur abc
</syntaxhighlight>
Die Deklaration sagt einzig aus, dass die Struktur später definiert wird, beinhaltet aber nicht die Strukturelemente. Folglich kann auf Basis dieses Prototyps keine Variable definiert werden, sondern einzig ein Zeiger auf solche eine Struktur:
<syntaxhighlight lang="C">
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Anwendung:
* Struktur, welche auf sich selbst verweist (Verkettete Liste)
:<syntaxhighlight lang="C">
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
int main(int argc,char *argv[]) {
struct vl *head=NULL;
struct vl a={.daten="Ele a"};
struct vl b={.daten="Element b"};
struct vl c={.daten="c-Eleent"};
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL; //Zur Kennzeichnung des letzten Elementes
for(struct vl*ptr=head;ptr;ptr=ptr->next)
printf("'%s'\n",ptr->daten);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Entsprechend der objektorientierten Programmierung, wenn alle Attribute der Klasse private sind:
:{| class="wikitable"
|-
! !! class.h
|-
|
||<syntaxhighlight lang="C">
struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
</syntaxhighlight>
|-
! main.c !! class.c
|-
|<syntaxhighlight lang="C">
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
..
//Kein Zugriff auf
//Strukturelemente möglich
return 0;
}
</syntaxhighlight>
||<syntaxhighlight lang="C">
#include "class.h"
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *)
malloc(sizeof(struct class));
this->attr1=10;
*me=this;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
//..
//Kein Zugriff auf Strukturelemente möglich
return 0;
}
|class_h=struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
|class_c=#include "class.h"
#include <stdlib.h> //fuer malloc()
#include <stdio.h> //fuer printf()
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *) malloc(sizeof(struct class));
printf("konstructor called\n");
this->attr1=10;
*me=this;
}
| execCompilerOptions=-Wall class.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Vergleichen von Strukturen ===
Ein Vergleich von Strukturen über den direkten Weg ist nicht möglich. Vielmehr müssen die Strukturelemente händisch verglichen werden:
<syntaxhighlight lang="C">
struct xyz {int inx,y,z;} var1,var2;
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} var1={1,2,3},var2={1,2,3};
int main(int argc,char *argv[]) {
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
printf("Strukturelemente von var1 und var2 identisch\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis
* Bei Rechnerarchitekturen mit nicht ausgerichteter Speicherausrichtung (Alignment) kann ergänzend ein Vergleich über memcmp() erfolgen
=== Speicherplatzbedarf einer Struktur ===
Für jedes Strukturelement wird Speicher entsprechend der Größe des Datentyps reserviert. Der Speicherplatzbedarf der Gesamtstruktur ergibt sich aus der Summe der Strukturelemente:
<syntaxhighlight lang="C">
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
sizeof(var1) //ergibt 12
sizeof(struct xyz) //ergibt 12
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
int main(int argc,char *argv[]) {
printf("sizeof(var1)=%zu Bytes\n",sizeof(var1));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Ermittlung der tatsächlichen Speichergröße einer Struktur erfolgt über den sizeof-Operator:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;} a;
sizeof(a); //=12 OK
sizeof(a.x); //=4 OK
sizeof(struct xyz); //=12 OK
sizeof(struct xyz.x); // KO
//Ist dies dennoch notwendig, so kann dies über den Umweg eines Zeigers
//erfolgen:
sizeof(((struct xyz *)0)->x); //=4 OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x,y,z;
} a;
int main(int argc,char *argv[]) {
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
printf("sizeof(a.x)=%zu Bytes\n",sizeof(a.x));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
printf("sizeof(struct xyz.x)=%zu Bytes\n",sizeof(struct xyz.x));
printf("sizeof(((struct xyz *)0)->x)=%zu Bytes\n",sizeof(((struct xyz *)0)->x));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei Rechnerarchitekturen mit ausgerichteter Speicherausrichtung (Alignment) (siehe {{w|Speicherausrichtung}}) kann der tatsächliche Speicherbedarf größer sein! Hier fügt der Compiler ggf. zwischen den Strukturelemente Füllbytes (Padding Bytes) ein
* Die Reihenfolge der Strukturelemente wird vom Compiler nicht geändert. D.h. die Zuordnung der Speicherstellen zu den Strukturelementen erfolgt in der Definitionsreihenfolge
=== Interne Organisation ===
Compilerintern werden die Strukturelemente über einen Offset dargestellt. Das erste Strukturelement bekommt dabei immer den Offset 0 zugewiesen. Das nachfolgende Element bekommt als Offset die Größe des Datentyps des vorherigen Elementes zugewiesen. Usw.. <br />
Der Compiler setzt den Zugriff auf ein Strukturelement einer (Struktur)Variablen so um, dass er zunächst die Startadresse der Variablen holt und zu dieser den Offset des Strukturelementes addiert. Die Anzahl der zu lesenden/schreiben Bytes ergibt sich aus dem Datentyp des Strukturelementes:
<syntaxhighlight lang="C">
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1; //(Beispielhaft soll var1 die Speicheradressen
//0x100..0x10B belegen). Der Zugriff auf
//die Variable erfolgt immer über die Startadresse
var1.x=7; //Zugriff auf Speicheradresse 0x100+0 (Offset)
var1.y=8; //Zugriff auf Speicheradresse 0x100+4 (Offset)
var1.z=9; //Zugriff auf Speicheradresse 0x100+8 (Offset)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1;
int main(int argc,char *argv[]) {
//Zugriff siehe Compiler
var1.x=7; //mov DWORD PTR var[rip+0],7
var1.y=8; //mov DWORD PTR var[rip+4],7
var1.z=9; //mov DWORD PTR var[rip+8],7
return 0;
} | execCompilerOptions=-Wall|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Offset eines Strukturelementes kann mit dem offsetof-Operator ermittelt werden:
<code>Syntax: offsetof(type,Strukturelement)</code>
Wie beim sizeof-Operator gilt der offsetof-Operator als Konstantenausdruck und der Rückgabedatentyp ist <code>size_t</code>. Zur Nutzung des Operators muss die Header-Datei 'stddef.h' inkludiert werden:
<syntaxhighlight lang="C">
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var1;
offsetof(struct xyz,z) --> 8
offsetof(var1,z) --> KO: Es wird ein Datentyp und
keine Variable erwartet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz{
int x,y,z;
} var1;
int main(int argc,char *argv[]) {
printf("offsetof(struct xyz,x)=%zu Bytes\n",offsetof(struct xyz,x));
printf("offsetof(struct xyz,y)=%zu Bytes\n",offsetof(struct xyz,y));
printf("offsetof(struct xyz,z)=%zu Bytes\n",offsetof(struct xyz,z));
printf("offsetof(var1,z)=%zu Bytes\n",offsetof(var1,z));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Unter Nutzung des offsetof-Operators kann man bei gegebener Adresse eines Strukturelementes auf die Startadresse der zugrundeliegenden Struktur zurückrechnen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1;
int *ptri=&var1.y;
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var={1,2,3};
int *ptri=&var.y;
int main(int argc,char *argv[]) {
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
printf("ptrxyz->x=%d ptrxyz->y=%d ptrxyz->z=%d",ptrxyz->x,ptrxyz->y,ptrxyz->z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dazu wird von der Startadresse des Strukturelementes der Offset abgezogen. Da der offsetof-Operator den Abstand in Bytes zurückgibt, muss der Pointer auf das Strukturelement zuvor ebenfalls in ein 'Byte'-Zeiger gewandelt werden.
Im Linux kernel wird diese Subtraktion über das container_of Makro realisiert:
<syntaxhighlight lang="C">
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
</syntaxhighlight>
Dieses Makro ermöglicht es, bei gegeben Startadresse eines Strukturelementes die Startadresse der zugrundeliegenden Struktur zu berechnen. Anwendung findet dieses Makro bspw. in:
* der objektorientierten Programmierung, um ausgehend vom gegebenen Parent-Element die Startadresse des Child-Elementes zu berechnen:
:<syntaxhighlight lang="C">
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
..
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
printf("parent.attr1=%d parent.att2=%d\n",me->attr1,me->attr2);
printf("child.attr1=%d\n",child->attr1);
}
int main(int argc,char *argv[]) {
struct child obj1;
obj1.attr1=1;
obj1.parent.attr1=2;
obj1.parent.attr2=3;
parent_methode(&obj1.parent);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei verketteten Listen, wenn das Next-Element im Datensatz selbst eingearbeitet ist:
:<syntaxhighlight lang="C">
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(PTR, TYPE, MEMBER) \
((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
vl_t head={NULL};
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
int main(int argc,char *argv[]) {
daten_t obj1={.daten1=1,.daten2=2};
daten_t obj2={.daten1=3,.daten2=4};
vl_addfront(&obj1);
vl_addfront(&obj2);
daten_t *ret=vl_getfront();
printf("%d %d\n",ret->daten1,ret->daten2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Explizites Cast ===
Eine Struktur kann nicht in einen anderen Datentyp und damit auch nicht in einen anderen Strukturdatentyp mit identischen Strukturelementen konvertiert werden:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} xyz;
struct abc {int a,b,c;} abc;
int var;
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} xyz;
struct abc {
int a,b,c;
} abc;
int var;
int main(int argc,char *argv[]) {
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Incomplete Array ===
Das letzte Element einer Struktur kann ein Array ohne Angabe einer Dimensionsgröße sein (Incomplete Array/Flexible Array Member). Bei der Definition einer Variablen von solch einem Datentyp wird in der Tat kein Speicher für das letzte Element reserviert, so dass dies 'händisch' erfolgen muss. Auf das Array kann ungeachtet dessen unproblematisch zugegriffen werden:
<syntaxhighlight lang="C">
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert
//wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert wurde
//Zur Darstellung dieses Sachverhaltes wurde der Sanitizer
//über den Compilerschalter -fsanitize=address aktiviert
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Speicherplatzreservierung für das incomplete Array kann auf zwei verschiedene Arten erfolgen:
* Speicherplatzreservierung für das Incomplete Array über Variableninitialisierung (nur GCC-C und nur im Falle einer globalen Variablen)
:<syntaxhighlight lang="C">
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
int main(int argc,char *argv[]) {
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(ele1)=%zu Bytes\n",sizeof(ele1));
printf("sizeof(ele2)=%zu Bytes\n",sizeof(ele2));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Speicherplatzreservierung für das Incomplete Array über malloc
:<syntaxhighlight lang="C">
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
if(b==NULL)
return printf("malloc failed\n"),1;
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
//zum Beweis Sanitizer über -fsanitize=address eingebunden
free(b);
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Das Incomplete Array bietet sich überall dort an, wo Daten gespeichert werden sollen, deren Größe sich erst zur Laufzeit ergibt.
=== Anwendung ===
Die Nutzung des Datentyps struct empfiehlt sich an vielen Stellen:
* Zusammengehörende Daten zu Kapseln (entsprechend der objektorientierten Programmierung
* Verkette Listen
* Aufgrund der Typsicherheit zur Darstellung von sicherheitskritischen Aufgaben
Siehe Übungsbereich!
=== C++ ===
Der wesentliche Syntax von Strukturen wurde in C++ übernommen. D.h.:
* das abschließende Semikolon
* der Zugriff auf die Strukturelemente
* Speicherplatzreservierung
* die Definition von Variablen mit der Definition des Datentyps
* ...
Ergänzend wurde in C++ der Datentyp class eingeführt, der weitestgehend identisch zu struct ist. Geändert/Hinzugefügt wurden folgende Sachverhalte:
* Classen/Strukturen können Methoden haben
* Operatoren (Zuweisungsoperator, Addition, ...) können überladen werden
* Alle Strukturelemente (und Methoden) einer struct sind per default public
* Alle Attribute (und Methoden) einer Class sind per default private
* Zur Nutzung des Datentyps ist das führende struct nicht notwendig (dies bedingt dann auch, dass der Strukturdatentyp kein separater Namensraum ist)
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var_xyz;
</syntaxhighlight>
* Initialisierungswerte für Strukturelemente und Klassenattribute bei der Datentypbeschreibung angegeben werden können:
:<syntaxhighlight lang="C++">
struct xyz {
int x=3;
int y=1;
int z;
};
xyz var={7}; //var.x=7 var.y=1 var.z=0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x=3;
int y=1;
int z;
};
int main(int argc,char *argv[]) {
xyz var={7}; //var.x=7 var.y=1 var.z=0
printf("var.x=%d var.y=%d var.z=%d\n",var.x,var.y,var.z);
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In C++ kann eine Struktur ebenfalls über 'designated initializers' initialisiert werden. Jedoch muss die Reihenfolge der Initialisierungselement identisch zur Datentypdefinition sein. Auch ist keine Doppeltbenennung erlaubt:
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x,y,z;
};
int main(int argc,char *argv[]) {
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
(void)var1;
(void)var2;
(void)var3;
(void)var4;
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Union ==
Ähnlich wie eine Struktur ist ein Union ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wird. Bei sog. Union beginnen jedoch alle Komponenten nicht wie bei Strukturen an nacheinander folgenden Speicheradressen, sondern an der identischen Speicheradresse, d.h. ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union kann folglich zu einem Zeitpunkt nur ein Element enthalten. Der benötigte Speicherplatz ergibt sich aus der größten Komponente.
<code>Syntax: union Unionname<sub>Opt</sub> {Datentyp Variablenname; …}<sub>Opt</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Schutz/Zugriffssteuerung der Unionelemente ist nicht vorhanden. Es kann in beliebiger Reihenfolge auf die einzelnen Elemente zugegriffen werden.
Die Anwendung ist identisch wie bei Strukturen, so dass im Folgenden nur die Abweichungen zu den Strukturen beschrieben werden.
=== Speicherplatzbedarf und interne Struktur einer Union ===
Die Größe der Union ergibt sich aus dem größtem Unionelement. Alle Unionelemente überlappen sich, so dass der Offset zum Basiselement 0 ist:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird ein kleineres Unionelement belegt und im Anschluss ein größeres Unionelement gelesen, so ist der Inhalt der durch das kleinere Element nicht beschriebenen Speicherstellen undefiniert:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc.a=0x11;
printf("%08x",abc.c);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
};
void foo(int var) {
int lok=var;
printf("Foo(%#08x) called\n",lok);
}
void bar(void) {
union abc abc;
abc.a=0x11;
printf("abc.a=%#02x\n",abc.a);
printf("abc.c=%#08x\n",abc.c);
}
int main(int argc,char *argv[]) {
//Zur Darstellung des Phänomens muss
//erstmal der Stack mit Daten belegt werden!
foo(0x12345678);
bar();
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Union ===
Bei einer Union kann nur ein Element initialisiert werden, d.h. die Initialisierungsliste kann nur einen Wert beinhalten. Ohne explizite Benennung des Unionelementes in der Initialisierungsliste wird das erste Element aus der Datentypbeschreibung initialisiert. Mit expliziter Benennung mittels 'designated initializers' können auch andere Elemente initialisiert werden:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Anwendung ===
Mittels des Datentyps union können diverse Anwendungsfälle abgedeckt werden:
* Über Union lassen sich größere Datentypen in kleinere Datentypen unterteilen, um z.B. einzelne Bytes zu extrahieren:
<syntaxhighlight lang="C">
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union floatu var={1.234};
printf("%f\n",var.var); //Darstellung des Float-Wertes
printf("%x\n",var.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var.byte[0],var.byte[1],var.byte[2],var.byte[3]);
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
union longlong var2={0x123456789ABCDEFULL};
printf("%llx\n",var2.ll);
printf("%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
int main(int argc,char *argv[]) {
union floatu var1={1.234};
printf("var1.var=%f\n",var1.var); //Darstellung des Float-Wertes
printf("var1.hex=%x\n",var1.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("var1.byte[0..3]=%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var1.byte[0],var1.byte[1],var1.byte[2],var1.byte[3]);
union longlong var2={0x123456789ABCDEFULL};
printf("var2.ll=%llx\n",var2.ll);
printf("var2.i[0..1]=%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Ein weiterer Anwendungsfall ergibt sich, wenn in einer Struktur unterschiedliche Datensätze gespeichert werden sollen (siehe {{w|Tagged Union}}):
:<syntaxhighlight lang="C">
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
int main(int argc,char *argv[]) {
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mittels eines Tagged Union kann komfortabel ein Binärbaum realisiert werden:
:<syntaxhighlight lang="C">
//Quelle: https://github.com/Hirrolot/datatype99
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h> //fuer printf()
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Die Eigenschaften des Datentyps union entsprechen den Eigenschaften des Datentyps struct in C++.
== Enum/Aufzählungstyp ==
Nach dem Wikipedia Artikel {{w|Aufzählungstyp}} ist ''ein Aufzählungstyp (englisch enumerated type) ein Datentyp für Variablen mit einer endlichen Wertemenge. Alle zulässigen Werte des Aufzählungstyps werden bei der Deklaration des Datentyps mit einem eindeutigen Namen (Identifikator) definiert, sie sind Symbole.''
<code>Syntax: enum enumname<sub>Opt</sub> {definition-list[=expression]}<sub>Opt</sub> Variablenliste<sub>Opt</sub></code>
Die Anwendung ist identisch wie bei Strukturen, so dass nachfolgend nur die Abweichungen zu den Strukturen beschrieben werden.
=== Datentyp von enum ===
In C entspricht der Datentyp Enum dem Datentyp <code>int</code> so dass Zuweisungen/Vergleiche mit Ganzzahlen möglich sind. Ganzzahloperationen funktionieren ebenso:
<syntaxhighlight lang="C">
enum STATUS {OK,KO=5}; //Definition des Datentyps
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
status++;
status=5.7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum STATUS {OK,KO=5}; //Definition des Datentyps
int main(int argc,char *argv[]) {
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
printf("status == 5\n");
status++;
status=5.7;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Enumelemente ===
Die Elemente der Definitionsliste sind Integerkonstanten. Diese können auch in Kombination mit anderen Datentypen genutzt werden. Auch gibt es keinen gesonderten Namensraum für Elemente der Definitionsliste. Sie 'konkurrieren' folglich mit allen Variablen- und Funktionsnamen:
<syntaxhighlight lang="C">
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
int main(int argc,char *argv[]) {
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der erste Enumelement der Definitionsliste bekommt den Wert 0 zugewiesen. Folgeelemente bekommen den Wert des Vorgängerelementes +1 zugewiesen.
Enumelemente können mit einer Konstanten (und Konstantenausdruck) initialisiert werden:
<syntaxhighlight lang="C">
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
int main(int argc,char *argv[]) {
printf("bill=%d john=%d, fred=%d\n",bill,john,fred);
printf("error=%d warning=%d info=%d ok=%d\n",error,warning,info,ok);
printf("Ostfalia=%d Wolfenbuettel=%d\n",Ostfalia,Wolfenbuettel);
printf("test=%d\n",test);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Es empfiehlt sich, die Enumelemente in GROSSBUCHSTABEN zu schreiben. Hiermit wird gekennzeichnet, dass es sich um Konstanten und nicht um Variablen/Funktionen handelt
=== Anwendung ===
Die Nutzung des Datentyps enum empfiehlt sich überall dort, wo eine Fallunterscheidung notwendig ist:
* Statusrückgabe von Funktionen:
:<syntaxhighlight lang="C">
enum STATUS {OK,MEMORY_OVERFLOW, DIVISION_BY_ZERO};
enum STATUS funct(…) {
return MEMORY_OVERFLOW;
}
</syntaxhighlight>
* Beschreibung der Zustände und der Ereignisse eines Zustandsautomates:
:<syntaxhighlight lang="C">
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Ergänzend zu den Abweichungen bei Structs sind hier weitere Unterscheidungsmerkmale vorhanden:
* Enums stellen einen eigenen Datentyp dar, der nicht mit int kompatible ist. Das bedingt unter anderem, dass einige Operatoren wie z.B. ++ nicht mehr auf Variablen des Datentyps enum angewendet werden. Die Enumelemente als solches sind jedoch kompatibel zum Ganzzahldatentyp:
:<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
int main(int argc,char *argv[]) {
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
printf("RED==2\n");
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
* Auch enums können Methoden besitzen.
* Über Operatorüberladung können z.B. nicht vorhandene Operatoren wie ++/-- ergänzt werden
* Über unscoped/scoped Enumerations wird der 'Namensraum' gesteuert:
:* Unscoped Enumeration (Elemente der Definitionsliste stehen wie bei C im Zugriff)
::<code>Syntax: enum name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE };
Color r = RED;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE };
Color r = RED;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
:* Scoped enumeration (Elemente der Definitionsliste haben einen eigenen 'Namensraum')
::<code>Syntax: enum '''class|struct''' name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
== Bitfelder ==
Nach dem Wikipediaartikel {{w|Bitfeld}} ''bezeichnet in der Informationstechnik und Programmierung ein Bitfeld ein vorzeichenloses Ganzzahldatentyp, in dem einzelne Bits oder Gruppen von Bits aneinandergereiht werden. Es stellt eine Art Verbunddatentyp auf Bit-Ebene dar. Im Gegensatz dazu steht der primitive Datentyp, bei dem der Wert aus allen Stellen gemeinsam gebildet wird.''
Der Syntax entspricht dem struct-Syntax, mit der Ergänzung, dass hinter den Strukturelementen noch die Bitbreite getrennt durch ein Doppelpunkt angegeben wird:
<syntaxhighlight lang="C">
struct time {
unsigned int hour: 5; //0..23 Bits 0..4
unsigned int minute: 6; //0..59 Bits 5..10
Unsigend int second: 6; //0..59 Bits 11..16
} myTime;
</syntaxhighlight>
Als mögliche Datentypen für die Strukturelemente stehen nur die Ganzzahldatentypen <code>int</code>, <code>short</code>, <code>long</code> , <code>long long</code> und <code>char</code> zur Verfügung. Der Datentyp eines Strukturelementes muss mindestens die Anzahl der Bits enthalten, wie diese über die Bitbreite gefordert wird.
Von den Strukturelementen kann keine Adresse bestimmt werden! Auch der <code>offsetf</code> - Operator schlägt fehl.
Der Datentyp entspricht im Wesentlichen einem Ganzzahlzahldatentyp, so dass bei Zugriff auf eine Variable dieses Datentyps eine Ganzzahl gelesen/geschrieben wird. Bei Zugriff auf die einzelnen Strukturelemente werden die entsprechenden Bits dieser Ganzzahlvariablen maskiert, so dass nur die betroffenen Bits geändert werden:
<syntaxhighlight lang="C">
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) | (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) | ((second&0b00001111)<<2);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
//Nachweis am besen über den Maschinensprachevergleich!
int main(int argc,char *argv[]) {
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) {{!}} (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) {{!}} ((second&0b00001111)<<2);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
h=c
}} Öffnen im Compiler Explorer] }}
=== Anwendung===
* Komprimierte Speicherung der Uhrzeit (wie dies z.B. in Realtimeclocks erfolgt)
:<syntaxhighlight lang="C">
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
int main(int argc,char *argv[]) {
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Aufteilung von FloatingPoint Zahlen in seine Komponenten
:<syntaxhighlight lang="C">
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
int main(int argc,char *argv[]) {
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",
(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Bitfelder existieren mit den bekannten Ergänzungen auch in C++.
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
9nwst0b7bocwxdrizxwfk230h7dgufy
1090844
1090843
2026-09-15T08:14:12Z
D. Justen
102048
Formatierung geändert
1090844
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C kennt nachfolgende grundlegende Datentypen und Zeiger auf diese Datentypen (siehe auch [[Programmieren in C/C++: Grundlagen# Grundlegende Datentypen und Typsicherheit| Grundlagen:Grundlegende Datentypen und Typsicherheit]])
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| [[#Ganzzahl Datentypen|Ganzzahl]] ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| [[#Gleitkomma Datentypen|Gleitkommazahl]] ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Array|Arrays]] ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| [[#Struktur/Verbundtyp|Strukturen]]/[[#Union|Unions]] ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| [[#Enum/Aufzählungstyp|Aufzählungstyp]] ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Grundlagen #Boolescher-Datentype/Operatoren|Boolescher Datentyp]] ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| [[#Komplexe Zahlen|Komplexe Zahlen]] ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
Bis auf die Datentypen Funktionen, Array und die Zeiger sollen die wesentlichen Aspekte dieser Datentypen im nachfolgenden beschrieben werden.
'''Der grundlegende Datentyp ist <code>int</code>!'''
* Es wird mit nichts Kleinerem gerechnet als mit dem Datentyp <code>int</code> (siehe [[#Implizite Typumwandlung | Implizite Typumwandlung]]) :
:<syntaxhighlight lang="C">
char var1=10,var2=20,var3;
var3=var1+var2; //Addition findet auf Basis des Datentyps int statt
</syntaxhighlight>
* Es gibt zwar den Booleschen Datentyp, dieser entspricht jedoch einem Ganzzahldatentyp und <code>true</code> und <code>false</code> entsprechen den Integerwerten 0 und 1
* Der Aufzählungsdatentyp und seine Aufzählungselemente sind vom Datentyp <code>int</code>
* Bis einschl. C90 wurde bei der Definition von Variablen ohne Angabe des Datentyps, bei Definition einer Funktion ohne Angabe des Datentyps der Übergabeparameter, des Rückgabedatentyps der Datentyp implizit auf int gesetzt ('''implizit int''')
:<syntaxhighlight lang="C">
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}int main(int argc,char *argv[]) {
printf("%d",foo(1,var2));
return 0;
} | execCompilerOptions=-Wall -std=c90|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Ganzzahl Datentypen ==
Grundlegend kennt die Programmiersprache C nur zwei Ganzzahldatentypen:
* Datentyp: <code>int</code>
: Vorzeichenbehafteter (signed) Datentyp, dessen Bitbreite von der Rechnerarchitektur und des Compilers abhängig ist
* Datentyp <code>char</code>
: Datentyp mit einer Mindestbreite von 8-Bit u.A. zur Speicherung von Zeichen typischerweise im ASCII Format. Die C-Spezifikation [C11 6.2.5 Types] lässt es dem Compiler frei, ob <code>char</code> als vorzeichenbehafteter oder vorzeichenloser Datentyp implementiert wird.
: Ergänzend kann der Datentyp <code>char</code> auch zur Speicherung von ganzen Zahlen genutzt werden. In diesem Fall empfiehlt sich, diese explizit als <code>signed</code> und <code>unsiged</code> zu definieren. Wenn nur ASCII Zeichen gespeichert werden, so ist diese Angabe nicht nötig!
Optional können Qualifier dem Datentyp vorangestellt werden:
* <code>unsigned</code> / <code>signed</code> zur Angabe, ob der Inhalt als vorzeichenlose Zahl oder als vorzeichenbehaftete Zahl zu interpretieren ist. Ohne Angabe sind Variablen vom Datentyp <code>int</code> vorzeichenbehaftet
* <code>short</code> / <code>long</code> / <code>long long</code> (letzteres seit C99) als vorangestellten Qualifier zu <code>int</code> zur Vergrößerung/Verkleinerung der Bitbreite. Bei Angabe des Qualifiers ist das Schlüsselwort <code>int</code> optional. Die Beschreibung <code>long long int</code> und <code>long long</code> sind gleichbedeutend!
Als Bitbreite für die Datentypen ist im C-Standard nur ein Mindestbreite definiert. Die genaue Bitbreite hängt von der Rechenbreite des Systems und vom Compiler ab (siehe [C11 6.2.5 Types]):
{| class="wikitable"
|-
! Datentype !! Mindest<br />breite !! Typisch bei 32-Bit<br />Architektur !! Typisch bei 64-Bit<br />Architektur !! printf Format<br />Anweisung
|-
| <code>char</code> || 8 || 8 || 8 || <code>%c</code>
|-
| <code>signed char</code><br /><code>unsigned char</code>|| 8 || 8 || 8 || <code>%hhd</code><br /><code>%hhu</code>
|-
| <code>short</code><br /><code>short int</code>|| 16 || 16 || 16 || <code>%hd</code> / <code>%hu</code>
|-
|<code>int</code>|| 16 || 16/32 || 32 || <code>%d</code> / <code>%u</code>
|-
|<code>long</code><br /><code>long int</code>|| 32 || 32 || 32/64 || <code>%ld</code> / <code>%lu</code>
|-
|<code>long long</code><br /><code>long long int</code>|| 64 || 64 || 64 || <code>%lld</code> / <code>%llu</code>
|}
In der Header-Datei <code>limits.h</code> sind die tatsächlichen Grenzwerte der Datentypen gespeichert:
{| class="wikitable"
|-
! Konstante !! Beschreibung !! Typ. bei 64-Bit Architektur
|-
| <code>CHAR_BIT</code> || Anzahl der Bits in einem Char || 8
|-
| <code>SCHAR_MIN</code> || min. Wert, den der Typ bei signed char aufnehmen kann || -128
|-
| <code>SCHAR_MAX</code> || max. Wert, den der Typ bei signed char aufnehmen kann || 127
|-
| <code>UCHAR_MAX</code> || max. Wert, den der Typ bei unsigned char aufnehmen kann || 255
|-
| <code>CHAR_MIN</code> || min. Wert, den der Typ char aufnehmen kann || 0 oder SCHAR_MIN
|-
| <code>CHAR_MAX</code> || max. Wert, den der Typ char aufnehmen kann || SCHAR_MAX oder UCHAR_MAX
|-
| <code>SHRT_MIN</code> || min. Wert, den der Typ short int annehmen kann || -32.768
|-
| <code>SHRT_MAX</code> || max. Wert, den der Typ short int annehmen kann || 32.767
|-
| <code>USHRT_MAX</code> || max. Wert, den der Typ unsigned short int annehmen kann || 65.535
|-
| <code>INT_MIN</code> || min. Wert, den der Typ int annehmen kann || -2.147.483.648
|-
| <code>INT_MAX</code> || max. Wert, den der Typ int annehmen kann || 2.147.483.647
|-
| <code>UINT_MAX</code> || max. Wert, den der Typ unsigned int aufnehmen kann || 4.294.967.296
|-
| <code>LONG_MIN</code> || min. Wert, den der Typ long int annehmen kann || -2.147.483.648 oder<br />-9.223.372.036.854.775.808
|-
| <code>LONG_MAX</code> || max. Wert, den der Typ long int annehmen kann || 2.147.483.647 oder<br />9.223.372.036.854.775.807
|-
| <code>ULONG_MAX</code> || max. Wert, den der Typ unsigned long int annehmen kann || 4.294.967.296 oder<br />18.446.744.073.709.551.616
|-
| <code>LLONG_MIN</code> || min. Wert, den der Typ long long int annehmen kann || -9.223.372.036.854.775.808
|-
| <code>LLONG_MAX</code> || max. Wert, den der Typ long long int annehmen kann || 9.223.372.036.854.775.807
|-
| <code>ULLONG_MAX</code> || max. Wert, den der Typ unsigned long long int annehmen kann || 18.446.744.073.709.551.615
|}
Aufgrund dessen, dass die Breite der Datentypen von der Rechnerarchitektur und vom Compiler abhängig ist, sind in der Header-Datei <code>stdint.h</code> Aliase für Datentypen enthalten, welche in ihrem Alias die tatsächliche Breite und das Vorzeichens beinhalten:
<syntaxhighlight lang="C">
uint8_t --> unsigned 8-Bit
int8_t --> signed 8-Bit
uint16_t --> unsigned 16-Bit
int16_t --> signed 16-Bit
...
</syntaxhighlight>
In C++ sind diese Aliase im <code>std</code> namespace definiert:
<syntaxhighlight lang="C++">
std::intptr_t
std::int8_t std::uint8_t
std::int16_t std::uint16_t
std::int32_t std::uint32_t
Std::int64_t std::uint64_t
</syntaxhighlight>
Zur Erzeugung von portablen/rechnerunabhängigen Programmen empfiehlt sich, diese Datentypen zu nutzen. Die Rechenbreite ist dann unabhängig vom Compiler und Betriebssystem.
== Gleitkomma Datentypen ==
Gleitkommazahlen werden im Computer auf Basis folgender Schreibweise dargestellt (siehe auch: {{w|Gleitkommazahl}}):<br />
<syntaxhighlight lang="C">
Dezimalsystem Dualsystem
12,3456710 = 1234567 * 10^-5 0,110 = 1,1001100110011 * 2^-4
------- -- --------------- --
Mantisse Exponent Mantisse Exponent
</syntaxhighlight>
;Mantisse: Vorzeichenlose ganze Zahl (ggf. mit einer festen Position des Dezimalpunktes=Festkommazahl)
;Exponent: Vorzeichenbehaftete ganze Zahl, welche um einen Bias verschoben ist
;Vorzeichen: Vorzeichen der (vorzeichenlosen) Mantisse
Zur Speicherung im Computer werden das Vorzeichen, die Mantisse und der Exponent getrennt im Binärformat gespeichert, für den Programmierer aber als eine (zusammenhängende) Zahl dargestellt:
[[File:Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse.png|thumb|400px|center|Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse]]
Gleitkommazahlen haben genauso wie ganze Zahlen einen beschränkten Wertebereich:
* Die Anzahl der Bits der Mantisse bestimmen die Anzahl der Nachkommastellen:
:<syntaxhighlight lang="C">
Bei 23-Bit Mantisse ist die max. Zahl 2^-23-1=0,000000119,
welches 6..7 dezimale Stellen entspricht!
</syntaxhighlight>
* Mit dem Exponent kann 'quasi' der kleinste und der größte Wertebereich angegeben werden:
:<syntaxhighlight lang="C">
Bei 8-Bit Exponent mit einem Bias von 127 liegt der Wertebereich des
Exponenten im Bereich von -126 … +127 (Exponent -127 und +127 wird zur
Darstellung weitere Zahlen benötigt).
Die kleinste darstellbare Zahl (unter Vernachlässigung der Nachkommastellen der Mantisse ist:
2^-126=1/2^126≅1,175*10^-38
Die größte darstellbare Zahl ist:
2^127 ≅1,7*10^38
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
float sqrtf(float);
float powf(float,float);
#include <ieee754.h>
#include <complex.h>
union test {
unsigned int i;
float f;
union ieee754_float b;
};
int main(int argc,char *argv[]) {
union test var = {.f=-0.1};
printf("Float=%f Binär=%032b\n",var.f,var.i);
printf("v=0b%b e=0b%08b m=0b(1).%023b\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%10d m=%29d\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%d-%d=%d m=1+%d/2^-23=%f\n",var.b.ieee.negative,
var.b.ieee.exponent,IEEE754_FLOAT_BIAS,var.b.ieee.exponent-IEEE754_FLOAT_BIAS,
var.b.ieee.mantissa,1.0+var.b.ieee.mantissa*1.0/(1<<23));
printf("\n--- Beispiele von Genauigkeitsprobleme im Umgang mit Gleitkommazahlen (hier float) ----\n");
printf("powf(sqrtf(%1.8f),2) = %1.8f\n",2.0f,powf(sqrtf(2.0f),2));
printf("%f + %f = %f\n",2000.0,0.0004,(double)(2000.0f+0.0004f));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Grundlegend kennen die Programmiersprachen C/C++ folgende Gleitkommadatentypen:
* Datentyp: <code>float</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindesten 6 Stellen betragen, so dass der Datentyp typischerweise 32-Bit groß ist
* Datentyp: <code>double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, so dass der Datentyp typischweise 64-Bit Große ist
* Datentyp: <code>long double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, damit könnte dieser Datentyp gleich dem Datentyp <code>double</code> gesetzt werden. In der Tat ist die Datenbreite Rechner- und Compilerabhängig. Einige Compiler setzen diesen Datentyp identisch zu <code>double</code>, bei x86 Prozessoren wird aufgrund der Hardwareunterstützung 80-Bit genutzt (wobei in der Tat der Datentyp aufgrund von alignment dann 16-Byte Speicherplatz beansprucht) und einige Systeme nutzen 128-Bit (wobei hier aufgrund ggf. fehlender Hardwareunterstützung Operationen mit diesem Datentyp per Software emuliert werden) (siehe Wikipedia Artikel {{w|lang=en|Long_double|long double}}).
Die genaue Darstellung (Anzahl der Bits für Mantisse und Exponent, Darstellung von NAN/INF, ….) ist in C nicht spezifiziert und somit compiler- und rechnerabhängig. Zumeist wird mittlerweile die {{w|IEEE 754}} Standardisierung genutzt (Norm wurde von Intel mit der Entwicklung der 8087 FPU entworfen).
Grunddatentypen und der Wertebereich (nach {{w|IEEE 754}})
{| class="wikitable"
|-
! Daten-<br/>type !! Speicher-<br />platz !! Exponent !! Mantisse !! Größte Zahl !! Kleinste Zahl !! Genauigkeit !! printf Format Anweisung
|-
| binary32→<code>float</code> || 4 Byte || 8 bit || 23 bit || ~3,4*10<sup>38</sup> || ~1,2*10<sup>-38</sup> || 7..8 Stellen || ---
|-
| binary64→<code>double</code> || 8 Byte || 11 bit || 52 bit || ~1,8*10<sup>308</sup> || ~2,2*10<sup>-308</sup> || 15..16 Stellen || %f %e %g
|-
| binary64 extended→<code>long double</code> || ≥10 Byte || ≥15 bit || ≥63 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 19..20 Stellen || %Lf %Le %Lg
|-
| binary128→<code>long double</code> || 16 Byte || 15 bit || 112 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 34 Stellen || %Lf %Le %Lg
|}
Die tatsächliche Auflösung der Datentyps kann auf Basis nachfolgender Konstanten, definiert in der Header-Datei <code>float.h</code>, ermittelt werden:
:<syntaxhighlight lang="C">
FLT_DIG --> Anzahl der dezimalen Nachkommastellen für float
DBL_DIG --> Anzahl der dezimalen Nachkommastellen für double
LDBL_DIG --> Anzahl der dezimalen Nachkommastellen für long double
FLT_MIN_10_EXP --> Minimaler Exponent zur Basis 10
DBL_MIN_10_EXP
LDBL_MIN_10_EXP
FLT_MAX_10_EXP --> Maximaler Exponent zur Basis 10
DBL_MAX_10_EXP
LDBL_MAX_10_EXP
LDBL_MANT_DIG --> Anzahl der Bits für die Mantisse
LDBL_MANT_DIG
LDBL_MANT_DIG
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <float.h>
int main(){
printf("FLT_DIG =%u\n",FLT_DIG);
printf("DBL_DIG =%u\n",DBL_DIG);
printf("LDBL_DIG =%u\n",LDBL_DIG);
printf("FLT_MIN_10_EXP =%d\n",FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP =%d\n",DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP=%d\n",LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP =%d\n",FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP =%d\n",DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP=%d\n",LDBL_MAX_10_EXP);
printf("FLT_MANT_DIG =%d\n",FLT_MANT_DIG);
printf("DBL_MANT_DIG =%d\n",DBL_MANT_DIG);
printf("LDBL_MANT_DIG =%d\n",LDBL_MANT_DIG);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Aufgrund des nicht standardisierten Formates sollte ein Gleitkommadatentyp nicht im Binärformat für den Datenaustausch (mit Netzwerk, über Dateien, ..) genutzt werden. Andere Rechnersysteme/Programmiersprachen würde aufgrund der anderen Interpretation andere Zahlenwerte aus den übertragenen/gespeicherten Binärdaten auslesen!
<syntaxhighlight lang="C">
float var1;
write(file_hdl,&var1,sizeof var1); //Schreiben des Binärwertes
//in eine Datei
double var2;
send(socket_hdl,&var2,sizeof var2,0);//Senden des Binärwertes
//über ein Netzwerk
</syntaxhighlight>
Die Standard-C-Library bietet einige mathematische Funktionen wie <code>sin() / cos() / tan() / atan2() / sqrt() / pow() / exp()/…</code> an. Die Prototypen dieser Funktion sind in der Header-Datei <code>math.h</code> beschrieben, so dass diese bei Nutzung dieser Funktion zu inkludieren ist. Ergänzend ist die Shared Library libm.so über den Compilerschalter '-lm' einzubinden:
<syntaxhighlight lang="C">
#include <math.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
double sqrt(double);
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
printf("var1=%f var2=%f\n",var1,var2);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen basieren auf den Datentyp <code>double</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist vom Datentyp <code>double</code>. Die Prototypen sehen wie folgt aus:
<syntaxhighlight lang="C">
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double); //Wertebereich der Rückgabe von -PI/2..+PI/2
double atan2(double,double); //Wertebereich der Rückgabe von -Pi .. +PI
double sqrt(double);
double log(double);
</syntaxhighlight>
Über den Suffix f oder l im Funktionsnamen kann der zugrundeliegende Datentyp auf <code>float</code> (Suffix f) oder <code>long double</code> (Suffix l) geändert werden:
<syntaxhighlight lang="C">
float sinf(float);
long double sinl(long double);
</syntaxhighlight>
Ergänzend zu den Prototypen sind die gebräuchlichen Naturkonstanten in <code>math.h</code> definiert (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
M_E Value of e
M_LOG2E Value of log_2 e
M_LOG10E Value of log_10 e
M_LN2 Value of log_e 2
M_LN10 Value of log_e 10
M_PI Value of π
M_PI_2 Value of π/2
M_PI_4 Value of π/4
M_1_PI Value of 1/π
M_2_PI Value of 2/π
M_2_SQRTPI Value of 2/√π
M_SQRT2 Value of √2
M_SQRT1_2 Value of 1/√2
</syntaxhighlight>
Gleitkommazahlen können nicht nur Zahlenwerte, sondern auch Sonderwerte annehmen. Diese Sonderwerte sind ebenfalls in <code>math.h</code> beschrieben (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
INFINITY A constant expression of type float representing
positive or unsigned infinity, if available; else a
positive constant of type float that overflows at
translation time.
NAN A constant expression of type float representing a
quiet NaN. This macro is only defined if the
implementation supports quiet NaNs for the float type.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <math.h>
//Quelle: https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c
#ifdef NAN
#define NAN_STR "NAN is supported"
#else
#define NAN_STR "NAN is not supported"
#endif
#ifdef INFINITY
#define INFINITY_STR "INFINITY is supported"
#else
#define INFINITY_STR "INFINITY is not supported"
#endif
int main(int argc, char *argv[argc]) {
printf("%s\n%s\n",NAN_STR,INFINITY_STR);
double x=0.0;
double y=1/x;
printf("1/%e -> %e\n",x,y);
if(y==INFINITY)
printf("1) Initinity\n");
if(isinf(y)) //besser
printf("2) Initinity\n");
printf("%llx\n%llx\n\n",*(long long *)&y,INFINITY);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
double z=-(x/x);
printf("%e/%e -> %e\n",x,x,z);
if(z == NAN) //funktioniert nicht
printf("1) Not a Number\n");
if(isnan(z)) //besser
printf("2) Not a Number\n");
if(z != z)
printf("3) Not a Number\n");
printf("%llx\n%llx",*(long long *)&z,NAN);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
return 0;
} | execCompilerOptions=-lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit <code>fesetround()/fegetround()</code> kann gesetzt/gelesen werden, wie mit Ergebnissen umzugehen sind, die nicht exakt darstellbar sind. Mögliche Werte sind 'round to nearest' (default), 'round up', 'round down' und 'round toward zero'.
== Komplexe Zahlen ==
Nach dem Wikipedia Artikel {{w|komplexe Zahlen}} ''stellen komplexe Zahlen eine Erweiterung der reellen Zahlen dar. Ziel der Erweiterung ist es, algebraische Gleichungen wie x<sup>2</sup>+1=0 bzw. x<sup>2</sup>=-1 lösbar zu machen. ... Da die Quadrate aller reellen Zahlen größer oder gleich 0 sind, kann die Lösung der Gleichung x<sup>2</sup>=-1 keine reelle Zahl sein. Man braucht eine ganz neue Zahl, die man üblicherweise i nennt, mit der Eigenschaft i<sup>2</sup>=-1. Diese Zahl i wird als imaginäre Einheit bezeichnet.
Komplexe Zahlen werden nun als Summe a+b*i definiert, wobei a und b reelle Zahlen sind und i die oben definierte imaginäre Einheit ist.''<br />
Der Datentyp für komplexe Zahlen (erst ab C99 enthalten) beinhaltet folglich zwei Gleitkommazahlen, eine für den reelen Teil und eine für den imaginären Teil. Entsprechend den Gleitkommazahlen steht der komplexe Datentyp ebenfalls in drei unterschiedlichen Genauigkeiten zur Verfügung:
{| class="wikitable"
|-
! Datentype !! Speicherplatz
|-
| <code>float _Complex</code> || 2x4Byte
|-
| <code>double _Complex</code><br /><code>_Complex</code> || 2x8Byte
|-
| <code>long double _Complex</code> || 2x10Byte
|}
Wie auch beim Booleschen Datentyp ist in der Header-Datei <code>complex.h</code> für den einfacheren Umgang mit diesem Datentyp das Makro <code>complex</code> als Textersetzung für <code>_Complex</code> gesetzt.
Zur Darstellung von komplexen Konstanten wurde die Gleitkommakonstante um den Suffix i ergänzt. Durch Anhängen von i wird aus dem ansonsten rellen Teil der imaginäre Teil und damit aus der Gleitkommakonstante eine komplexe Gleitkommakonstante:
<syntaxhighlight lang="C">
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Normale Gleitkommavariablen werden als reellen Teil einer komplexen Zahl angesehen. Bei Operationen von Gleitkommazahlen und komplexen Zahlen wird der imaginäre Teil der Gleitkommazahl auf 0 gesetzt. Beim Zuweisen einer komplexen Zahl an eine Gleitkommazahl wird nur der reele Teil 'gelesen'.<br />
Soll eine Gleitkommavariablen zu einem imaginären Teil gewandelt werden, so muss diese bspw mit der Konstanten 1.0i multipliziert werden:
<syntaxhighlight lang="C">
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C-Library bietet diverse mathematische Funktionen wie csin(), ccos(), csqrt(), cpow() und ergänzend Umrechnungsfunktionen von Gleitkommazahlen in komplexe Zahlen (und umgedreht) wie creal(),cimag() ,cabs() für den Umgang mit komplexen Zahlen an:
<syntaxhighlight lang="C">
double _Complex csin(double _Complex);
double _Complex csqrt(double _Complex);
double creal(double _Complex);
double cimag(double _Complex);
</syntaxhighlight>
Zur Nutzung dieser Funktionen muss die Header-Datei <code>complex.h</code> inkludiert und ergänzend die Shared Library libm.so über den Compilerschalter '-lm' eingebunden werden.
<syntaxhighlight lang="C">
#include <complex.h>
//Math-Library mittels Linker-Command '-lm' einbinden
int main(int argc, char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen beruhen auf den Datentyp <code>double _Complex</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist <code>double _Complex</code> resp. <code>double</code> (bei den Umrechnungsfunktionen). Über den Suffix f und l im Funktionsnamen kann der zugrundeliegende Datentyp geändert werden:
<syntaxhighlight lang="C">
float crealf(float _Complex z);
long double creall(long double _Complex z);
</syntaxhighlight>
Hinweis:
* Der Datentyp <code>_Complex</code> und die dazugehörigen mathematischen Funktionen sind in der C-Spezifikation als optional gekennzeichnet.
== Generische mathematische Funktionen ==
In der <code>tgmath.h</code> Header Datei sind für die mathematischen Funktionen Makros enthalten, welche den Datentyp der Übergabeparameter bestimmen und basierend auf den Datentyp die dazugehörige mathematische Funktion aufrufen.
<code>tgmath.h</code> selbst inkludiert <code>math.h</code> und <code>complex.h</code>, so dass diese nicht weiter zu inkludieren sind.
Steht für den Übergabedatentyp keine passende Funktion zu Verfügung, so ist das Verhalten des Makros undefiniert (bspw. wenn ein komplexes Argument an eine Funktion übergeben wird, die nur für Gleitkommazahlen ausgelegt ist <code>ceil(1+2i);</code> )
Folgendes Regelwerk wird angewendet:
* Ist einer der Übergabeparameter imaginär, so ist die ausgewählte Funktion in der Spezifikation der Funktion beschrieben
* Ist einer der Übergabeparameter Komplexe, so wird die Komplexe Variante der Funktion aufgerufen, andernfalls die Gleitkomma Variante
* Ist einer der Übergabeparameter vom Datentyp <code>long double</code>, so wird die <code>long double</code> Variante, bei integer und double die <code>double</code> Variante und andernfalls die <code>float</code> Variante aufgerufen
Beispiel:
<syntaxhighlight lang="C">
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
int main(int argc,char *argv[]) {
foo(1l+1li,2.0l,3.0f,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=c
}} Öffnen im Compiler Explorer] }}
== Boolschescher Datentyp ==
Siehe [[Programmieren in C/C++: Grundlagen#Boolescher-Datentype/Operatoren|Grundlagen: Boolescher-Datentype/Operatoren]]
== void / unvollständiger Datentype ==
Der Datentyp <code>void</code> dient vorrangig dazu, nicht vorhandene Über- und Rückgabewerte von Funktionen anzuzeigen. Eine Variable vom Datentyp <code>void</code> kann nicht angelegt werden. Ein Zeiger vom Datentyp <code>void</code> ist möglich, kann aber nicht dereferenziert werden (siehe Kap. [[Programmieren in C/C++: Zeiger #Void-Zeiger| Zeiger:Void-Zeiger]])
<syntaxhighlight lang="C">
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* <code>sizeof(void)</code> ist nach der C-Spezifikation nicht erlaubt. Dennoch geben viele Compiler hier den Wert 1 zurück!
* Mit einem expliziten Cast auf den Datentyp void wird dem Compiler mitgeteilt, dass diese Variable in Gebrauch ist, der Wert in dieser Operation aber nicht genutzt wird. Hierüber kann die Compilerwarning 'unused Variable' unterbunden werden:
:<syntaxhighlight lang="C">
void func(int par1, int par2) {
int var1=12;
int var2=13;
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int par1, int par2) {
int var1=12;
int var2=13;
int var3=14; //Nicht genutzte Variable
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
printf("Genutzt\n");
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Datentypkonvertierung ==
Für das Rechnen/Vergleichen müssen beide Operatoren vom identischen Datentyp sein! Sind diese nicht identisch, so müssen die Datentypen 'angeglichen' werden. Dies kann einerseits ‚automatisch‘ mittels 'implizierter' Typumwandlung oder ‚manuell‘ mittels ‚expliziter' Typumwandlung erfolgen.<br />
Beim Zuweisungsoperator (inkl. Parameterzuweisung bei Funktionsaufrufen und Funktionsrückgabewerte mittels return) gilt dies ebenso, nur dass hier der Quelldatentyp an den Zieldatentyp angepasst werden muss. Die impliziten Regeln finden hier keine Anwendung.
Hinweis:
* Empfehlenswert ist, die Datentypen der Variablen so zu wählen, dass der Compiler keine implizite Typumwandlung tätigt. Kann dies nicht vermieden werden, so sollte die explizite Typumwandlung genutzt werden (um sich einen möglichen Datenverlust bewusst zu machen)
* Der Datentyp selbst sollte den möglichen Wertebereich der Variablen entsprechen und nicht unnötig groß gewählt werden
:<syntaxhighlight lang="C">
Datentyp zur Speicherung der Stundenzeit:
Wertebereich: 0 ... 23 -> unsigned char
Datentyp zur Speicherung einer Jahreszahl:
Wertebereich: 2000 v.C. ... 4000 n.C -> signed short
Datentyp zur Speicherung einer Temperatur:
Wertebreich: -273,0°C ... 2000,0°C -> float
</syntaxhighlight>
=== Implizite Typumwandlung ===
Diese Regeln wurden so aufgestellt, dass dabei stets ein Datentyp in einen anderen Datentyp mit höherem Wertigkeit umgewandelt wird [C11 6.3.1.8] und [Harbison: S 199]. Bei Ganzzahlen gilt ergänzend folgende (Rangordnung [C11 6.3.1.1]: long long, long, int, short,char,_Bool):
{| class="wikitable"
|-
! Regel/<br />Priorität !! If either operand<br />has Type !! And the other operand<br />has Type !! Converts both to
|-
| 1 (hoch) || long double || any real type || long double
|-
| 2 || double || any real type || double
|-
| 3 || float || any real type || float
|-
| 4 || any unsigned type || any unsigned type || the unsigned type<br/>with the greater rank
|-
| 5 || any signed type || any signed type || the signed type<br/>with the greater rank
|-
| 6 || any unsigned type || a signed type with a equal<br/> or less rank || the unsigned type
|-
| 7 || any unsigned type || a signed type that can represent<br/>all of values of the unsigned type || the signed type
|-
| 8 (niedrig) || any other type || any other type || both operands are<br/> converted to the unsigned <br/>integer type corresponding<br/> to the type of the operand<br/> with the signed<br/> integer type
|}
Ergänzend gilt das Regelwerk zu Integer Promotion, welche Datentypen kleiner als <code>signed int</code> zu <code>int</code> und kleiner als <code>unsigned int</code> zu <code>unsigned int</code> konvertiert (Compiler kann hiervon abweichen, wenn sichergestellt ist, dass kein Datenverlust eintritt).
Regel 6 und 7 sind der nicht klar definierten Bitbreite der ganzzahligen Datentypen geschuldet und versuchen, Konvertierungsverluste zu vermeiden. Sie lesen sich zunächst kryptisch, lassen sich aber einfach am folgenden Beispiel erklären:
<syntaxhighlight lang="C">
Operand 1: unsigned int (hier 32-Bit)
Operand 2: long (hier 32-Bit / 64-Bit)
</syntaxhighlight>
* Im Fall, dass der Datentyp <code>long</code> 64-Bit breit ist, kann dieser problemlos die vorzeichenlose 32-Bit Zahl ohne Konvertierungsverluste repräsentieren, so dass der Zieltype <code>signed long</code> ist (Regel 7)
* Im Fall, dass der Datentyp <code>long</code> 32-Bit breit ist, kann dieser mit seinen Wertebereich von -2.147.483.648 bis +2.147.483.647 nicht den vorzeichenlosen Zahlenbereich von 0…4.294.967.295 darstellen. In diesem Fall hat der unsigned Datentyp einen höheren Rang, so dass als Zieltyp <code>unsigend long</code> gewählt wird (Regel 6)
'''Regel 6 bedeutet die Gefahr eines Konvertierungsverlustes, dessen man sich bewusst sein sollte!''' Diese tritt insb. dann in Kraft, wenn ein Operand vom Typ <code>unsigned long long</code> ist (64-Bit).
Beispiele von impliziten Typumwandlungen:
<syntaxhighlight lang="C">
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
vari=5.0*(int)sin(vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ Wikibooks Formatierung schlägt hier fehlt
double sin(double);
int main(int argc,char *argv[]) {
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
printf("vars=%hd\n",vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
printf("vars=%hd\n",vars);
vari=5.0*(int)sin(vars);
printf("vari=%d\n",vari);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
printf("vari=%d\n",vari);
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im CompilerExplorer können sie sich die impliziten Typumwandlungen anzeigen lassen. Dazu gehen sie bitte wie folgt vor:
:* Im Source-Fenster mit '+Add new' ein Compiler Fenster öffnen
:* Im Compiler-Fenster mit '+Add new' ein 'GCC Tree/RTL' Fenster öffnen
:* Im GCC Tree/RTL-Fenster unter 'Select a pass…' 'original tree' auswählen
Um implizite Typumwandlung besser erkennen zu können, wird oftmals bei Variablennamen die ''' 'Ungarische Notation' ''' angewendet (siehe {{w|Ungarische Notation}}). Aufgrund der besonderen Namensgebung kann der Programmierer ohne großen Aufwand frühzeitig mögliche Typkonflikte erkennen. Der Variablenname setzt sich wie folgt zusammen:
<syntaxhighlight lang="C">
{Präfix}{Datentyp}{Bezeichner}
</syntaxhighlight>
:'''Präfix''': p->Pointer h->Handle i->index c->count f->flag rg->Array
:'''Datentyp''': ch->Character st->string w->word b->byte…
:'''Bezeichner''': Zum Binden der Variable an eine konkrete Aufgabe (keine Unterstriche).
:Bezeichner ist optional, wenn aus Präfix und Datentyp die 'Aufgabe' der Variable direkt sichtbar ist
Beispiele:
<syntaxhighlight lang="C">
char rgchtemp[10]; //Array (Range) vom Datentyp character
int ich; //Index zum Adressieren eines Arrays vom Datentyp
//character
</syntaxhighlight>
=== Explizite Typumwandlung ===
Programmierer erzwingt durch explizite Typumwandlung (auch CASTen genannt) eine Umwandlung eines Datentyps in einen anderen. Dazu wird der Zieldatentyp in runden Klammern vor Quelldatentype geschrieben:
<syntaxhighlight lang="C">
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
In der Rangfolge der Operatoren steht der Cast-Operator unterhalb von bspw. Funktionsaufrufen, Arrayzugriffen aber auch der Dereferenzierung:
{| class="wikitable"
|-
! Priorität !! Symbol !! Assoziativität !! Bedeutung
|-
| 15 || ... || ... || ...
|-
| 14
||
++/-- (Präfix)<br />
+/- (Vorzeichen) <br />
<nowiki>!</nowiki>/~ <br />
&<br />
<nowiki>*</nowiki><br />
(TYP)<br />
...
|| R-L
||
Präfix-Inkrement/Dekrement<br />
Vorzeichen<br />
Logisches/Bitweises Nicht<br />
Adresse<br />
Zeigerdereferenzierung<br />
'''Typumwandlung (Explizites Cast)'''<br />
...
|-
| 13
||
* / %
|| L-R
|| Multiplikation/Division/Modulo
|-
| 12 || ... || ... || ...
|}
Im Zweifel gilt auch hier, den zu wandelnden Typ ergänzend zu klammern.
Hinweis:
* Bedenke, dass die explizite Typumwandlung so aufgestellt sein sollte, dass der Zieldatentyp dem notwendigen Datentyp entspricht. Andernfalls wendet der Compiler ergänzend eine implizierte Typumwandlung an:
:<syntaxhighlight lang="C">
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Mittels expliziter Typumwandlung können Ganzzahl nach Gleitkommazahlen (und andersherum) und Zeiger in einen anderen Zeiger und auf andere Datentypen gewandelt werden. Eine Konvertierung von Arrays, Strukturen, Unions zu anderen Datentypen als sich selbst ist weiterhin nicht möglich:
<syntaxhighlight lang="C">
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei den möglichen Konvertierungen sollte Folgendes berücksichtigt werden:
* '''Vorzeichenlose Ganzzahl''' → '''Vorzeichenlose Ganzzahl''': Wenn der Zieldatentyp größer ist, wird die Zahl durch führende '0' erweitert. Wenn der Zieldatentyp kleiner ist, werde die zu vielen Bitstellen abgeschnitten/verworfen (ggf. Datenverlust)
* '''Vorzeichenbehaftete Ganzzahl''' → '''Vorzeichenbehaftete Ganzzahl''': Wenn der Zieldatentyp größer ist, wird vorzeichenrichtig erweitertet (d.h. das Auffüllen erfolgt auf Basis des Vorzeichens). Wenn der Zieldatentyp kleiner ist, werden auch hier die zu vielen Bits abgeschnitten/verworfen (Vorsicht: Negative Zahlen können dabei in positive Zahlen gewandelt werden)
* '''Gleitkommazahl''' → '''Gleitkommazahl''': Hier wird vereinfacht ausgedrückt sowohl die Mantisse als auch der Exponent einzeln kopiert. Wenn die Zielmantisse kleiner ist, gehen 'Nachkommastellen' verloren. Wenn der Quellexponent einen größeren Wert beinhaltet, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf Unendlich gesetzt. Umgedreht, wenn der Quellexponent kleiner ist, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf 0 gesetzt
* '''Ganzzahl''' → '''Gleitkommazahl''': Hier wird, vereinfacht ausgedrückt, die Ganzzahl in die Mantisse kopiert. Um Datenverluste zu vermeiden, sollte die Bitbreite der Zielmantisse größer gleich der Bitbreite der Ganzzahl sein
* '''Gleitkommazahl''' → '''Ganzzahl''': Im Wesentlichen wird hier die Mantisse übernommen, so dass hier die Bitbreite des Zieldatentyps mindestens der Bitbreite der Mantisse sein sollte
* '''Zeiger''' ↔ '''Ganzzahl''': Die Konvertierung ist möglich. Da bei 64-Bit Systemen der Zeiger 64-Bit und Integer 32-Bit breit ist, meckert ggf. der Compiler. Für solche Fälle existieren die Datentypen 'intptr_t' und 'uintptr_t', über welche sichergestellt ist, dass ein Zeiger in einen Ganzzahldatentyp gespeichert werden kann!
* '''Zeiger''' ↔ '''Gleitkommazahl''': Diese Konvertierung ist nicht möglich!
* '''Struktur/Union''' ↔ '''Ganzzahl/Gleitkommazahl''': Diese Konvertierung ist nicht möglich. Es können nur einzelnen Strukturelemente konvertiert werden, sofern diese vom Typ Ganzzahl/Gleitkommazahl sind
* '''Array''' ↔ '''Ganzzahl/Gleitkommazahl''': Der Arrayname entspricht einen Zeiger, so dass hier ein Zeiger in eine Ganzzahl oder umgedreht konvertiert wird (siehe Zeiger ↔ Ganzzahl)
In C++ gibt es weitere CAST-Operatoren, auf welche hier derzeit noch nicht weiter eingegangen wird!
* Static_cast (Entspricht dem Expliziten Cast)
* Const_cast
* Dynamic_cast
* Reinterpret_cast
== Verbundtyp Struktur/Klasse (nur C++) ==
Nach dem Wikipedia Artikel {{w|Verbund (Datentyp)}} ist ''ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten können wiederum Verbünde enthalten, wodurch auch komplexe Datenstrukturen definiert werden können.<br />
Für jedes Strukturelement wird Speicher reserviert. Alle Strukturelemente liegen hintereinander im Speicher.''
<code>Syntax: struct Strukturname<sub>Opt</sub> {Datentype Strukturelementname; … }<sub>OPT</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Verbund entspricht einer Java Klasse mit dem Unterschied zu C (nicht C++) , dass ein Verbund keine Methoden beinhaltet und keine Zugriffsbeschränkung für die Attribute gesetzt werden können.
Der Syntax erlaubt es, gleichermaßen einen Datentyp (über Strukturname) zu definieren und Variablen von diesem Datentyp (über Variablenliste) anzulegen. Da beide Elemente optional sind, ergeben sich diverse Kombinationsmöglichkeiten:
* Nur Strukturname → Definition eines neuen Datentyps
:<syntaxhighlight lang="C">
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
var1.y=2;
var1.z=1;
printf("var1.x=%d var1.y=%d var1.z=%d\n",var1.x,var1.y,var1.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C: Der Strukturname ist nur mit dem vorangestellten <code>struct</code> gültig. Der Strukturname stellt somit einen eigenen Namensraum, getrennt von dem Namensraum der Variablen/Funktionen, dar. Daher kann ein Strukturname identisch zu einem Variablennamen sein:
:<syntaxhighlight lang="C">
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
xyz2.x=xyz2.y=xyz2.z=1;
printf("xyz2.x=%d xyz2.y=%d xyz2.z=%d\n",xyz2.x,xyz2.y,xyz2.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C++: Der Strukturname ist sowohl mit als auch ohne dem vorangestellten <code>struct</code> gültig. Auch hier stellt der Strukturname einen eigenen Namensraum dar, der jedoch eine niedrigere Priorität als der der Variablen hat:
:<syntaxhighlight lang="C++">
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz beschreibt hier die Variable
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz3 beschreibt hier die Variable
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
* Nur Variablenliste → Definition einer/mehrerer Variablen von einem 'unnamed' Datentyp
:<syntaxhighlight lang="C">
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Angewendet wird die Schreibweise gerne, wenn eine Struktur innerhalb einer Struktur definiert wird und die innere Struktur zur besseren Strukturierung dient:
:<syntaxhighlight lang="C">
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Strukturname und Variablenliste → Definition eines Datentyps und Definition von Variablen. D.h. es können im Nachhinein weitere Variablen von diesem Datentyp angelegt und die hier angelegten Variablen genutzt werden.
:<syntaxhighlight lang="C">
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y; //Nutzung der Variablen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y=1; //Nutzung der Variablen
(void)var1;
(void)ptr1;
(void)ptr2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Kein Strukturname und keine Variablenliste → "Anonymous Struct", d.h. Definition eines 'unnamed' Datentyps, von der ergänzend keine Variable angelegt wird. Anonymus Structs sind nur innerhalb von Strukturen erlaubt/einsetzbar. Hier dienen sie der besseren Strukturierung und ersparen dem Programmierer die Benennung des normalerweise notwendigen Strukturelementes:
:<syntaxhighlight lang="C">
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
(void)var;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Eine Struktur (und auch eine C++ Klasse) wird mit einem Semikolon abgeschlossen
* Eine alternative Beschreibung zu Strukturen finden sie in [https://abstractexpr.com/2023/06/29/structures-in-c-from-basics-to-memory-alignment/ Structures in C: From Basics to Memory Alignment]
=== Strukturelement ===
Innerhalb der Struktur können beliebige Strukturelemente von beliebigen Datentypen angelegt werden. Einzige Voraussetzung, der Datentyp des anzulegenden Strukturelementes muss zuvor definiert worden sein. Ergänzend kann der neue Datentyp auch in der Struktur selbst definiert werden, sofern mit der Definition des Datentyps auch eine Variable angelegt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zugriff auf Strukturelemente ===
Die Programmiersprachen C/C++ unterscheiden zwei 'Zugriffsarten' auf die Strukturelemente, abhängig vom zugrundeliegenden Datentyp des linken Operanden::
* Handelt es sich beim linken Operanden um eine (struct)Variablen, so erfolgt der Zugriff über den Punkt-Operator <code>.</code>:
:<syntaxhighlight lang="C">
struct {
int a,b,c;
} abc;
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct {
int a,b,c;
} abc;
int main(int argc,char *argv[]) {
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c=12;
printf("abc.a=%d abc.b=%d abc.c=%d\n",abc.a,abc.b,abc.c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Handelt es sich beim linken Operanden um einen Zeiger auf eine (struct)Variable, so erfolgt der Zugriff über den Zeiger-Operator <code>-></code>:
:<syntaxhighlight lang="C">
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
int main(int argc,char *argv[]) {
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Werden innerhalb von Strukturen weitere Strukturen und Zeiger auf Strukturen angelegt, so müssen diese Regeln auf jedes innere Strukturelement einzeln angewendet werden:
<syntaxhighlight lang="C">
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
int main(int argc,char *argv[]) {
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Strukturen ===
Mit dem Anlegen einer Strukturvariablen kann diese auch initialisiert werden. Eine 'Vorbelegung' der Strukturelemente bei der Definition der Struktur ist in C nicht möglich.<br />
Die Initialisierung erfolgt über eine Initialisierungsliste (siehe Kap [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]). Innerhalb der Initialisierungsliste stehen die Initialisierungswerte entweder in der Reihenfolge der Datentypdefinition oder werden explizit mit dem ‘.‘ Operator angesprochen (designated initializers). Werden einzelne Strukturelemente ausgelassen, so werden diese mit 0 initialisiert:
<syntaxhighlight lang="C">
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
int main(int argc,char *argv[]) {
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
printf("v1.a=%d v1.b=%d v1.str[0]=%d\n",v1.a,v1.b,v1.str[0]);
printf("v2.a=%d v2.b=%d v2.str[0]=%d\n",v2.a,v2.b,v2.str[0]);
printf("v3.a=%d v3.b=%d v3.str[0]=%d\n",v3.a,v3.b,v3.str[0]);
printf("v4.a=%d v4.b=%d v4.str[0]=%d\n",v4.a,v4.b,v4.str[0]);
printf("v5.a=%d v5.b=%d v5.str[0]=%d\n",v5.a,v5.b,v5.str[0]);
printf("v6.a=%d v6.b=%d v6.str[0]=%d\n",v6.a,v6.b,v6.str[0]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Initialisierung einer Struktur über nachfolgende Art bewirkt etwas anderes, als erwartet:
<syntaxhighlight lang="C">
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
printf("var.a=%d var.b=%d var.c=%d\n",var.a,var.b,var.c);
//Gerne mal den Compiler Wechseln
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der Initialisierungsliste wird über 'var.b=12' und 'var.c=3' die zu diesem Zeitpunkt noch nicht initialisierte Variable var die Elemente b und c initialisiert. Mit dem Werten der Initialisierungsliste (hier {12,3}) wird nachfolgend die Variable erneut initialisiert und 12 dem Strukturelement a und 3 dem Strukturelement b zugewiesen. Abhängig vom Compiler ist das Strukturelement c entweder 3 oder 0.
Bei verschachtelten Strukturen muss entsprechend obiger Aussage für jede innere Struktur eine eigene Initialisierungsliste erstellt werden. Die inneren Initialisierungslisten können entfallen, was jedoch nicht empfohlen wird und ergänzend vom Compiler bei '-Wall' als Warning angemerkt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8}}
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={{.x=5,.y=6},{7,8}},
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8} }
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={ {.x=5,.y=6},{7,8} },
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
int main(int argc,char *argv[]) {
printf("v1.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v1.a, v1.b, v1.xy.x, v1.xy.y, v1.arr[0].x, v1.arr[0].y, v1.arr[1].x, v1.arr[1].y );
printf("v2.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v2.a, v2.b, v2.xy.x, v2.xy.y, v2.arr[0].x, v2.arr[0].y, v2.arr[1].x, v2.arr[1].y );
printf("v3.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v3.a, v3.b, v3.xy.x, v3.xy.y, v3.arr[0].x, v3.arr[0].y, v3.arr[1].x, v3.arr[1].y );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zuweisen/Kopieren von Strukturen ===
Strukturen werden über den Namen als 'ganzes' angesprochen, so dass eine Zuweisung als 'ganzes' möglich ist. Bei bspw. einer 12-Byte großen Struktur werden bei Nutzung der Variable die gesamten 12-Byte gelesen/geändert!
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1,var2;
var1=var2; //12-Bytes kopiert
//--> entspricht memcpy(&var1,&var2,sizeof(xyz));
</syntaxhighlight>
Die Zuweisung als 'ganzes' gilt auch bei der Parameterübergabe und -rückgabe von Funktionen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;};
//Funktionsdefinition
struct xyz function(struct xyz par) {
return (struct xyz){par.z,par.y,par.x};
}
//Funktionsaufruf
struct xyz var=function((struct xyz){1,2,3});
//Mit dem Aufruf der Funktion werden 12-Bytes in die Variable par kopiert
//Mit dem Ende der Funktion werden 12-Bytes in die Variable var kopiert
</syntaxhighlight>
Bedenke, dass bei großen Strukturen das Kopieren Rechenzeit benötigt und folglich vermieden werden sollte! Alternativ sollten Zeiger auf Strukturen über- und zurückgeben werden.
Über Compound Literal (siehe Kap. [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]) kann einer Strukturvariablen als 'ganzes' einen neuen Wert zugewiesen werden:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
var1={.a=7}; //KO, Initialisierungsliste kann hier nicht
//angewendet werden
var1=(struct abc){.a=7}; //Wertezuweisung über Compound Literal möglich
</syntaxhighlight>
Formel gesehen entspricht das Compound Literal einer 'unnamed Variable', die als erstes angelegt und initialisiert wird. Der Inhalt dieser Variablen wird im Anschluss der eigentlichen Variable zugewiesen!
=== Prototyp / Deklaration einer Struktur ===
Soll der Datentyp einer Struktur genutzt werden, der erst an weiter hinten liegenden Stellen im Programm definiert wird, so ist wie bei Variablen/Funktionen ein Prototyp/Deklaration notwendig:
<syntaxhighlight lang="C">
struct abc; //Prototyp der Struktur abc
...
struct abc { int a,b,c;}; //Definition der Struktur abc
</syntaxhighlight>
Die Deklaration sagt einzig aus, dass die Struktur später definiert wird, beinhaltet aber nicht die Strukturelemente. Folglich kann auf Basis dieses Prototyps keine Variable definiert werden, sondern einzig ein Zeiger auf solche eine Struktur:
<syntaxhighlight lang="C">
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Anwendung:
* Struktur, welche auf sich selbst verweist (Verkettete Liste)
:<syntaxhighlight lang="C">
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
int main(int argc,char *argv[]) {
struct vl *head=NULL;
struct vl a={.daten="Ele a"};
struct vl b={.daten="Element b"};
struct vl c={.daten="c-Eleent"};
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL; //Zur Kennzeichnung des letzten Elementes
for(struct vl*ptr=head;ptr;ptr=ptr->next)
printf("'%s'\n",ptr->daten);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Entsprechend der objektorientierten Programmierung, wenn alle Attribute der Klasse private sind:
:{| class="wikitable"
|-
! !! class.h
|-
|
||<syntaxhighlight lang="C">
struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
</syntaxhighlight>
|-
! main.c !! class.c
|-
|<syntaxhighlight lang="C">
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
..
//Kein Zugriff auf
//Strukturelemente möglich
return 0;
}
</syntaxhighlight>
||<syntaxhighlight lang="C">
#include "class.h"
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *)
malloc(sizeof(struct class));
this->attr1=10;
*me=this;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
//..
//Kein Zugriff auf Strukturelemente möglich
return 0;
}
|class_h=struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
|class_c=#include "class.h"
#include <stdlib.h> //fuer malloc()
#include <stdio.h> //fuer printf()
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *) malloc(sizeof(struct class));
printf("konstructor called\n");
this->attr1=10;
*me=this;
}
| execCompilerOptions=-Wall class.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Vergleichen von Strukturen ===
Ein Vergleich von Strukturen über den direkten Weg ist nicht möglich. Vielmehr müssen die Strukturelemente händisch verglichen werden:
<syntaxhighlight lang="C">
struct xyz {int inx,y,z;} var1,var2;
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} var1={1,2,3},var2={1,2,3};
int main(int argc,char *argv[]) {
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
printf("Strukturelemente von var1 und var2 identisch\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis
* Bei Rechnerarchitekturen mit nicht ausgerichteter Speicherausrichtung (Alignment) kann ergänzend ein Vergleich über memcmp() erfolgen
=== Speicherplatzbedarf einer Struktur ===
Für jedes Strukturelement wird Speicher entsprechend der Größe des Datentyps reserviert. Der Speicherplatzbedarf der Gesamtstruktur ergibt sich aus der Summe der Strukturelemente:
<syntaxhighlight lang="C">
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
sizeof(var1) //ergibt 12
sizeof(struct xyz) //ergibt 12
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
int main(int argc,char *argv[]) {
printf("sizeof(var1)=%zu Bytes\n",sizeof(var1));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Ermittlung der tatsächlichen Speichergröße einer Struktur erfolgt über den sizeof-Operator:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;} a;
sizeof(a); //=12 OK
sizeof(a.x); //=4 OK
sizeof(struct xyz); //=12 OK
sizeof(struct xyz.x); // KO
//Ist dies dennoch notwendig, so kann dies über den Umweg eines Zeigers
//erfolgen:
sizeof(((struct xyz *)0)->x); //=4 OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x,y,z;
} a;
int main(int argc,char *argv[]) {
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
printf("sizeof(a.x)=%zu Bytes\n",sizeof(a.x));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
printf("sizeof(struct xyz.x)=%zu Bytes\n",sizeof(struct xyz.x));
printf("sizeof(((struct xyz *)0)->x)=%zu Bytes\n",sizeof(((struct xyz *)0)->x));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei Rechnerarchitekturen mit ausgerichteter Speicherausrichtung (Alignment) (siehe {{w|Speicherausrichtung}}) kann der tatsächliche Speicherbedarf größer sein! Hier fügt der Compiler ggf. zwischen den Strukturelemente Füllbytes (Padding Bytes) ein
* Die Reihenfolge der Strukturelemente wird vom Compiler nicht geändert. D.h. die Zuordnung der Speicherstellen zu den Strukturelementen erfolgt in der Definitionsreihenfolge
=== Interne Organisation ===
Compilerintern werden die Strukturelemente über einen Offset dargestellt. Das erste Strukturelement bekommt dabei immer den Offset 0 zugewiesen. Das nachfolgende Element bekommt als Offset die Größe des Datentyps des vorherigen Elementes zugewiesen. Usw.. <br />
Der Compiler setzt den Zugriff auf ein Strukturelement einer (Struktur)Variablen so um, dass er zunächst die Startadresse der Variablen holt und zu dieser den Offset des Strukturelementes addiert. Die Anzahl der zu lesenden/schreiben Bytes ergibt sich aus dem Datentyp des Strukturelementes:
<syntaxhighlight lang="C">
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1; //(Beispielhaft soll var1 die Speicheradressen
//0x100..0x10B belegen). Der Zugriff auf
//die Variable erfolgt immer über die Startadresse
var1.x=7; //Zugriff auf Speicheradresse 0x100+0 (Offset)
var1.y=8; //Zugriff auf Speicheradresse 0x100+4 (Offset)
var1.z=9; //Zugriff auf Speicheradresse 0x100+8 (Offset)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1;
int main(int argc,char *argv[]) {
//Zugriff siehe Compiler
var1.x=7; //mov DWORD PTR var[rip+0],7
var1.y=8; //mov DWORD PTR var[rip+4],7
var1.z=9; //mov DWORD PTR var[rip+8],7
return 0;
} | execCompilerOptions=-Wall|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Offset eines Strukturelementes kann mit dem offsetof-Operator ermittelt werden:
<code>Syntax: offsetof(type,Strukturelement)</code>
Wie beim sizeof-Operator gilt der offsetof-Operator als Konstantenausdruck und der Rückgabedatentyp ist <code>size_t</code>. Zur Nutzung des Operators muss die Header-Datei 'stddef.h' inkludiert werden:
<syntaxhighlight lang="C">
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var1;
offsetof(struct xyz,z) --> 8
offsetof(var1,z) --> KO: Es wird ein Datentyp und
keine Variable erwartet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz{
int x,y,z;
} var1;
int main(int argc,char *argv[]) {
printf("offsetof(struct xyz,x)=%zu Bytes\n",offsetof(struct xyz,x));
printf("offsetof(struct xyz,y)=%zu Bytes\n",offsetof(struct xyz,y));
printf("offsetof(struct xyz,z)=%zu Bytes\n",offsetof(struct xyz,z));
printf("offsetof(var1,z)=%zu Bytes\n",offsetof(var1,z));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Unter Nutzung des offsetof-Operators kann man bei gegebener Adresse eines Strukturelementes auf die Startadresse der zugrundeliegenden Struktur zurückrechnen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1;
int *ptri=&var1.y;
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var={1,2,3};
int *ptri=&var.y;
int main(int argc,char *argv[]) {
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
printf("ptrxyz->x=%d ptrxyz->y=%d ptrxyz->z=%d",ptrxyz->x,ptrxyz->y,ptrxyz->z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dazu wird von der Startadresse des Strukturelementes der Offset abgezogen. Da der offsetof-Operator den Abstand in Bytes zurückgibt, muss der Pointer auf das Strukturelement zuvor ebenfalls in ein 'Byte'-Zeiger gewandelt werden.
Im Linux kernel wird diese Subtraktion über das container_of Makro realisiert:
<syntaxhighlight lang="C">
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
</syntaxhighlight>
Dieses Makro ermöglicht es, bei gegeben Startadresse eines Strukturelementes die Startadresse der zugrundeliegenden Struktur zu berechnen. Anwendung findet dieses Makro bspw. in:
* der objektorientierten Programmierung, um ausgehend vom gegebenen Parent-Element die Startadresse des Child-Elementes zu berechnen:
:<syntaxhighlight lang="C">
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
..
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
printf("parent.attr1=%d parent.att2=%d\n",me->attr1,me->attr2);
printf("child.attr1=%d\n",child->attr1);
}
int main(int argc,char *argv[]) {
struct child obj1;
obj1.attr1=1;
obj1.parent.attr1=2;
obj1.parent.attr2=3;
parent_methode(&obj1.parent);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei verketteten Listen, wenn das Next-Element im Datensatz selbst eingearbeitet ist:
:<syntaxhighlight lang="C">
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(PTR, TYPE, MEMBER) \
((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
vl_t head={NULL};
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
int main(int argc,char *argv[]) {
daten_t obj1={.daten1=1,.daten2=2};
daten_t obj2={.daten1=3,.daten2=4};
vl_addfront(&obj1);
vl_addfront(&obj2);
daten_t *ret=vl_getfront();
printf("%d %d\n",ret->daten1,ret->daten2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Explizites Cast ===
Eine Struktur kann nicht in einen anderen Datentyp und damit auch nicht in einen anderen Strukturdatentyp mit identischen Strukturelementen konvertiert werden:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} xyz;
struct abc {int a,b,c;} abc;
int var;
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} xyz;
struct abc {
int a,b,c;
} abc;
int var;
int main(int argc,char *argv[]) {
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Incomplete Array ===
Das letzte Element einer Struktur kann ein Array ohne Angabe einer Dimensionsgröße sein (Incomplete Array/Flexible Array Member). Bei der Definition einer Variablen von solch einem Datentyp wird in der Tat kein Speicher für das letzte Element reserviert, so dass dies 'händisch' erfolgen muss. Auf das Array kann ungeachtet dessen unproblematisch zugegriffen werden:
<syntaxhighlight lang="C">
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert
//wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert wurde
//Zur Darstellung dieses Sachverhaltes wurde der Sanitizer
//über den Compilerschalter -fsanitize=address aktiviert
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Speicherplatzreservierung für das incomplete Array kann auf zwei verschiedene Arten erfolgen:
* Speicherplatzreservierung für das Incomplete Array über Variableninitialisierung (nur GCC-C und nur im Falle einer globalen Variablen)
:<syntaxhighlight lang="C">
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
int main(int argc,char *argv[]) {
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(ele1)=%zu Bytes\n",sizeof(ele1));
printf("sizeof(ele2)=%zu Bytes\n",sizeof(ele2));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Speicherplatzreservierung für das Incomplete Array über malloc
:<syntaxhighlight lang="C">
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
if(b==NULL)
return printf("malloc failed\n"),1;
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
//zum Beweis Sanitizer über -fsanitize=address eingebunden
free(b);
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Das Incomplete Array bietet sich überall dort an, wo Daten gespeichert werden sollen, deren Größe sich erst zur Laufzeit ergibt.
=== Anwendung ===
Die Nutzung des Datentyps struct empfiehlt sich an vielen Stellen:
* Zusammengehörende Daten zu Kapseln (entsprechend der objektorientierten Programmierung
* Verkette Listen
* Aufgrund der Typsicherheit zur Darstellung von sicherheitskritischen Aufgaben
Siehe Übungsbereich!
=== C++ ===
Der wesentliche Syntax von Strukturen wurde in C++ übernommen. D.h.:
* das abschließende Semikolon
* der Zugriff auf die Strukturelemente
* Speicherplatzreservierung
* die Definition von Variablen mit der Definition des Datentyps
* ...
Ergänzend wurde in C++ der Datentyp class eingeführt, der weitestgehend identisch zu struct ist. Geändert/Hinzugefügt wurden folgende Sachverhalte:
* Classen/Strukturen können Methoden haben
* Operatoren (Zuweisungsoperator, Addition, ...) können überladen werden
* Alle Strukturelemente (und Methoden) einer struct sind per default public
* Alle Attribute (und Methoden) einer Class sind per default private
* Zur Nutzung des Datentyps ist das führende struct nicht notwendig (dies bedingt dann auch, dass der Strukturdatentyp kein separater Namensraum ist)
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var_xyz;
</syntaxhighlight>
* Initialisierungswerte für Strukturelemente und Klassenattribute bei der Datentypbeschreibung angegeben werden können:
:<syntaxhighlight lang="C++">
struct xyz {
int x=3;
int y=1;
int z;
};
xyz var={7}; //var.x=7 var.y=1 var.z=0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x=3;
int y=1;
int z;
};
int main(int argc,char *argv[]) {
xyz var={7}; //var.x=7 var.y=1 var.z=0
printf("var.x=%d var.y=%d var.z=%d\n",var.x,var.y,var.z);
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In C++ kann eine Struktur ebenfalls über 'designated initializers' initialisiert werden. Jedoch muss die Reihenfolge der Initialisierungselement identisch zur Datentypdefinition sein. Auch ist keine Doppeltbenennung erlaubt:
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x,y,z;
};
int main(int argc,char *argv[]) {
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
(void)var1;
(void)var2;
(void)var3;
(void)var4;
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Union ==
Ähnlich wie eine Struktur ist ein Union ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wird. Bei sog. Union beginnen jedoch alle Komponenten nicht wie bei Strukturen an nacheinander folgenden Speicheradressen, sondern an der identischen Speicheradresse, d.h. ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union kann folglich zu einem Zeitpunkt nur ein Element enthalten. Der benötigte Speicherplatz ergibt sich aus der größten Komponente.
<code>Syntax: union Unionname<sub>Opt</sub> {Datentyp Variablenname; …}<sub>Opt</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Schutz/Zugriffssteuerung der Unionelemente ist nicht vorhanden. Es kann in beliebiger Reihenfolge auf die einzelnen Elemente zugegriffen werden.
Die Anwendung ist identisch wie bei Strukturen, so dass im Folgenden nur die Abweichungen zu den Strukturen beschrieben werden.
=== Speicherplatzbedarf und interne Struktur einer Union ===
Die Größe der Union ergibt sich aus dem größtem Unionelement. Alle Unionelemente überlappen sich, so dass der Offset zum Basiselement 0 ist:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird ein kleineres Unionelement belegt und im Anschluss ein größeres Unionelement gelesen, so ist der Inhalt der durch das kleinere Element nicht beschriebenen Speicherstellen undefiniert:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc.a=0x11;
printf("%08x",abc.c);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
};
void foo(int var) {
int lok=var;
printf("Foo(%#08x) called\n",lok);
}
void bar(void) {
union abc abc;
abc.a=0x11;
printf("abc.a=%#02x\n",abc.a);
printf("abc.c=%#08x\n",abc.c);
}
int main(int argc,char *argv[]) {
//Zur Darstellung des Phänomens muss
//erstmal der Stack mit Daten belegt werden!
foo(0x12345678);
bar();
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Union ===
Bei einer Union kann nur ein Element initialisiert werden, d.h. die Initialisierungsliste kann nur einen Wert beinhalten. Ohne explizite Benennung des Unionelementes in der Initialisierungsliste wird das erste Element aus der Datentypbeschreibung initialisiert. Mit expliziter Benennung mittels 'designated initializers' können auch andere Elemente initialisiert werden:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Anwendung ===
Mittels des Datentyps union können diverse Anwendungsfälle abgedeckt werden:
* Über Union lassen sich größere Datentypen in kleinere Datentypen unterteilen, um z.B. einzelne Bytes zu extrahieren:
<syntaxhighlight lang="C">
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union floatu var={1.234};
printf("%f\n",var.var); //Darstellung des Float-Wertes
printf("%x\n",var.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var.byte[0],var.byte[1],var.byte[2],var.byte[3]);
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
union longlong var2={0x123456789ABCDEFULL};
printf("%llx\n",var2.ll);
printf("%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
int main(int argc,char *argv[]) {
union floatu var1={1.234};
printf("var1.var=%f\n",var1.var); //Darstellung des Float-Wertes
printf("var1.hex=%x\n",var1.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("var1.byte[0..3]=%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var1.byte[0],var1.byte[1],var1.byte[2],var1.byte[3]);
union longlong var2={0x123456789ABCDEFULL};
printf("var2.ll=%llx\n",var2.ll);
printf("var2.i[0..1]=%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Ein weiterer Anwendungsfall ergibt sich, wenn in einer Struktur unterschiedliche Datensätze gespeichert werden sollen (siehe {{w|Tagged Union}}):
:<syntaxhighlight lang="C">
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
int main(int argc,char *argv[]) {
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mittels eines Tagged Union kann komfortabel ein Binärbaum realisiert werden:
:<syntaxhighlight lang="C">
//Quelle: https://github.com/Hirrolot/datatype99
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h> //fuer printf()
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Die Eigenschaften des Datentyps union entsprechen den Eigenschaften des Datentyps struct in C++.
== Enum/Aufzählungstyp ==
Nach dem Wikipedia Artikel {{w|Aufzählungstyp}} ist ''ein Aufzählungstyp (englisch enumerated type) ein Datentyp für Variablen mit einer endlichen Wertemenge. Alle zulässigen Werte des Aufzählungstyps werden bei der Deklaration des Datentyps mit einem eindeutigen Namen (Identifikator) definiert, sie sind Symbole.''
<code>Syntax: enum enumname<sub>Opt</sub> {definition-list[=expression]}<sub>Opt</sub> Variablenliste<sub>Opt</sub></code>
Die Anwendung ist identisch wie bei Strukturen, so dass nachfolgend nur die Abweichungen zu den Strukturen beschrieben werden.
=== Datentyp von enum ===
In C entspricht der Datentyp Enum dem Datentyp <code>int</code> so dass Zuweisungen/Vergleiche mit Ganzzahlen möglich sind. Ganzzahloperationen funktionieren ebenso:
<syntaxhighlight lang="C">
enum STATUS {OK,KO=5}; //Definition des Datentyps
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
status++;
status=5.7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum STATUS {OK,KO=5}; //Definition des Datentyps
int main(int argc,char *argv[]) {
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
printf("status == 5\n");
status++;
status=5.7;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Enumelemente ===
Die Elemente der Definitionsliste sind Integerkonstanten. Diese können auch in Kombination mit anderen Datentypen genutzt werden. Auch gibt es keinen gesonderten Namensraum für Elemente der Definitionsliste. Sie 'konkurrieren' folglich mit allen Variablen- und Funktionsnamen:
<syntaxhighlight lang="C">
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
int main(int argc,char *argv[]) {
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der erste Enumelement der Definitionsliste bekommt den Wert 0 zugewiesen. Folgeelemente bekommen den Wert des Vorgängerelementes +1 zugewiesen.
Enumelemente können mit einer Konstanten (und Konstantenausdruck) initialisiert werden:
<syntaxhighlight lang="C">
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
int main(int argc,char *argv[]) {
printf("bill=%d john=%d, fred=%d\n",bill,john,fred);
printf("error=%d warning=%d info=%d ok=%d\n",error,warning,info,ok);
printf("Ostfalia=%d Wolfenbuettel=%d\n",Ostfalia,Wolfenbuettel);
printf("test=%d\n",test);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Es empfiehlt sich, die Enumelemente in GROSSBUCHSTABEN zu schreiben. Hiermit wird gekennzeichnet, dass es sich um Konstanten und nicht um Variablen/Funktionen handelt
=== Anwendung ===
Die Nutzung des Datentyps enum empfiehlt sich überall dort, wo eine Fallunterscheidung notwendig ist:
* Statusrückgabe von Funktionen:
:<syntaxhighlight lang="C">
enum STATUS {OK,MEMORY_OVERFLOW, DIVISION_BY_ZERO};
enum STATUS funct(…) {
return MEMORY_OVERFLOW;
}
</syntaxhighlight>
* Beschreibung der Zustände und der Ereignisse eines Zustandsautomates:
:<syntaxhighlight lang="C">
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Ergänzend zu den Abweichungen bei Structs sind hier weitere Unterscheidungsmerkmale vorhanden:
* Enums stellen einen eigenen Datentyp dar, der nicht mit int kompatible ist. Das bedingt unter anderem, dass einige Operatoren wie z.B. ++ nicht mehr auf Variablen des Datentyps enum angewendet werden. Die Enumelemente als solches sind jedoch kompatibel zum Ganzzahldatentyp:
:<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
int main(int argc,char *argv[]) {
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
printf("RED==2\n");
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
* Auch enums können Methoden besitzen.
* Über Operatorüberladung können z.B. nicht vorhandene Operatoren wie ++/-- ergänzt werden
* Über unscoped/scoped Enumerations wird der 'Namensraum' gesteuert:
:* Unscoped Enumeration (Elemente der Definitionsliste stehen wie bei C im Zugriff)
::<code>Syntax: enum name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE };
Color r = RED;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE };
Color r = RED;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
:* Scoped enumeration (Elemente der Definitionsliste haben einen eigenen 'Namensraum')
::<code>Syntax: enum '''class|struct''' name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
== Bitfelder ==
Nach dem Wikipediaartikel {{w|Bitfeld}} ''bezeichnet in der Informationstechnik und Programmierung ein Bitfeld ein vorzeichenloses Ganzzahldatentyp, in dem einzelne Bits oder Gruppen von Bits aneinandergereiht werden. Es stellt eine Art Verbunddatentyp auf Bit-Ebene dar. Im Gegensatz dazu steht der primitive Datentyp, bei dem der Wert aus allen Stellen gemeinsam gebildet wird.''
Der Syntax entspricht dem struct-Syntax, mit der Ergänzung, dass hinter den Strukturelementen noch die Bitbreite getrennt durch ein Doppelpunkt angegeben wird:
<syntaxhighlight lang="C">
struct time {
unsigned int hour: 5; //0..23 Bits 0..4
unsigned int minute: 6; //0..59 Bits 5..10
Unsigend int second: 6; //0..59 Bits 11..16
} myTime;
</syntaxhighlight>
Als mögliche Datentypen für die Strukturelemente stehen nur die Ganzzahldatentypen <code>int</code>, <code>short</code>, <code>long</code> , <code>long long</code> und <code>char</code> zur Verfügung. Der Datentyp eines Strukturelementes muss mindestens die Anzahl der Bits enthalten, wie diese über die Bitbreite gefordert wird.
Von den Strukturelementen kann keine Adresse bestimmt werden! Auch der <code>offsetf</code> - Operator schlägt fehl.
Der Datentyp entspricht im Wesentlichen einem Ganzzahlzahldatentyp, so dass bei Zugriff auf eine Variable dieses Datentyps eine Ganzzahl gelesen/geschrieben wird. Bei Zugriff auf die einzelnen Strukturelemente werden die entsprechenden Bits dieser Ganzzahlvariablen maskiert, so dass nur die betroffenen Bits geändert werden:
<syntaxhighlight lang="C">
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) | (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) | ((second&0b00001111)<<2);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
//Nachweis am besen über den Maschinensprachevergleich!
int main(int argc,char *argv[]) {
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) {{!}} (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) {{!}} ((second&0b00001111)<<2);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
h=c
}} Öffnen im Compiler Explorer] }}
=== Anwendung===
* Komprimierte Speicherung der Uhrzeit (wie dies z.B. in Realtimeclocks erfolgt)
:<syntaxhighlight lang="C">
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
int main(int argc,char *argv[]) {
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Aufteilung von FloatingPoint Zahlen in seine Komponenten
:<syntaxhighlight lang="C">
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
int main(int argc,char *argv[]) {
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",
(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Bitfelder existieren mit den bekannten Ergänzungen auch in C++.
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
exntjttgwv6f95gk4x8g1fvld6scdp5
1090849
1090844
2026-09-15T10:24:02Z
D. Justen
102048
Rechtschreibung
1090849
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C kennt nachfolgende grundlegende Datentypen und Zeiger auf diese Datentypen (siehe auch [[Programmieren in C/C++: Grundlagen# Grundlegende Datentypen und Typsicherheit| Grundlagen:Grundlegende Datentypen und Typsicherheit]])
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| [[#Ganzzahl Datentypen|Ganzzahl]] ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| [[#Gleitkomma Datentypen|Gleitkommazahl]] ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Array|Arrays]] ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| [[#Struktur/Verbundtyp|Strukturen]]/[[#Union|Unions]] ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| [[#Enum/Aufzählungstyp|Aufzählungstyp]] ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Grundlagen #Boolescher-Datentype/Operatoren|Boolescher Datentyp]] ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| [[#Komplexe Zahlen|Komplexe Zahlen]] ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
Bis auf die Datentypen Funktionen, Array und die Zeiger sollen die wesentlichen Aspekte dieser Datentypen im nachfolgenden beschrieben werden.
'''Der grundlegende Datentyp ist <code>int</code>!'''
* Es wird mit nichts Kleinerem gerechnet als mit dem Datentyp <code>int</code> (siehe [[#Implizite Typumwandlung | Implizite Typumwandlung]]) :
:<syntaxhighlight lang="C">
char var1=10,var2=20,var3;
var3=var1+var2; //Addition findet auf Basis des Datentyps int statt
</syntaxhighlight>
* Es gibt zwar den Booleschen Datentyp, dieser entspricht jedoch einem Ganzzahldatentyp und <code>true</code> und <code>false</code> entsprechen den Integerwerten 0 und 1
* Der Aufzählungsdatentyp und seine Aufzählungselemente sind vom Datentyp <code>int</code>
* Bis einschl. C90 wurde bei der Definition von Variablen ohne Angabe des Datentyps, bei Definition einer Funktion ohne Angabe des Datentyps der Übergabeparameter, des Rückgabedatentyps der Datentyp implizit auf int gesetzt ('''implizit int''')
:<syntaxhighlight lang="C">
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}int main(int argc,char *argv[]) {
printf("%d",foo(1,var2));
return 0;
} | execCompilerOptions=-Wall -std=c90|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Ganzzahl Datentypen ==
Grundlegend kennt die Programmiersprache C nur zwei Ganzzahldatentypen:
* Datentyp: <code>int</code>
: Vorzeichenbehafteter (signed) Datentyp, dessen Bitbreite von der Rechnerarchitektur und des Compilers abhängig ist
* Datentyp <code>char</code>
: Datentyp mit einer Mindestbreite von 8-Bit u.A. zur Speicherung von Zeichen typischerweise im ASCII Format. Die C-Spezifikation [C11 6.2.5 Types] lässt es dem Compiler frei, ob <code>char</code> als vorzeichenbehafteter oder vorzeichenloser Datentyp implementiert wird.
: Ergänzend kann der Datentyp <code>char</code> auch zur Speicherung von ganzen Zahlen genutzt werden. In diesem Fall empfiehlt sich, diese explizit als <code>signed</code> und <code>unsiged</code> zu definieren. Wenn nur ASCII Zeichen gespeichert werden, so ist diese Angabe nicht nötig!
Optional können Qualifier dem Datentyp vorangestellt werden:
* <code>unsigned</code> / <code>signed</code> zur Angabe, ob der Inhalt als vorzeichenlose Zahl oder als vorzeichenbehaftete Zahl zu interpretieren ist. Ohne Angabe sind Variablen vom Datentyp <code>int</code> vorzeichenbehaftet
* <code>short</code> / <code>long</code> / <code>long long</code> (letzteres seit C99) als vorangestellten Qualifier zu <code>int</code> zur Vergrößerung/Verkleinerung der Bitbreite. Bei Angabe des Qualifiers ist das Schlüsselwort <code>int</code> optional. Die Beschreibung <code>long long int</code> und <code>long long</code> sind gleichbedeutend!
Als Bitbreite für die Datentypen ist im C-Standard nur ein Mindestbreite definiert. Die genaue Bitbreite hängt von der Rechenbreite des Systems und vom Compiler ab (siehe [C11 6.2.5 Types]):
{| class="wikitable"
|-
! Datentype !! Mindest<br />breite !! Typisch bei 32-Bit<br />Architektur !! Typisch bei 64-Bit<br />Architektur !! printf Format<br />Anweisung
|-
| <code>char</code> || 8 || 8 || 8 || <code>%c</code>
|-
| <code>signed char</code><br /><code>unsigned char</code>|| 8 || 8 || 8 || <code>%hhd</code><br /><code>%hhu</code>
|-
| <code>short</code><br /><code>short int</code>|| 16 || 16 || 16 || <code>%hd</code> / <code>%hu</code>
|-
|<code>int</code>|| 16 || 16/32 || 32 || <code>%d</code> / <code>%u</code>
|-
|<code>long</code><br /><code>long int</code>|| 32 || 32 || 32/64 || <code>%ld</code> / <code>%lu</code>
|-
|<code>long long</code><br /><code>long long int</code>|| 64 || 64 || 64 || <code>%lld</code> / <code>%llu</code>
|}
In der Header-Datei <code>limits.h</code> sind die tatsächlichen Grenzwerte der Datentypen gespeichert:
{| class="wikitable"
|-
! Konstante !! Beschreibung !! Typ. bei 64-Bit Architektur
|-
| <code>CHAR_BIT</code> || Anzahl der Bits in einem Char || 8
|-
| <code>SCHAR_MIN</code> || min. Wert, den der Typ bei signed char aufnehmen kann || -128
|-
| <code>SCHAR_MAX</code> || max. Wert, den der Typ bei signed char aufnehmen kann || 127
|-
| <code>UCHAR_MAX</code> || max. Wert, den der Typ bei unsigned char aufnehmen kann || 255
|-
| <code>CHAR_MIN</code> || min. Wert, den der Typ char aufnehmen kann || 0 oder SCHAR_MIN
|-
| <code>CHAR_MAX</code> || max. Wert, den der Typ char aufnehmen kann || SCHAR_MAX oder UCHAR_MAX
|-
| <code>SHRT_MIN</code> || min. Wert, den der Typ short int annehmen kann || -32.768
|-
| <code>SHRT_MAX</code> || max. Wert, den der Typ short int annehmen kann || 32.767
|-
| <code>USHRT_MAX</code> || max. Wert, den der Typ unsigned short int annehmen kann || 65.535
|-
| <code>INT_MIN</code> || min. Wert, den der Typ int annehmen kann || -2.147.483.648
|-
| <code>INT_MAX</code> || max. Wert, den der Typ int annehmen kann || 2.147.483.647
|-
| <code>UINT_MAX</code> || max. Wert, den der Typ unsigned int aufnehmen kann || 4.294.967.296
|-
| <code>LONG_MIN</code> || min. Wert, den der Typ long int annehmen kann || -2.147.483.648 oder<br />-9.223.372.036.854.775.808
|-
| <code>LONG_MAX</code> || max. Wert, den der Typ long int annehmen kann || 2.147.483.647 oder<br />9.223.372.036.854.775.807
|-
| <code>ULONG_MAX</code> || max. Wert, den der Typ unsigned long int annehmen kann || 4.294.967.296 oder<br />18.446.744.073.709.551.616
|-
| <code>LLONG_MIN</code> || min. Wert, den der Typ long long int annehmen kann || -9.223.372.036.854.775.808
|-
| <code>LLONG_MAX</code> || max. Wert, den der Typ long long int annehmen kann || 9.223.372.036.854.775.807
|-
| <code>ULLONG_MAX</code> || max. Wert, den der Typ unsigned long long int annehmen kann || 18.446.744.073.709.551.615
|}
Aufgrund dessen, dass die Breite der Datentypen von der Rechnerarchitektur und vom Compiler abhängig ist, sind in der Header-Datei <code>stdint.h</code> Aliase für Datentypen enthalten, welche in ihrem Alias die tatsächliche Breite und das Vorzeichens beinhalten:
<syntaxhighlight lang="C">
uint8_t --> unsigned 8-Bit
int8_t --> signed 8-Bit
uint16_t --> unsigned 16-Bit
int16_t --> signed 16-Bit
...
</syntaxhighlight>
In C++ sind diese Aliase im <code>std</code> namespace definiert:
<syntaxhighlight lang="C++">
std::intptr_t
std::int8_t std::uint8_t
std::int16_t std::uint16_t
std::int32_t std::uint32_t
Std::int64_t std::uint64_t
</syntaxhighlight>
Zur Erzeugung von portablen/rechnerunabhängigen Programmen empfiehlt sich, diese Datentypen zu nutzen. Die Rechenbreite ist dann unabhängig vom Compiler und Betriebssystem.
== Gleitkomma Datentypen ==
Gleitkommazahlen werden im Computer auf Basis folgender Schreibweise dargestellt (siehe auch: {{w|Gleitkommazahl}}):<br />
<syntaxhighlight lang="C">
Dezimalsystem Dualsystem
12,3456710 = 1234567 * 10^-5 0,110 = 1,1001100110011 * 2^-4
------- -- --------------- --
Mantisse Exponent Mantisse Exponent
</syntaxhighlight>
;Mantisse: Vorzeichenlose ganze Zahl (ggf. mit einer festen Position des Dezimalpunktes=Festkommazahl)
;Exponent: Vorzeichenbehaftete ganze Zahl, welche um einen Bias verschoben ist
;Vorzeichen: Vorzeichen der (vorzeichenlosen) Mantisse
Zur Speicherung im Computer werden das Vorzeichen, die Mantisse und der Exponent getrennt im Binärformat gespeichert, für den Programmierer aber als eine (zusammenhängende) Zahl dargestellt:
[[File:Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse.png|thumb|400px|center|Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse]]
Gleitkommazahlen haben genauso wie ganze Zahlen einen beschränkten Wertebereich:
* Die Anzahl der Bits der Mantisse bestimmen die Anzahl der Nachkommastellen:
:<syntaxhighlight lang="C">
Bei 23-Bit Mantisse ist die max. Zahl 2^-23-1=0,000000119,
welches 6..7 dezimale Stellen entspricht!
</syntaxhighlight>
* Mit dem Exponent kann 'quasi' der kleinste und der größte Wertebereich angegeben werden:
:<syntaxhighlight lang="C">
Bei 8-Bit Exponent mit einem Bias von 127 liegt der Wertebereich des
Exponenten im Bereich von -126 … +127 (Exponent -127 und +127 wird zur
Darstellung weitere Zahlen benötigt).
Die kleinste darstellbare Zahl (unter Vernachlässigung der Nachkommastellen der Mantisse ist:
2^-126=1/2^126≅1,175*10^-38
Die größte darstellbare Zahl ist:
2^127 ≅1,7*10^38
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
float sqrtf(float);
float powf(float,float);
#include <ieee754.h>
#include <complex.h>
union test {
unsigned int i;
float f;
union ieee754_float b;
};
int main(int argc,char *argv[]) {
union test var = {.f=-0.1};
printf("Float=%f Binär=%032b\n",var.f,var.i);
printf("v=0b%b e=0b%08b m=0b(1).%023b\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%10d m=%29d\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%d-%d=%d m=1+%d/2^-23=%f\n",var.b.ieee.negative,
var.b.ieee.exponent,IEEE754_FLOAT_BIAS,var.b.ieee.exponent-IEEE754_FLOAT_BIAS,
var.b.ieee.mantissa,1.0+var.b.ieee.mantissa*1.0/(1<<23));
printf("\n--- Beispiele von Genauigkeitsprobleme im Umgang mit Gleitkommazahlen (hier float) ----\n");
printf("powf(sqrtf(%1.8f),2) = %1.8f\n",2.0f,powf(sqrtf(2.0f),2));
printf("%f + %f = %f\n",2000.0,0.0004,(double)(2000.0f+0.0004f));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Grundlegend kennen die Programmiersprachen C/C++ folgende Gleitkommadatentypen:
* Datentyp: <code>float</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindesten 6 Stellen betragen, so dass der Datentyp typischerweise 32-Bit groß ist
* Datentyp: <code>double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, so dass der Datentyp typischweise 64-Bit Große ist
* Datentyp: <code>long double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, damit könnte dieser Datentyp gleich dem Datentyp <code>double</code> gesetzt werden. In der Tat ist die Datenbreite Rechner- und Compilerabhängig. Einige Compiler setzen diesen Datentyp identisch zu <code>double</code>, bei x86 Prozessoren wird aufgrund der Hardwareunterstützung 80-Bit genutzt (wobei in der Tat der Datentyp aufgrund von alignment dann 16-Byte Speicherplatz beansprucht) und einige Systeme nutzen 128-Bit (wobei hier aufgrund ggf. fehlender Hardwareunterstützung Operationen mit diesem Datentyp per Software emuliert werden) (siehe Wikipedia Artikel {{w|lang=en|Long_double|long double}}).
Die genaue Darstellung (Anzahl der Bits für Mantisse und Exponent, Darstellung von NAN/INF, ….) ist in C nicht spezifiziert und somit compiler- und rechnerabhängig. Zumeist wird mittlerweile die {{w|IEEE 754}} Standardisierung genutzt (Norm wurde von Intel mit der Entwicklung der 8087 FPU entworfen).
Grunddatentypen und der Wertebereich (nach {{w|IEEE 754}})
{| class="wikitable"
|-
! Daten-<br/>type !! Speicher-<br />platz !! Exponent !! Mantisse !! Größte Zahl !! Kleinste Zahl !! Genauigkeit !! printf Format Anweisung
|-
| binary32→<code>float</code> || 4 Byte || 8 bit || 23 bit || ~3,4*10<sup>38</sup> || ~1,2*10<sup>-38</sup> || 7..8 Stellen || ---
|-
| binary64→<code>double</code> || 8 Byte || 11 bit || 52 bit || ~1,8*10<sup>308</sup> || ~2,2*10<sup>-308</sup> || 15..16 Stellen || %f %e %g
|-
| binary64 extended→<code>long double</code> || ≥10 Byte || ≥15 bit || ≥63 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 19..20 Stellen || %Lf %Le %Lg
|-
| binary128→<code>long double</code> || 16 Byte || 15 bit || 112 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 34 Stellen || %Lf %Le %Lg
|}
Die tatsächliche Auflösung der Datentyps kann auf Basis nachfolgender Konstanten, definiert in der Header-Datei <code>float.h</code>, ermittelt werden:
:<syntaxhighlight lang="C">
FLT_DIG --> Anzahl der dezimalen Nachkommastellen für float
DBL_DIG --> Anzahl der dezimalen Nachkommastellen für double
LDBL_DIG --> Anzahl der dezimalen Nachkommastellen für long double
FLT_MIN_10_EXP --> Minimaler Exponent zur Basis 10
DBL_MIN_10_EXP
LDBL_MIN_10_EXP
FLT_MAX_10_EXP --> Maximaler Exponent zur Basis 10
DBL_MAX_10_EXP
LDBL_MAX_10_EXP
LDBL_MANT_DIG --> Anzahl der Bits für die Mantisse
LDBL_MANT_DIG
LDBL_MANT_DIG
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <float.h>
int main(){
printf("FLT_DIG =%u\n",FLT_DIG);
printf("DBL_DIG =%u\n",DBL_DIG);
printf("LDBL_DIG =%u\n",LDBL_DIG);
printf("FLT_MIN_10_EXP =%d\n",FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP =%d\n",DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP=%d\n",LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP =%d\n",FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP =%d\n",DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP=%d\n",LDBL_MAX_10_EXP);
printf("FLT_MANT_DIG =%d\n",FLT_MANT_DIG);
printf("DBL_MANT_DIG =%d\n",DBL_MANT_DIG);
printf("LDBL_MANT_DIG =%d\n",LDBL_MANT_DIG);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Aufgrund des nicht standardisierten Formates sollte ein Gleitkommadatentyp nicht im Binärformat für den Datenaustausch (mit Netzwerk, über Dateien, ..) genutzt werden. Andere Rechnersysteme/Programmiersprachen würde aufgrund der anderen Interpretation andere Zahlenwerte aus den übertragenen/gespeicherten Binärdaten auslesen!
<syntaxhighlight lang="C">
float var1;
write(file_hdl,&var1,sizeof var1); //Schreiben des Binärwertes
//in eine Datei
double var2;
send(socket_hdl,&var2,sizeof var2,0);//Senden des Binärwertes
//über ein Netzwerk
</syntaxhighlight>
Die Standard-C-Library bietet einige mathematische Funktionen wie <code>sin() / cos() / tan() / atan2() / sqrt() / pow() / exp()/…</code> an. Die Prototypen dieser Funktion sind in der Header-Datei <code>math.h</code> beschrieben, so dass diese bei Nutzung dieser Funktion zu inkludieren ist. Ergänzend ist die Shared Library libm.so über den Compilerschalter '-lm' einzubinden:
<syntaxhighlight lang="C">
#include <math.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
double sqrt(double);
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
printf("var1=%f var2=%f\n",var1,var2);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen basieren auf den Datentyp <code>double</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist vom Datentyp <code>double</code>. Die Prototypen sehen wie folgt aus:
<syntaxhighlight lang="C">
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double); //Wertebereich der Rückgabe von -PI/2..+PI/2
double atan2(double,double); //Wertebereich der Rückgabe von -Pi .. +PI
double sqrt(double);
double log(double);
</syntaxhighlight>
Über den Suffix f oder l im Funktionsnamen kann der zugrundeliegende Datentyp auf <code>float</code> (Suffix f) oder <code>long double</code> (Suffix l) geändert werden:
<syntaxhighlight lang="C">
float sinf(float);
long double sinl(long double);
</syntaxhighlight>
Ergänzend zu den Prototypen sind die gebräuchlichen Naturkonstanten in <code>math.h</code> definiert (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
M_E Value of e
M_LOG2E Value of log_2 e
M_LOG10E Value of log_10 e
M_LN2 Value of log_e 2
M_LN10 Value of log_e 10
M_PI Value of π
M_PI_2 Value of π/2
M_PI_4 Value of π/4
M_1_PI Value of 1/π
M_2_PI Value of 2/π
M_2_SQRTPI Value of 2/√π
M_SQRT2 Value of √2
M_SQRT1_2 Value of 1/√2
</syntaxhighlight>
Gleitkommazahlen können nicht nur Zahlenwerte, sondern auch Sonderwerte annehmen. Diese Sonderwerte sind ebenfalls in <code>math.h</code> beschrieben (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
INFINITY A constant expression of type float representing
positive or unsigned infinity, if available; else a
positive constant of type float that overflows at
translation time.
NAN A constant expression of type float representing a
quiet NaN. This macro is only defined if the
implementation supports quiet NaNs for the float type.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <math.h>
//Quelle: https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c
#ifdef NAN
#define NAN_STR "NAN is supported"
#else
#define NAN_STR "NAN is not supported"
#endif
#ifdef INFINITY
#define INFINITY_STR "INFINITY is supported"
#else
#define INFINITY_STR "INFINITY is not supported"
#endif
int main(int argc, char *argv[argc]) {
printf("%s\n%s\n",NAN_STR,INFINITY_STR);
double x=0.0;
double y=1/x;
printf("1/%e -> %e\n",x,y);
if(y==INFINITY)
printf("1) Initinity\n");
if(isinf(y)) //besser
printf("2) Initinity\n");
printf("%llx\n%llx\n\n",*(long long *)&y,INFINITY);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
double z=-(x/x);
printf("%e/%e -> %e\n",x,x,z);
if(z == NAN) //funktioniert nicht
printf("1) Not a Number\n");
if(isnan(z)) //besser
printf("2) Not a Number\n");
if(z != z)
printf("3) Not a Number\n");
printf("%llx\n%llx",*(long long *)&z,NAN);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
return 0;
} | execCompilerOptions=-lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit <code>fesetround()/fegetround()</code> kann gesetzt/gelesen werden, wie mit Ergebnissen umzugehen sind, die nicht exakt darstellbar sind. Mögliche Werte sind 'round to nearest' (default), 'round up', 'round down' und 'round toward zero'.
== Komplexe Zahlen ==
Nach dem Wikipedia Artikel {{w|komplexe Zahlen}} ''stellen komplexe Zahlen eine Erweiterung der reellen Zahlen dar. Ziel der Erweiterung ist es, algebraische Gleichungen wie x<sup>2</sup>+1=0 bzw. x<sup>2</sup>=-1 lösbar zu machen. ... Da die Quadrate aller reellen Zahlen größer oder gleich 0 sind, kann die Lösung der Gleichung x<sup>2</sup>=-1 keine reelle Zahl sein. Man braucht eine ganz neue Zahl, die man üblicherweise i nennt, mit der Eigenschaft i<sup>2</sup>=-1. Diese Zahl i wird als imaginäre Einheit bezeichnet.
Komplexe Zahlen werden nun als Summe a+b*i definiert, wobei a und b reelle Zahlen sind und i die oben definierte imaginäre Einheit ist.''<br />
Der Datentyp für komplexe Zahlen (erst ab C99 enthalten) beinhaltet folglich zwei Gleitkommazahlen, eine für den reelen Teil und eine für den imaginären Teil. Entsprechend den Gleitkommazahlen steht der komplexe Datentyp ebenfalls in drei unterschiedlichen Genauigkeiten zur Verfügung:
{| class="wikitable"
|-
! Datentype !! Speicherplatz
|-
| <code>float _Complex</code> || 2x4Byte
|-
| <code>double _Complex</code><br /><code>_Complex</code> || 2x8Byte
|-
| <code>long double _Complex</code> || 2x10Byte
|}
Wie auch beim Booleschen Datentyp ist in der Header-Datei <code>complex.h</code> für den einfacheren Umgang mit diesem Datentyp das Makro <code>complex</code> als Textersetzung für <code>_Complex</code> gesetzt.
Zur Darstellung von komplexen Konstanten wurde die Gleitkommakonstante um den Suffix i ergänzt. Durch Anhängen von i wird aus dem ansonsten rellen Teil der imaginäre Teil und damit aus der Gleitkommakonstante eine komplexe Gleitkommakonstante:
<syntaxhighlight lang="C">
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Normale Gleitkommavariablen werden als reellen Teil einer komplexen Zahl angesehen. Bei Operationen von Gleitkommazahlen und komplexen Zahlen wird der imaginäre Teil der Gleitkommazahl auf 0 gesetzt. Beim Zuweisen einer komplexen Zahl an eine Gleitkommazahl wird nur der reele Teil 'gelesen'.<br />
Soll eine Gleitkommavariablen zu einem imaginären Teil gewandelt werden, so muss diese bspw mit der Konstanten 1.0i multipliziert werden:
<syntaxhighlight lang="C">
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C-Library bietet diverse mathematische Funktionen wie csin(), ccos(), csqrt(), cpow() und ergänzend Umrechnungsfunktionen von Gleitkommazahlen in komplexe Zahlen (und umgedreht) wie creal(),cimag() ,cabs() für den Umgang mit komplexen Zahlen an:
<syntaxhighlight lang="C">
double _Complex csin(double _Complex);
double _Complex csqrt(double _Complex);
double creal(double _Complex);
double cimag(double _Complex);
</syntaxhighlight>
Zur Nutzung dieser Funktionen muss die Header-Datei <code>complex.h</code> inkludiert und ergänzend die Shared Library libm.so über den Compilerschalter '-lm' eingebunden werden.
<syntaxhighlight lang="C">
#include <complex.h>
//Math-Library mittels Linker-Command '-lm' einbinden
int main(int argc, char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen beruhen auf den Datentyp <code>double _Complex</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist <code>double _Complex</code> resp. <code>double</code> (bei den Umrechnungsfunktionen). Über den Suffix f und l im Funktionsnamen kann der zugrundeliegende Datentyp geändert werden:
<syntaxhighlight lang="C">
float crealf(float _Complex z);
long double creall(long double _Complex z);
</syntaxhighlight>
Hinweis:
* Der Datentyp <code>_Complex</code> und die dazugehörigen mathematischen Funktionen sind in der C-Spezifikation als optional gekennzeichnet.
== Generische mathematische Funktionen ==
In der <code>tgmath.h</code> Header Datei sind für die mathematischen Funktionen Makros enthalten, welche den Datentyp der Übergabeparameter bestimmen und basierend auf den Datentyp die dazugehörige mathematische Funktion aufrufen.
<code>tgmath.h</code> selbst inkludiert <code>math.h</code> und <code>complex.h</code>, so dass diese nicht weiter zu inkludieren sind.
Steht für den Übergabedatentyp keine passende Funktion zur Verfügung, so ist das Verhalten des Makros undefiniert (bspw. wenn ein komplexes Argument an eine Funktion übergeben wird, die nur für Gleitkommazahlen ausgelegt ist <code>ceil(1+2i);</code> )
Folgendes Regelwerk wird angewendet:
* Ist einer der Übergabeparameter imaginär, so ist die ausgewählte Funktion in der Spezifikation der Funktion beschrieben
* Ist einer der Übergabeparameter Komplexe, so wird die komplexe Variante der Funktion aufgerufen, andernfalls die Gleitkomma Variante
* Ist einer der Übergabeparameter vom Datentyp <code>long double</code>, so wird die <code>long double</code> Variante, bei Ganzzahlen und <code>double</code> die <code>double</code> Variante und andernfalls die <code>float</code> Variante aufgerufen
Beispiel:
<syntaxhighlight lang="C">
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
int main(int argc,char *argv[]) {
foo(1l+1li,2.0l,3.0f,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=c
}} Öffnen im Compiler Explorer] }}
== Boolschescher Datentyp ==
Siehe [[Programmieren in C/C++: Grundlagen#Boolescher-Datentype/Operatoren|Grundlagen: Boolescher-Datentype/Operatoren]]
== void / unvollständiger Datentype ==
Der Datentyp <code>void</code> dient vorrangig dazu, nicht vorhandene Über- und Rückgabewerte von Funktionen anzuzeigen. Eine Variable vom Datentyp <code>void</code> kann nicht angelegt werden. Ein Zeiger vom Datentyp <code>void</code> ist möglich, kann aber nicht dereferenziert werden (siehe Kap. [[Programmieren in C/C++: Zeiger #Void-Zeiger| Zeiger:Void-Zeiger]])
<syntaxhighlight lang="C">
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(void); //Void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* <code>sizeof(void)</code> ist nach der C-Spezifikation nicht erlaubt. Dennoch geben viele Compiler hier den Wert 1 zurück!
* Mit einem expliziten Cast auf den Datentyp void wird dem Compiler mitgeteilt, dass diese Variable in Gebrauch ist, der Wert in dieser Operation aber nicht genutzt wird. Hierüber kann die Compilerwarning 'unused Variable' unterbunden werden:
:<syntaxhighlight lang="C">
void func(int par1, int par2) {
int var1=12;
int var2=13;
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int par1, int par2) {
int var1=12;
int var2=13;
int var3=14; //Nicht genutzte Variable
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
printf("Genutzt\n");
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Datentypkonvertierung ==
Für das Rechnen/Vergleichen müssen beide Operatoren vom identischen Datentyp sein! Sind diese nicht identisch, so müssen die Datentypen 'angeglichen' werden. Dies kann einerseits ‚automatisch‘ mittels 'implizierter' Typumwandlung oder ‚manuell‘ mittels ‚expliziter' Typumwandlung erfolgen.<br />
Beim Zuweisungsoperator (inkl. Parameterzuweisung bei Funktionsaufrufen und Funktionsrückgabewerte mittels return) gilt dies ebenso, nur dass hier der Quelldatentyp an den Zieldatentyp angepasst werden muss. Die impliziten Regeln finden hier keine Anwendung.
Hinweis:
* Empfehlenswert ist, die Datentypen der Variablen so zu wählen, dass der Compiler keine implizite Typumwandlung tätigt. Kann dies nicht vermieden werden, so sollte die explizite Typumwandlung genutzt werden (um sich einen möglichen Datenverlust bewusst zu machen)
* Der Datentyp selbst sollte den möglichen Wertebereich der Variablen entsprechen und nicht unnötig groß gewählt werden
:<syntaxhighlight lang="C">
Datentyp zur Speicherung der Stundenzeit:
Wertebereich: 0 ... 23 -> unsigned char
Datentyp zur Speicherung einer Jahreszahl:
Wertebereich: 2000 v.C. ... 4000 n.C -> signed short
Datentyp zur Speicherung einer Temperatur:
Wertebreich: -273,0°C ... 2000,0°C -> float
</syntaxhighlight>
=== Implizite Typumwandlung ===
Diese Regeln wurden so aufgestellt, dass dabei stets ein Datentyp in einen anderen Datentyp mit höherem Wertigkeit umgewandelt wird [C11 6.3.1.8] und [Harbison: S 199]. Bei Ganzzahlen gilt ergänzend folgende (Rangordnung [C11 6.3.1.1]: long long, long, int, short,char,_Bool):
{| class="wikitable"
|-
! Regel/<br />Priorität !! If either operand<br />has Type !! And the other operand<br />has Type !! Converts both to
|-
| 1 (hoch) || long double || any real type || long double
|-
| 2 || double || any real type || double
|-
| 3 || float || any real type || float
|-
| 4 || any unsigned type || any unsigned type || the unsigned type<br/>with the greater rank
|-
| 5 || any signed type || any signed type || the signed type<br/>with the greater rank
|-
| 6 || any unsigned type || a signed type with a equal<br/> or less rank || the unsigned type
|-
| 7 || any unsigned type || a signed type that can represent<br/>all of values of the unsigned type || the signed type
|-
| 8 (niedrig) || any other type || any other type || both operands are<br/> converted to the unsigned <br/>integer type corresponding<br/> to the type of the operand<br/> with the signed<br/> integer type
|}
Ergänzend gilt das Regelwerk zu Integer Promotion, welche Datentypen kleiner als <code>signed int</code> zu <code>int</code> und kleiner als <code>unsigned int</code> zu <code>unsigned int</code> konvertiert (Compiler kann hiervon abweichen, wenn sichergestellt ist, dass kein Datenverlust eintritt).
Regel 6 und 7 sind der nicht klar definierten Bitbreite der ganzzahligen Datentypen geschuldet und versuchen, Konvertierungsverluste zu vermeiden. Sie lesen sich zunächst kryptisch, lassen sich aber einfach am folgenden Beispiel erklären:
<syntaxhighlight lang="C">
Operand 1: unsigned int (hier 32-Bit)
Operand 2: long (hier 32-Bit / 64-Bit)
</syntaxhighlight>
* Im Fall, dass der Datentyp <code>long</code> 64-Bit breit ist, kann dieser problemlos die vorzeichenlose 32-Bit Zahl ohne Konvertierungsverluste repräsentieren, so dass der Zieltype <code>signed long</code> ist (Regel 7)
* Im Fall, dass der Datentyp <code>long</code> 32-Bit breit ist, kann dieser mit seinen Wertebereich von -2.147.483.648 bis +2.147.483.647 nicht den vorzeichenlosen Zahlenbereich von 0…4.294.967.295 darstellen. In diesem Fall hat der unsigned Datentyp einen höheren Rang, so dass als Zieltyp <code>unsigend long</code> gewählt wird (Regel 6)
'''Regel 6 bedeutet die Gefahr eines Konvertierungsverlustes, dessen man sich bewusst sein sollte!''' Diese tritt insb. dann in Kraft, wenn ein Operand vom Typ <code>unsigned long long</code> ist (64-Bit).
Beispiele von impliziten Typumwandlungen:
<syntaxhighlight lang="C">
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
vari=5.0*(int)sin(vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ Wikibooks Formatierung schlägt hier fehlt
double sin(double);
int main(int argc,char *argv[]) {
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
printf("vars=%hd\n",vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
printf("vars=%hd\n",vars);
vari=5.0*(int)sin(vars);
printf("vari=%d\n",vari);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
printf("vari=%d\n",vari);
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im CompilerExplorer können sie sich die impliziten Typumwandlungen anzeigen lassen. Dazu gehen sie bitte wie folgt vor:
:* Im Source-Fenster mit '+Add new' ein Compiler Fenster öffnen
:* Im Compiler-Fenster mit '+Add new' ein 'GCC Tree/RTL' Fenster öffnen
:* Im GCC Tree/RTL-Fenster unter 'Select a pass…' 'original tree' auswählen
Um implizite Typumwandlung besser erkennen zu können, wird oftmals bei Variablennamen die ''' 'Ungarische Notation' ''' angewendet (siehe {{w|Ungarische Notation}}). Aufgrund der besonderen Namensgebung kann der Programmierer ohne großen Aufwand frühzeitig mögliche Typkonflikte erkennen. Der Variablenname setzt sich wie folgt zusammen:
<syntaxhighlight lang="C">
{Präfix}{Datentyp}{Bezeichner}
</syntaxhighlight>
:'''Präfix''': p->Pointer h->Handle i->index c->count f->flag rg->Array
:'''Datentyp''': ch->Character st->string w->word b->byte…
:'''Bezeichner''': Zum Binden der Variable an eine konkrete Aufgabe (keine Unterstriche).
:Bezeichner ist optional, wenn aus Präfix und Datentyp die 'Aufgabe' der Variable direkt sichtbar ist
Beispiele:
<syntaxhighlight lang="C">
char rgchtemp[10]; //Array (Range) vom Datentyp character
int ich; //Index zum Adressieren eines Arrays vom Datentyp
//character
</syntaxhighlight>
=== Explizite Typumwandlung ===
Programmierer erzwingt durch explizite Typumwandlung (auch CASTen genannt) eine Umwandlung eines Datentyps in einen anderen. Dazu wird der Zieldatentyp in runden Klammern vor Quelldatentype geschrieben:
<syntaxhighlight lang="C">
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
In der Rangfolge der Operatoren steht der Cast-Operator unterhalb von bspw. Funktionsaufrufen, Arrayzugriffen aber auch der Dereferenzierung:
{| class="wikitable"
|-
! Priorität !! Symbol !! Assoziativität !! Bedeutung
|-
| 15 || ... || ... || ...
|-
| 14
||
++/-- (Präfix)<br />
+/- (Vorzeichen) <br />
<nowiki>!</nowiki>/~ <br />
&<br />
<nowiki>*</nowiki><br />
(TYP)<br />
...
|| R-L
||
Präfix-Inkrement/Dekrement<br />
Vorzeichen<br />
Logisches/Bitweises Nicht<br />
Adresse<br />
Zeigerdereferenzierung<br />
'''Typumwandlung (Explizites Cast)'''<br />
...
|-
| 13
||
* / %
|| L-R
|| Multiplikation/Division/Modulo
|-
| 12 || ... || ... || ...
|}
Im Zweifel gilt auch hier, den zu wandelnden Typ ergänzend zu klammern.
Hinweis:
* Bedenke, dass die explizite Typumwandlung so aufgestellt sein sollte, dass der Zieldatentyp dem notwendigen Datentyp entspricht. Andernfalls wendet der Compiler ergänzend eine implizierte Typumwandlung an:
:<syntaxhighlight lang="C">
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Mittels expliziter Typumwandlung können Ganzzahl nach Gleitkommazahlen (und andersherum) und Zeiger in einen anderen Zeiger und auf andere Datentypen gewandelt werden. Eine Konvertierung von Arrays, Strukturen, Unions zu anderen Datentypen als sich selbst ist weiterhin nicht möglich:
<syntaxhighlight lang="C">
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei den möglichen Konvertierungen sollte Folgendes berücksichtigt werden:
* '''Vorzeichenlose Ganzzahl''' → '''Vorzeichenlose Ganzzahl''': Wenn der Zieldatentyp größer ist, wird die Zahl durch führende '0' erweitert. Wenn der Zieldatentyp kleiner ist, werde die zu vielen Bitstellen abgeschnitten/verworfen (ggf. Datenverlust)
* '''Vorzeichenbehaftete Ganzzahl''' → '''Vorzeichenbehaftete Ganzzahl''': Wenn der Zieldatentyp größer ist, wird vorzeichenrichtig erweitertet (d.h. das Auffüllen erfolgt auf Basis des Vorzeichens). Wenn der Zieldatentyp kleiner ist, werden auch hier die zu vielen Bits abgeschnitten/verworfen (Vorsicht: Negative Zahlen können dabei in positive Zahlen gewandelt werden)
* '''Gleitkommazahl''' → '''Gleitkommazahl''': Hier wird vereinfacht ausgedrückt sowohl die Mantisse als auch der Exponent einzeln kopiert. Wenn die Zielmantisse kleiner ist, gehen 'Nachkommastellen' verloren. Wenn der Quellexponent einen größeren Wert beinhaltet, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf Unendlich gesetzt. Umgedreht, wenn der Quellexponent kleiner ist, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf 0 gesetzt
* '''Ganzzahl''' → '''Gleitkommazahl''': Hier wird, vereinfacht ausgedrückt, die Ganzzahl in die Mantisse kopiert. Um Datenverluste zu vermeiden, sollte die Bitbreite der Zielmantisse größer gleich der Bitbreite der Ganzzahl sein
* '''Gleitkommazahl''' → '''Ganzzahl''': Im Wesentlichen wird hier die Mantisse übernommen, so dass hier die Bitbreite des Zieldatentyps mindestens der Bitbreite der Mantisse sein sollte
* '''Zeiger''' ↔ '''Ganzzahl''': Die Konvertierung ist möglich. Da bei 64-Bit Systemen der Zeiger 64-Bit und Integer 32-Bit breit ist, meckert ggf. der Compiler. Für solche Fälle existieren die Datentypen 'intptr_t' und 'uintptr_t', über welche sichergestellt ist, dass ein Zeiger in einen Ganzzahldatentyp gespeichert werden kann!
* '''Zeiger''' ↔ '''Gleitkommazahl''': Diese Konvertierung ist nicht möglich!
* '''Struktur/Union''' ↔ '''Ganzzahl/Gleitkommazahl''': Diese Konvertierung ist nicht möglich. Es können nur einzelnen Strukturelemente konvertiert werden, sofern diese vom Typ Ganzzahl/Gleitkommazahl sind
* '''Array''' ↔ '''Ganzzahl/Gleitkommazahl''': Der Arrayname entspricht einen Zeiger, so dass hier ein Zeiger in eine Ganzzahl oder umgedreht konvertiert wird (siehe Zeiger ↔ Ganzzahl)
In C++ gibt es weitere CAST-Operatoren, auf welche hier derzeit noch nicht weiter eingegangen wird!
* Static_cast (Entspricht dem Expliziten Cast)
* Const_cast
* Dynamic_cast
* Reinterpret_cast
== Verbundtyp Struktur/Klasse (nur C++) ==
Nach dem Wikipedia Artikel {{w|Verbund (Datentyp)}} ist ''ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten können wiederum Verbünde enthalten, wodurch auch komplexe Datenstrukturen definiert werden können.<br />
Für jedes Strukturelement wird Speicher reserviert. Alle Strukturelemente liegen hintereinander im Speicher.''
<code>Syntax: struct Strukturname<sub>Opt</sub> {Datentype Strukturelementname; … }<sub>OPT</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Verbund entspricht einer Java Klasse mit dem Unterschied zu C (nicht C++) , dass ein Verbund keine Methoden beinhaltet und keine Zugriffsbeschränkung für die Attribute gesetzt werden können.
Der Syntax erlaubt es, gleichermaßen einen Datentyp (über Strukturname) zu definieren und Variablen von diesem Datentyp (über Variablenliste) anzulegen. Da beide Elemente optional sind, ergeben sich diverse Kombinationsmöglichkeiten:
* Nur Strukturname → Definition eines neuen Datentyps
:<syntaxhighlight lang="C">
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
var1.y=2;
var1.z=1;
printf("var1.x=%d var1.y=%d var1.z=%d\n",var1.x,var1.y,var1.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C: Der Strukturname ist nur mit dem vorangestellten <code>struct</code> gültig. Der Strukturname stellt somit einen eigenen Namensraum, getrennt von dem Namensraum der Variablen/Funktionen, dar. Daher kann ein Strukturname identisch zu einem Variablennamen sein:
:<syntaxhighlight lang="C">
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
xyz2.x=xyz2.y=xyz2.z=1;
printf("xyz2.x=%d xyz2.y=%d xyz2.z=%d\n",xyz2.x,xyz2.y,xyz2.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C++: Der Strukturname ist sowohl mit als auch ohne dem vorangestellten <code>struct</code> gültig. Auch hier stellt der Strukturname einen eigenen Namensraum dar, der jedoch eine niedrigere Priorität als der der Variablen hat:
:<syntaxhighlight lang="C++">
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz beschreibt hier die Variable
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz3 beschreibt hier die Variable
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
* Nur Variablenliste → Definition einer/mehrerer Variablen von einem 'unnamed' Datentyp
:<syntaxhighlight lang="C">
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Angewendet wird die Schreibweise gerne, wenn eine Struktur innerhalb einer Struktur definiert wird und die innere Struktur zur besseren Strukturierung dient:
:<syntaxhighlight lang="C">
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Strukturname und Variablenliste → Definition eines Datentyps und Definition von Variablen. D.h. es können im Nachhinein weitere Variablen von diesem Datentyp angelegt und die hier angelegten Variablen genutzt werden.
:<syntaxhighlight lang="C">
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y; //Nutzung der Variablen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y=1; //Nutzung der Variablen
(void)var1;
(void)ptr1;
(void)ptr2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Kein Strukturname und keine Variablenliste → "Anonymous Struct", d.h. Definition eines 'unnamed' Datentyps, von der ergänzend keine Variable angelegt wird. Anonymus Structs sind nur innerhalb von Strukturen erlaubt/einsetzbar. Hier dienen sie der besseren Strukturierung und ersparen dem Programmierer die Benennung des normalerweise notwendigen Strukturelementes:
:<syntaxhighlight lang="C">
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
(void)var;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Eine Struktur (und auch eine C++ Klasse) wird mit einem Semikolon abgeschlossen
* Eine alternative Beschreibung zu Strukturen finden sie in [https://abstractexpr.com/2023/06/29/structures-in-c-from-basics-to-memory-alignment/ Structures in C: From Basics to Memory Alignment]
=== Strukturelement ===
Innerhalb der Struktur können beliebige Strukturelemente von beliebigen Datentypen angelegt werden. Einzige Voraussetzung, der Datentyp des anzulegenden Strukturelementes muss zuvor definiert worden sein. Ergänzend kann der neue Datentyp auch in der Struktur selbst definiert werden, sofern mit der Definition des Datentyps auch eine Variable angelegt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zugriff auf Strukturelemente ===
Die Programmiersprachen C/C++ unterscheiden zwei 'Zugriffsarten' auf die Strukturelemente, abhängig vom zugrundeliegenden Datentyp des linken Operanden::
* Handelt es sich beim linken Operanden um eine (struct)Variablen, so erfolgt der Zugriff über den Punkt-Operator <code>.</code>:
:<syntaxhighlight lang="C">
struct {
int a,b,c;
} abc;
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct {
int a,b,c;
} abc;
int main(int argc,char *argv[]) {
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c=12;
printf("abc.a=%d abc.b=%d abc.c=%d\n",abc.a,abc.b,abc.c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Handelt es sich beim linken Operanden um einen Zeiger auf eine (struct)Variable, so erfolgt der Zugriff über den Zeiger-Operator <code>-></code>:
:<syntaxhighlight lang="C">
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
int main(int argc,char *argv[]) {
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Werden innerhalb von Strukturen weitere Strukturen und Zeiger auf Strukturen angelegt, so müssen diese Regeln auf jedes innere Strukturelement einzeln angewendet werden:
<syntaxhighlight lang="C">
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
int main(int argc,char *argv[]) {
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Strukturen ===
Mit dem Anlegen einer Strukturvariablen kann diese auch initialisiert werden. Eine 'Vorbelegung' der Strukturelemente bei der Definition der Struktur ist in C nicht möglich.<br />
Die Initialisierung erfolgt über eine Initialisierungsliste (siehe Kap [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]). Innerhalb der Initialisierungsliste stehen die Initialisierungswerte entweder in der Reihenfolge der Datentypdefinition oder werden explizit mit dem ‘.‘ Operator angesprochen (designated initializers). Werden einzelne Strukturelemente ausgelassen, so werden diese mit 0 initialisiert:
<syntaxhighlight lang="C">
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
int main(int argc,char *argv[]) {
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
printf("v1.a=%d v1.b=%d v1.str[0]=%d\n",v1.a,v1.b,v1.str[0]);
printf("v2.a=%d v2.b=%d v2.str[0]=%d\n",v2.a,v2.b,v2.str[0]);
printf("v3.a=%d v3.b=%d v3.str[0]=%d\n",v3.a,v3.b,v3.str[0]);
printf("v4.a=%d v4.b=%d v4.str[0]=%d\n",v4.a,v4.b,v4.str[0]);
printf("v5.a=%d v5.b=%d v5.str[0]=%d\n",v5.a,v5.b,v5.str[0]);
printf("v6.a=%d v6.b=%d v6.str[0]=%d\n",v6.a,v6.b,v6.str[0]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Initialisierung einer Struktur über nachfolgende Art bewirkt etwas anderes, als erwartet:
<syntaxhighlight lang="C">
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
printf("var.a=%d var.b=%d var.c=%d\n",var.a,var.b,var.c);
//Gerne mal den Compiler Wechseln
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der Initialisierungsliste wird über 'var.b=12' und 'var.c=3' die zu diesem Zeitpunkt noch nicht initialisierte Variable var die Elemente b und c initialisiert. Mit dem Werten der Initialisierungsliste (hier {12,3}) wird nachfolgend die Variable erneut initialisiert und 12 dem Strukturelement a und 3 dem Strukturelement b zugewiesen. Abhängig vom Compiler ist das Strukturelement c entweder 3 oder 0.
Bei verschachtelten Strukturen muss entsprechend obiger Aussage für jede innere Struktur eine eigene Initialisierungsliste erstellt werden. Die inneren Initialisierungslisten können entfallen, was jedoch nicht empfohlen wird und ergänzend vom Compiler bei '-Wall' als Warning angemerkt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8}}
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={{.x=5,.y=6},{7,8}},
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8} }
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={ {.x=5,.y=6},{7,8} },
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
int main(int argc,char *argv[]) {
printf("v1.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v1.a, v1.b, v1.xy.x, v1.xy.y, v1.arr[0].x, v1.arr[0].y, v1.arr[1].x, v1.arr[1].y );
printf("v2.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v2.a, v2.b, v2.xy.x, v2.xy.y, v2.arr[0].x, v2.arr[0].y, v2.arr[1].x, v2.arr[1].y );
printf("v3.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v3.a, v3.b, v3.xy.x, v3.xy.y, v3.arr[0].x, v3.arr[0].y, v3.arr[1].x, v3.arr[1].y );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zuweisen/Kopieren von Strukturen ===
Strukturen werden über den Namen als 'ganzes' angesprochen, so dass eine Zuweisung als 'ganzes' möglich ist. Bei bspw. einer 12-Byte großen Struktur werden bei Nutzung der Variable die gesamten 12-Byte gelesen/geändert!
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1,var2;
var1=var2; //12-Bytes kopiert
//--> entspricht memcpy(&var1,&var2,sizeof(xyz));
</syntaxhighlight>
Die Zuweisung als 'ganzes' gilt auch bei der Parameterübergabe und -rückgabe von Funktionen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;};
//Funktionsdefinition
struct xyz function(struct xyz par) {
return (struct xyz){par.z,par.y,par.x};
}
//Funktionsaufruf
struct xyz var=function((struct xyz){1,2,3});
//Mit dem Aufruf der Funktion werden 12-Bytes in die Variable par kopiert
//Mit dem Ende der Funktion werden 12-Bytes in die Variable var kopiert
</syntaxhighlight>
Bedenke, dass bei großen Strukturen das Kopieren Rechenzeit benötigt und folglich vermieden werden sollte! Alternativ sollten Zeiger auf Strukturen über- und zurückgeben werden.
Über Compound Literal (siehe Kap. [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]) kann einer Strukturvariablen als 'ganzes' einen neuen Wert zugewiesen werden:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
var1={.a=7}; //KO, Initialisierungsliste kann hier nicht
//angewendet werden
var1=(struct abc){.a=7}; //Wertezuweisung über Compound Literal möglich
</syntaxhighlight>
Formel gesehen entspricht das Compound Literal einer 'unnamed Variable', die als erstes angelegt und initialisiert wird. Der Inhalt dieser Variablen wird im Anschluss der eigentlichen Variable zugewiesen!
=== Prototyp / Deklaration einer Struktur ===
Soll der Datentyp einer Struktur genutzt werden, der erst an weiter hinten liegenden Stellen im Programm definiert wird, so ist wie bei Variablen/Funktionen ein Prototyp/Deklaration notwendig:
<syntaxhighlight lang="C">
struct abc; //Prototyp der Struktur abc
...
struct abc { int a,b,c;}; //Definition der Struktur abc
</syntaxhighlight>
Die Deklaration sagt einzig aus, dass die Struktur später definiert wird, beinhaltet aber nicht die Strukturelemente. Folglich kann auf Basis dieses Prototyps keine Variable definiert werden, sondern einzig ein Zeiger auf solche eine Struktur:
<syntaxhighlight lang="C">
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Anwendung:
* Struktur, welche auf sich selbst verweist (Verkettete Liste)
:<syntaxhighlight lang="C">
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
int main(int argc,char *argv[]) {
struct vl *head=NULL;
struct vl a={.daten="Ele a"};
struct vl b={.daten="Element b"};
struct vl c={.daten="c-Eleent"};
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL; //Zur Kennzeichnung des letzten Elementes
for(struct vl*ptr=head;ptr;ptr=ptr->next)
printf("'%s'\n",ptr->daten);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Entsprechend der objektorientierten Programmierung, wenn alle Attribute der Klasse private sind:
:{| class="wikitable"
|-
! !! class.h
|-
|
||<syntaxhighlight lang="C">
struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
</syntaxhighlight>
|-
! main.c !! class.c
|-
|<syntaxhighlight lang="C">
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
..
//Kein Zugriff auf
//Strukturelemente möglich
return 0;
}
</syntaxhighlight>
||<syntaxhighlight lang="C">
#include "class.h"
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *)
malloc(sizeof(struct class));
this->attr1=10;
*me=this;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
//..
//Kein Zugriff auf Strukturelemente möglich
return 0;
}
|class_h=struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
|class_c=#include "class.h"
#include <stdlib.h> //fuer malloc()
#include <stdio.h> //fuer printf()
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *) malloc(sizeof(struct class));
printf("konstructor called\n");
this->attr1=10;
*me=this;
}
| execCompilerOptions=-Wall class.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Vergleichen von Strukturen ===
Ein Vergleich von Strukturen über den direkten Weg ist nicht möglich. Vielmehr müssen die Strukturelemente händisch verglichen werden:
<syntaxhighlight lang="C">
struct xyz {int inx,y,z;} var1,var2;
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} var1={1,2,3},var2={1,2,3};
int main(int argc,char *argv[]) {
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
printf("Strukturelemente von var1 und var2 identisch\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis
* Bei Rechnerarchitekturen mit nicht ausgerichteter Speicherausrichtung (Alignment) kann ergänzend ein Vergleich über memcmp() erfolgen
=== Speicherplatzbedarf einer Struktur ===
Für jedes Strukturelement wird Speicher entsprechend der Größe des Datentyps reserviert. Der Speicherplatzbedarf der Gesamtstruktur ergibt sich aus der Summe der Strukturelemente:
<syntaxhighlight lang="C">
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
sizeof(var1) //ergibt 12
sizeof(struct xyz) //ergibt 12
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
int main(int argc,char *argv[]) {
printf("sizeof(var1)=%zu Bytes\n",sizeof(var1));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Ermittlung der tatsächlichen Speichergröße einer Struktur erfolgt über den sizeof-Operator:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;} a;
sizeof(a); //=12 OK
sizeof(a.x); //=4 OK
sizeof(struct xyz); //=12 OK
sizeof(struct xyz.x); // KO
//Ist dies dennoch notwendig, so kann dies über den Umweg eines Zeigers
//erfolgen:
sizeof(((struct xyz *)0)->x); //=4 OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x,y,z;
} a;
int main(int argc,char *argv[]) {
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
printf("sizeof(a.x)=%zu Bytes\n",sizeof(a.x));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
printf("sizeof(struct xyz.x)=%zu Bytes\n",sizeof(struct xyz.x));
printf("sizeof(((struct xyz *)0)->x)=%zu Bytes\n",sizeof(((struct xyz *)0)->x));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei Rechnerarchitekturen mit ausgerichteter Speicherausrichtung (Alignment) (siehe {{w|Speicherausrichtung}}) kann der tatsächliche Speicherbedarf größer sein! Hier fügt der Compiler ggf. zwischen den Strukturelemente Füllbytes (Padding Bytes) ein
* Die Reihenfolge der Strukturelemente wird vom Compiler nicht geändert. D.h. die Zuordnung der Speicherstellen zu den Strukturelementen erfolgt in der Definitionsreihenfolge
=== Interne Organisation ===
Compilerintern werden die Strukturelemente über einen Offset dargestellt. Das erste Strukturelement bekommt dabei immer den Offset 0 zugewiesen. Das nachfolgende Element bekommt als Offset die Größe des Datentyps des vorherigen Elementes zugewiesen. Usw.. <br />
Der Compiler setzt den Zugriff auf ein Strukturelement einer (Struktur)Variablen so um, dass er zunächst die Startadresse der Variablen holt und zu dieser den Offset des Strukturelementes addiert. Die Anzahl der zu lesenden/schreiben Bytes ergibt sich aus dem Datentyp des Strukturelementes:
<syntaxhighlight lang="C">
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1; //(Beispielhaft soll var1 die Speicheradressen
//0x100..0x10B belegen). Der Zugriff auf
//die Variable erfolgt immer über die Startadresse
var1.x=7; //Zugriff auf Speicheradresse 0x100+0 (Offset)
var1.y=8; //Zugriff auf Speicheradresse 0x100+4 (Offset)
var1.z=9; //Zugriff auf Speicheradresse 0x100+8 (Offset)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1;
int main(int argc,char *argv[]) {
//Zugriff siehe Compiler
var1.x=7; //mov DWORD PTR var[rip+0],7
var1.y=8; //mov DWORD PTR var[rip+4],7
var1.z=9; //mov DWORD PTR var[rip+8],7
return 0;
} | execCompilerOptions=-Wall|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Offset eines Strukturelementes kann mit dem offsetof-Operator ermittelt werden:
<code>Syntax: offsetof(type,Strukturelement)</code>
Wie beim sizeof-Operator gilt der offsetof-Operator als Konstantenausdruck und der Rückgabedatentyp ist <code>size_t</code>. Zur Nutzung des Operators muss die Header-Datei 'stddef.h' inkludiert werden:
<syntaxhighlight lang="C">
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var1;
offsetof(struct xyz,z) --> 8
offsetof(var1,z) --> KO: Es wird ein Datentyp und
keine Variable erwartet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz{
int x,y,z;
} var1;
int main(int argc,char *argv[]) {
printf("offsetof(struct xyz,x)=%zu Bytes\n",offsetof(struct xyz,x));
printf("offsetof(struct xyz,y)=%zu Bytes\n",offsetof(struct xyz,y));
printf("offsetof(struct xyz,z)=%zu Bytes\n",offsetof(struct xyz,z));
printf("offsetof(var1,z)=%zu Bytes\n",offsetof(var1,z));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Unter Nutzung des offsetof-Operators kann man bei gegebener Adresse eines Strukturelementes auf die Startadresse der zugrundeliegenden Struktur zurückrechnen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1;
int *ptri=&var1.y;
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var={1,2,3};
int *ptri=&var.y;
int main(int argc,char *argv[]) {
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
printf("ptrxyz->x=%d ptrxyz->y=%d ptrxyz->z=%d",ptrxyz->x,ptrxyz->y,ptrxyz->z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dazu wird von der Startadresse des Strukturelementes der Offset abgezogen. Da der offsetof-Operator den Abstand in Bytes zurückgibt, muss der Pointer auf das Strukturelement zuvor ebenfalls in ein 'Byte'-Zeiger gewandelt werden.
Im Linux kernel wird diese Subtraktion über das container_of Makro realisiert:
<syntaxhighlight lang="C">
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
</syntaxhighlight>
Dieses Makro ermöglicht es, bei gegeben Startadresse eines Strukturelementes die Startadresse der zugrundeliegenden Struktur zu berechnen. Anwendung findet dieses Makro bspw. in:
* der objektorientierten Programmierung, um ausgehend vom gegebenen Parent-Element die Startadresse des Child-Elementes zu berechnen:
:<syntaxhighlight lang="C">
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
..
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
printf("parent.attr1=%d parent.att2=%d\n",me->attr1,me->attr2);
printf("child.attr1=%d\n",child->attr1);
}
int main(int argc,char *argv[]) {
struct child obj1;
obj1.attr1=1;
obj1.parent.attr1=2;
obj1.parent.attr2=3;
parent_methode(&obj1.parent);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei verketteten Listen, wenn das Next-Element im Datensatz selbst eingearbeitet ist:
:<syntaxhighlight lang="C">
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(PTR, TYPE, MEMBER) \
((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
vl_t head={NULL};
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
int main(int argc,char *argv[]) {
daten_t obj1={.daten1=1,.daten2=2};
daten_t obj2={.daten1=3,.daten2=4};
vl_addfront(&obj1);
vl_addfront(&obj2);
daten_t *ret=vl_getfront();
printf("%d %d\n",ret->daten1,ret->daten2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Explizites Cast ===
Eine Struktur kann nicht in einen anderen Datentyp und damit auch nicht in einen anderen Strukturdatentyp mit identischen Strukturelementen konvertiert werden:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} xyz;
struct abc {int a,b,c;} abc;
int var;
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} xyz;
struct abc {
int a,b,c;
} abc;
int var;
int main(int argc,char *argv[]) {
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Incomplete Array ===
Das letzte Element einer Struktur kann ein Array ohne Angabe einer Dimensionsgröße sein (Incomplete Array/Flexible Array Member). Bei der Definition einer Variablen von solch einem Datentyp wird in der Tat kein Speicher für das letzte Element reserviert, so dass dies 'händisch' erfolgen muss. Auf das Array kann ungeachtet dessen unproblematisch zugegriffen werden:
<syntaxhighlight lang="C">
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert
//wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert wurde
//Zur Darstellung dieses Sachverhaltes wurde der Sanitizer
//über den Compilerschalter -fsanitize=address aktiviert
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Speicherplatzreservierung für das incomplete Array kann auf zwei verschiedene Arten erfolgen:
* Speicherplatzreservierung für das Incomplete Array über Variableninitialisierung (nur GCC-C und nur im Falle einer globalen Variablen)
:<syntaxhighlight lang="C">
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
int main(int argc,char *argv[]) {
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(ele1)=%zu Bytes\n",sizeof(ele1));
printf("sizeof(ele2)=%zu Bytes\n",sizeof(ele2));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Speicherplatzreservierung für das Incomplete Array über malloc
:<syntaxhighlight lang="C">
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
if(b==NULL)
return printf("malloc failed\n"),1;
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
//zum Beweis Sanitizer über -fsanitize=address eingebunden
free(b);
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Das Incomplete Array bietet sich überall dort an, wo Daten gespeichert werden sollen, deren Größe sich erst zur Laufzeit ergibt.
=== Anwendung ===
Die Nutzung des Datentyps struct empfiehlt sich an vielen Stellen:
* Zusammengehörende Daten zu Kapseln (entsprechend der objektorientierten Programmierung
* Verkette Listen
* Aufgrund der Typsicherheit zur Darstellung von sicherheitskritischen Aufgaben
Siehe Übungsbereich!
=== C++ ===
Der wesentliche Syntax von Strukturen wurde in C++ übernommen. D.h.:
* das abschließende Semikolon
* der Zugriff auf die Strukturelemente
* Speicherplatzreservierung
* die Definition von Variablen mit der Definition des Datentyps
* ...
Ergänzend wurde in C++ der Datentyp class eingeführt, der weitestgehend identisch zu struct ist. Geändert/Hinzugefügt wurden folgende Sachverhalte:
* Classen/Strukturen können Methoden haben
* Operatoren (Zuweisungsoperator, Addition, ...) können überladen werden
* Alle Strukturelemente (und Methoden) einer struct sind per default public
* Alle Attribute (und Methoden) einer Class sind per default private
* Zur Nutzung des Datentyps ist das führende struct nicht notwendig (dies bedingt dann auch, dass der Strukturdatentyp kein separater Namensraum ist)
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var_xyz;
</syntaxhighlight>
* Initialisierungswerte für Strukturelemente und Klassenattribute bei der Datentypbeschreibung angegeben werden können:
:<syntaxhighlight lang="C++">
struct xyz {
int x=3;
int y=1;
int z;
};
xyz var={7}; //var.x=7 var.y=1 var.z=0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x=3;
int y=1;
int z;
};
int main(int argc,char *argv[]) {
xyz var={7}; //var.x=7 var.y=1 var.z=0
printf("var.x=%d var.y=%d var.z=%d\n",var.x,var.y,var.z);
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In C++ kann eine Struktur ebenfalls über 'designated initializers' initialisiert werden. Jedoch muss die Reihenfolge der Initialisierungselement identisch zur Datentypdefinition sein. Auch ist keine Doppeltbenennung erlaubt:
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x,y,z;
};
int main(int argc,char *argv[]) {
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
(void)var1;
(void)var2;
(void)var3;
(void)var4;
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Union ==
Ähnlich wie eine Struktur ist ein Union ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wird. Bei sog. Union beginnen jedoch alle Komponenten nicht wie bei Strukturen an nacheinander folgenden Speicheradressen, sondern an der identischen Speicheradresse, d.h. ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union kann folglich zu einem Zeitpunkt nur ein Element enthalten. Der benötigte Speicherplatz ergibt sich aus der größten Komponente.
<code>Syntax: union Unionname<sub>Opt</sub> {Datentyp Variablenname; …}<sub>Opt</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Schutz/Zugriffssteuerung der Unionelemente ist nicht vorhanden. Es kann in beliebiger Reihenfolge auf die einzelnen Elemente zugegriffen werden.
Die Anwendung ist identisch wie bei Strukturen, so dass im Folgenden nur die Abweichungen zu den Strukturen beschrieben werden.
=== Speicherplatzbedarf und interne Struktur einer Union ===
Die Größe der Union ergibt sich aus dem größtem Unionelement. Alle Unionelemente überlappen sich, so dass der Offset zum Basiselement 0 ist:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird ein kleineres Unionelement belegt und im Anschluss ein größeres Unionelement gelesen, so ist der Inhalt der durch das kleinere Element nicht beschriebenen Speicherstellen undefiniert:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc.a=0x11;
printf("%08x",abc.c);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
};
void foo(int var) {
int lok=var;
printf("Foo(%#08x) called\n",lok);
}
void bar(void) {
union abc abc;
abc.a=0x11;
printf("abc.a=%#02x\n",abc.a);
printf("abc.c=%#08x\n",abc.c);
}
int main(int argc,char *argv[]) {
//Zur Darstellung des Phänomens muss
//erstmal der Stack mit Daten belegt werden!
foo(0x12345678);
bar();
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Union ===
Bei einer Union kann nur ein Element initialisiert werden, d.h. die Initialisierungsliste kann nur einen Wert beinhalten. Ohne explizite Benennung des Unionelementes in der Initialisierungsliste wird das erste Element aus der Datentypbeschreibung initialisiert. Mit expliziter Benennung mittels 'designated initializers' können auch andere Elemente initialisiert werden:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Anwendung ===
Mittels des Datentyps union können diverse Anwendungsfälle abgedeckt werden:
* Über Union lassen sich größere Datentypen in kleinere Datentypen unterteilen, um z.B. einzelne Bytes zu extrahieren:
<syntaxhighlight lang="C">
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union floatu var={1.234};
printf("%f\n",var.var); //Darstellung des Float-Wertes
printf("%x\n",var.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var.byte[0],var.byte[1],var.byte[2],var.byte[3]);
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
union longlong var2={0x123456789ABCDEFULL};
printf("%llx\n",var2.ll);
printf("%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
int main(int argc,char *argv[]) {
union floatu var1={1.234};
printf("var1.var=%f\n",var1.var); //Darstellung des Float-Wertes
printf("var1.hex=%x\n",var1.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("var1.byte[0..3]=%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var1.byte[0],var1.byte[1],var1.byte[2],var1.byte[3]);
union longlong var2={0x123456789ABCDEFULL};
printf("var2.ll=%llx\n",var2.ll);
printf("var2.i[0..1]=%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Ein weiterer Anwendungsfall ergibt sich, wenn in einer Struktur unterschiedliche Datensätze gespeichert werden sollen (siehe {{w|Tagged Union}}):
:<syntaxhighlight lang="C">
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
int main(int argc,char *argv[]) {
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mittels eines Tagged Union kann komfortabel ein Binärbaum realisiert werden:
:<syntaxhighlight lang="C">
//Quelle: https://github.com/Hirrolot/datatype99
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h> //fuer printf()
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Die Eigenschaften des Datentyps union entsprechen den Eigenschaften des Datentyps struct in C++.
== Enum/Aufzählungstyp ==
Nach dem Wikipedia Artikel {{w|Aufzählungstyp}} ist ''ein Aufzählungstyp (englisch enumerated type) ein Datentyp für Variablen mit einer endlichen Wertemenge. Alle zulässigen Werte des Aufzählungstyps werden bei der Deklaration des Datentyps mit einem eindeutigen Namen (Identifikator) definiert, sie sind Symbole.''
<code>Syntax: enum enumname<sub>Opt</sub> {definition-list[=expression]}<sub>Opt</sub> Variablenliste<sub>Opt</sub></code>
Die Anwendung ist identisch wie bei Strukturen, so dass nachfolgend nur die Abweichungen zu den Strukturen beschrieben werden.
=== Datentyp von enum ===
In C entspricht der Datentyp Enum dem Datentyp <code>int</code> so dass Zuweisungen/Vergleiche mit Ganzzahlen möglich sind. Ganzzahloperationen funktionieren ebenso:
<syntaxhighlight lang="C">
enum STATUS {OK,KO=5}; //Definition des Datentyps
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
status++;
status=5.7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum STATUS {OK,KO=5}; //Definition des Datentyps
int main(int argc,char *argv[]) {
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
printf("status == 5\n");
status++;
status=5.7;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Enumelemente ===
Die Elemente der Definitionsliste sind Integerkonstanten. Diese können auch in Kombination mit anderen Datentypen genutzt werden. Auch gibt es keinen gesonderten Namensraum für Elemente der Definitionsliste. Sie 'konkurrieren' folglich mit allen Variablen- und Funktionsnamen:
<syntaxhighlight lang="C">
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
int main(int argc,char *argv[]) {
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der erste Enumelement der Definitionsliste bekommt den Wert 0 zugewiesen. Folgeelemente bekommen den Wert des Vorgängerelementes +1 zugewiesen.
Enumelemente können mit einer Konstanten (und Konstantenausdruck) initialisiert werden:
<syntaxhighlight lang="C">
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
int main(int argc,char *argv[]) {
printf("bill=%d john=%d, fred=%d\n",bill,john,fred);
printf("error=%d warning=%d info=%d ok=%d\n",error,warning,info,ok);
printf("Ostfalia=%d Wolfenbuettel=%d\n",Ostfalia,Wolfenbuettel);
printf("test=%d\n",test);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Es empfiehlt sich, die Enumelemente in GROSSBUCHSTABEN zu schreiben. Hiermit wird gekennzeichnet, dass es sich um Konstanten und nicht um Variablen/Funktionen handelt
=== Anwendung ===
Die Nutzung des Datentyps enum empfiehlt sich überall dort, wo eine Fallunterscheidung notwendig ist:
* Statusrückgabe von Funktionen:
:<syntaxhighlight lang="C">
enum STATUS {OK,MEMORY_OVERFLOW, DIVISION_BY_ZERO};
enum STATUS funct(…) {
return MEMORY_OVERFLOW;
}
</syntaxhighlight>
* Beschreibung der Zustände und der Ereignisse eines Zustandsautomates:
:<syntaxhighlight lang="C">
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Ergänzend zu den Abweichungen bei Structs sind hier weitere Unterscheidungsmerkmale vorhanden:
* Enums stellen einen eigenen Datentyp dar, der nicht mit int kompatible ist. Das bedingt unter anderem, dass einige Operatoren wie z.B. ++ nicht mehr auf Variablen des Datentyps enum angewendet werden. Die Enumelemente als solches sind jedoch kompatibel zum Ganzzahldatentyp:
:<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
int main(int argc,char *argv[]) {
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
printf("RED==2\n");
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
* Auch enums können Methoden besitzen.
* Über Operatorüberladung können z.B. nicht vorhandene Operatoren wie ++/-- ergänzt werden
* Über unscoped/scoped Enumerations wird der 'Namensraum' gesteuert:
:* Unscoped Enumeration (Elemente der Definitionsliste stehen wie bei C im Zugriff)
::<code>Syntax: enum name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE };
Color r = RED;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE };
Color r = RED;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
:* Scoped enumeration (Elemente der Definitionsliste haben einen eigenen 'Namensraum')
::<code>Syntax: enum '''class|struct''' name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
== Bitfelder ==
Nach dem Wikipediaartikel {{w|Bitfeld}} ''bezeichnet in der Informationstechnik und Programmierung ein Bitfeld ein vorzeichenloses Ganzzahldatentyp, in dem einzelne Bits oder Gruppen von Bits aneinandergereiht werden. Es stellt eine Art Verbunddatentyp auf Bit-Ebene dar. Im Gegensatz dazu steht der primitive Datentyp, bei dem der Wert aus allen Stellen gemeinsam gebildet wird.''
Der Syntax entspricht dem struct-Syntax, mit der Ergänzung, dass hinter den Strukturelementen noch die Bitbreite getrennt durch ein Doppelpunkt angegeben wird:
<syntaxhighlight lang="C">
struct time {
unsigned int hour: 5; //0..23 Bits 0..4
unsigned int minute: 6; //0..59 Bits 5..10
Unsigend int second: 6; //0..59 Bits 11..16
} myTime;
</syntaxhighlight>
Als mögliche Datentypen für die Strukturelemente stehen nur die Ganzzahldatentypen <code>int</code>, <code>short</code>, <code>long</code> , <code>long long</code> und <code>char</code> zur Verfügung. Der Datentyp eines Strukturelementes muss mindestens die Anzahl der Bits enthalten, wie diese über die Bitbreite gefordert wird.
Von den Strukturelementen kann keine Adresse bestimmt werden! Auch der <code>offsetf</code> - Operator schlägt fehl.
Der Datentyp entspricht im Wesentlichen einem Ganzzahlzahldatentyp, so dass bei Zugriff auf eine Variable dieses Datentyps eine Ganzzahl gelesen/geschrieben wird. Bei Zugriff auf die einzelnen Strukturelemente werden die entsprechenden Bits dieser Ganzzahlvariablen maskiert, so dass nur die betroffenen Bits geändert werden:
<syntaxhighlight lang="C">
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) | (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) | ((second&0b00001111)<<2);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
//Nachweis am besen über den Maschinensprachevergleich!
int main(int argc,char *argv[]) {
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) {{!}} (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) {{!}} ((second&0b00001111)<<2);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
h=c
}} Öffnen im Compiler Explorer] }}
=== Anwendung===
* Komprimierte Speicherung der Uhrzeit (wie dies z.B. in Realtimeclocks erfolgt)
:<syntaxhighlight lang="C">
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
int main(int argc,char *argv[]) {
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Aufteilung von FloatingPoint Zahlen in seine Komponenten
:<syntaxhighlight lang="C">
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
int main(int argc,char *argv[]) {
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",
(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Bitfelder existieren mit den bekannten Ergänzungen auch in C++.
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
mx0cazvyzqh3ii0c0qdtfoq0eatwgi5
1090850
1090849
2026-09-15T10:59:58Z
D. Justen
102048
Formulierung geändert/ergänzt
1090850
wikitext
text/x-wiki
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
<!-- Falls du ein automatisch erstelltes Inhaltsverzeichnis nicht willst, ersetze das nachfolgende TOC durch NOTOC -->
<!-- Einklammerung mit noinclude, damit dieses nicht in der Druckversion erscheint -->
<noinclude>__TOC__</noinclude>
Die Programmiersprache C kennt nachfolgende grundlegende Datentypen und Zeiger auf diese Datentypen (siehe auch [[Programmieren in C/C++: Grundlagen# Grundlegende Datentypen und Typsicherheit| Grundlagen:Grundlegende Datentypen und Typsicherheit]])
{| class="wikitable"
|-
! Datentyp !! Bsp. für Datentyp !! Bsp. für Zeiger auf Datentyp
|-
| [[#Ganzzahl Datentypen|Ganzzahl]] ||
<syntaxhighlight lang="C">
char var;
int var;
short int var;
long int var;
long long int var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
char *ptr;
int *ptr;
short int *ptr;
long int *ptr;
long long int *ptr;
</syntaxhighlight>
|-
| [[#Gleitkomma Datentypen|Gleitkommazahl]] ||
<syntaxhighlight lang="C">
double var;
float var;
long double var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
double *ptr;
float *ptr;
long double *ptr;
</syntaxhighlight>
|-
| Funktionen ||
<syntaxhighlight lang="C">
void func(void) {}
</syntaxhighlight>
|| <syntaxhighlight lang="C">
void (*pfunc)(void);
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Array|Arrays]] ||
<syntaxhighlight lang="C">
int arr[10];
float arr[3][3];
</syntaxhighlight>
||
<syntaxhighlight lang="C">
int (*parr);
float (*parr)[3];
void (*pfunc[5])(void);
</syntaxhighlight>
|-
| [[#Struktur/Verbundtyp|Strukturen]]/[[#Union|Unions]] ||
<syntaxhighlight lang="C">
struct xyz {int x,y,z};
union abc {int a,b,c};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
struct xyz *ptr;
union abc *ptr;
</syntaxhighlight>
|-
| [[#Enum/Aufzählungstyp|Aufzählungstyp]] ||
<syntaxhighlight lang="C">
enum abc {A,B,C};
</syntaxhighlight>
||
<syntaxhighlight lang="C">
enum abc *ptr;
</syntaxhighlight>
|-
| [[Programmieren in C/C++: Grundlagen #Boolescher-Datentype/Operatoren|Boolescher Datentyp]] ||
<syntaxhighlight lang="C">
_Bool var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Bool *ptr;
</syntaxhighlight>
|-
| [[#Komplexe Zahlen|Komplexe Zahlen]] ||
<syntaxhighlight lang="C">
_Complex var;
</syntaxhighlight>
||
<syntaxhighlight lang="C">
_Complex *ptr;
</syntaxhighlight>
|}
Bis auf die Datentypen Funktionen, Array und die Zeiger sollen die wesentlichen Aspekte dieser Datentypen im nachfolgenden beschrieben werden.
'''Der grundlegende Datentyp ist <code>int</code>!'''
* Es wird mit nichts Kleinerem gerechnet als mit dem Datentyp <code>int</code> (siehe [[#Implizite Typumwandlung | Implizite Typumwandlung]]) :
:<syntaxhighlight lang="C">
char var1=10,var2=20,var3;
var3=var1+var2; //Addition findet auf Basis des Datentyps int statt
</syntaxhighlight>
* Es gibt zwar den Booleschen Datentyp, dieser entspricht jedoch einem Ganzzahldatentyp und <code>true</code> und <code>false</code> entsprechen den Integerwerten 0 und 1
* Der Aufzählungsdatentyp und seine Aufzählungselemente sind vom Datentyp <code>int</code>
* Bis einschl. C90 wurde bei der Definition von Variablen ohne Angabe des Datentyps, bei Definition einer Funktion ohne Angabe des Datentyps der Übergabeparameter, des Rückgabedatentyps der Datentyp implizit auf int gesetzt ('''implizit int''')
:<syntaxhighlight lang="C">
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
static var2=2;
foo(par1,par2){
auto var1;
var1=par1+par2;
return var1;
}int main(int argc,char *argv[]) {
printf("%d",foo(1,var2));
return 0;
} | execCompilerOptions=-Wall -std=c90|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Ganzzahl Datentypen ==
Grundlegend kennt die Programmiersprache C nur zwei Ganzzahldatentypen:
* Datentyp: <code>int</code>
: Vorzeichenbehafteter (signed) Datentyp, dessen Bitbreite von der Rechnerarchitektur und des Compilers abhängig ist
* Datentyp <code>char</code>
: Datentyp mit einer Mindestbreite von 8-Bit u.A. zur Speicherung von Zeichen typischerweise im ASCII Format. Die C-Spezifikation [C11 6.2.5 Types] lässt es dem Compiler frei, ob <code>char</code> als vorzeichenbehafteter oder vorzeichenloser Datentyp implementiert wird.
: Ergänzend kann der Datentyp <code>char</code> auch zur Speicherung von ganzen Zahlen genutzt werden. In diesem Fall empfiehlt sich, diese explizit als <code>signed</code> und <code>unsiged</code> zu definieren. Wenn nur ASCII Zeichen gespeichert werden, so ist diese Angabe nicht nötig!
Optional können Qualifier dem Datentyp vorangestellt werden:
* <code>unsigned</code> / <code>signed</code> zur Angabe, ob der Inhalt als vorzeichenlose Zahl oder als vorzeichenbehaftete Zahl zu interpretieren ist. Ohne Angabe sind Variablen vom Datentyp <code>int</code> vorzeichenbehaftet
* <code>short</code> / <code>long</code> / <code>long long</code> (letzteres seit C99) als vorangestellten Qualifier zu <code>int</code> zur Vergrößerung/Verkleinerung der Bitbreite. Bei Angabe des Qualifiers ist das Schlüsselwort <code>int</code> optional. Die Beschreibung <code>long long int</code> und <code>long long</code> sind gleichbedeutend!
Als Bitbreite für die Datentypen ist im C-Standard nur ein Mindestbreite definiert. Die genaue Bitbreite hängt von der Rechenbreite des Systems und vom Compiler ab (siehe [C11 6.2.5 Types]):
{| class="wikitable"
|-
! Datentype !! Mindest<br />breite !! Typisch bei 32-Bit<br />Architektur !! Typisch bei 64-Bit<br />Architektur !! printf Format<br />Anweisung
|-
| <code>char</code> || 8 || 8 || 8 || <code>%c</code>
|-
| <code>signed char</code><br /><code>unsigned char</code>|| 8 || 8 || 8 || <code>%hhd</code><br /><code>%hhu</code>
|-
| <code>short</code><br /><code>short int</code>|| 16 || 16 || 16 || <code>%hd</code> / <code>%hu</code>
|-
|<code>int</code>|| 16 || 16/32 || 32 || <code>%d</code> / <code>%u</code>
|-
|<code>long</code><br /><code>long int</code>|| 32 || 32 || 32/64 || <code>%ld</code> / <code>%lu</code>
|-
|<code>long long</code><br /><code>long long int</code>|| 64 || 64 || 64 || <code>%lld</code> / <code>%llu</code>
|}
In der Header-Datei <code>limits.h</code> sind die tatsächlichen Grenzwerte der Datentypen gespeichert:
{| class="wikitable"
|-
! Konstante !! Beschreibung !! Typ. bei 64-Bit Architektur
|-
| <code>CHAR_BIT</code> || Anzahl der Bits in einem Char || 8
|-
| <code>SCHAR_MIN</code> || min. Wert, den der Typ bei signed char aufnehmen kann || -128
|-
| <code>SCHAR_MAX</code> || max. Wert, den der Typ bei signed char aufnehmen kann || 127
|-
| <code>UCHAR_MAX</code> || max. Wert, den der Typ bei unsigned char aufnehmen kann || 255
|-
| <code>CHAR_MIN</code> || min. Wert, den der Typ char aufnehmen kann || 0 oder SCHAR_MIN
|-
| <code>CHAR_MAX</code> || max. Wert, den der Typ char aufnehmen kann || SCHAR_MAX oder UCHAR_MAX
|-
| <code>SHRT_MIN</code> || min. Wert, den der Typ short int annehmen kann || -32.768
|-
| <code>SHRT_MAX</code> || max. Wert, den der Typ short int annehmen kann || 32.767
|-
| <code>USHRT_MAX</code> || max. Wert, den der Typ unsigned short int annehmen kann || 65.535
|-
| <code>INT_MIN</code> || min. Wert, den der Typ int annehmen kann || -2.147.483.648
|-
| <code>INT_MAX</code> || max. Wert, den der Typ int annehmen kann || 2.147.483.647
|-
| <code>UINT_MAX</code> || max. Wert, den der Typ unsigned int aufnehmen kann || 4.294.967.296
|-
| <code>LONG_MIN</code> || min. Wert, den der Typ long int annehmen kann || -2.147.483.648 oder<br />-9.223.372.036.854.775.808
|-
| <code>LONG_MAX</code> || max. Wert, den der Typ long int annehmen kann || 2.147.483.647 oder<br />9.223.372.036.854.775.807
|-
| <code>ULONG_MAX</code> || max. Wert, den der Typ unsigned long int annehmen kann || 4.294.967.296 oder<br />18.446.744.073.709.551.616
|-
| <code>LLONG_MIN</code> || min. Wert, den der Typ long long int annehmen kann || -9.223.372.036.854.775.808
|-
| <code>LLONG_MAX</code> || max. Wert, den der Typ long long int annehmen kann || 9.223.372.036.854.775.807
|-
| <code>ULLONG_MAX</code> || max. Wert, den der Typ unsigned long long int annehmen kann || 18.446.744.073.709.551.615
|}
Aufgrund dessen, dass die Breite der Datentypen von der Rechnerarchitektur und vom Compiler abhängig ist, sind in der Header-Datei <code>stdint.h</code> Aliase für Datentypen enthalten, welche in ihrem Alias die tatsächliche Breite und das Vorzeichens beinhalten:
<syntaxhighlight lang="C">
uint8_t --> unsigned 8-Bit
int8_t --> signed 8-Bit
uint16_t --> unsigned 16-Bit
int16_t --> signed 16-Bit
...
</syntaxhighlight>
In C++ sind diese Aliase im <code>std</code> namespace definiert:
<syntaxhighlight lang="C++">
std::intptr_t
std::int8_t std::uint8_t
std::int16_t std::uint16_t
std::int32_t std::uint32_t
Std::int64_t std::uint64_t
</syntaxhighlight>
Zur Erzeugung von portablen/rechnerunabhängigen Programmen empfiehlt sich, diese Datentypen zu nutzen. Die Rechenbreite ist dann unabhängig vom Compiler und Betriebssystem.
== Gleitkomma Datentypen ==
Gleitkommazahlen werden im Computer auf Basis folgender Schreibweise dargestellt (siehe auch: {{w|Gleitkommazahl}}):<br />
<syntaxhighlight lang="C">
Dezimalsystem Dualsystem
12,3456710 = 1234567 * 10^-5 0,110 = 1,1001100110011 * 2^-4
------- -- --------------- --
Mantisse Exponent Mantisse Exponent
</syntaxhighlight>
;Mantisse: Vorzeichenlose ganze Zahl (ggf. mit einer festen Position des Dezimalpunktes=Festkommazahl)
;Exponent: Vorzeichenbehaftete ganze Zahl, welche um einen Bias verschoben ist
;Vorzeichen: Vorzeichen der (vorzeichenlosen) Mantisse
Zur Speicherung im Computer werden das Vorzeichen, die Mantisse und der Exponent getrennt im Binärformat gespeichert, für den Programmierer aber als eine (zusammenhängende) Zahl dargestellt:
[[File:Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse.png|thumb|400px|center|Bitweise Darstellung einer Gleitkommazahl, aufgeteilt in Vorzeichen, Exponent und Mantisse]]
Gleitkommazahlen haben genauso wie ganze Zahlen einen beschränkten Wertebereich:
* Die Anzahl der Bits der Mantisse bestimmen die Anzahl der Nachkommastellen:
:<syntaxhighlight lang="C">
Bei 23-Bit Mantisse ist die max. Zahl 2^-23-1=0,000000119,
welches 6..7 dezimale Stellen entspricht!
</syntaxhighlight>
* Mit dem Exponent kann 'quasi' der kleinste und der größte Wertebereich angegeben werden:
:<syntaxhighlight lang="C">
Bei 8-Bit Exponent mit einem Bias von 127 liegt der Wertebereich des
Exponenten im Bereich von -126 … +127 (Exponent -127 und +127 wird zur
Darstellung weitere Zahlen benötigt).
Die kleinste darstellbare Zahl (unter Vernachlässigung der Nachkommastellen der Mantisse ist:
2^-126=1/2^126≅1,175*10^-38
Die größte darstellbare Zahl ist:
2^127 ≅1,7*10^38
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
float sqrtf(float);
float powf(float,float);
#include <ieee754.h>
#include <complex.h>
union test {
unsigned int i;
float f;
union ieee754_float b;
};
int main(int argc,char *argv[]) {
union test var = {.f=-0.1};
printf("Float=%f Binär=%032b\n",var.f,var.i);
printf("v=0b%b e=0b%08b m=0b(1).%023b\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%10d m=%29d\n",var.b.ieee.negative,var.b.ieee.exponent,var.b.ieee.mantissa);
printf("v=%b e=%d-%d=%d m=1+%d/2^-23=%f\n",var.b.ieee.negative,
var.b.ieee.exponent,IEEE754_FLOAT_BIAS,var.b.ieee.exponent-IEEE754_FLOAT_BIAS,
var.b.ieee.mantissa,1.0+var.b.ieee.mantissa*1.0/(1<<23));
printf("\n--- Beispiele von Genauigkeitsprobleme im Umgang mit Gleitkommazahlen (hier float) ----\n");
printf("powf(sqrtf(%1.8f),2) = %1.8f\n",2.0f,powf(sqrtf(2.0f),2));
printf("%f + %f = %f\n",2000.0,0.0004,(double)(2000.0f+0.0004f));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Grundlegend kennen die Programmiersprachen C/C++ folgende Gleitkommadatentypen:
* Datentyp: <code>float</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindesten 6 Stellen betragen, so dass der Datentyp typischerweise 32-Bit groß ist
* Datentyp: <code>double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, so dass der Datentyp typischweise 64-Bit Große ist
* Datentyp: <code>long double</code>
: Lt. Spezifikation soll die Anzahl der (dezimalen) Nachkommastellen mindestens 10 Stellen betragen, damit könnte dieser Datentyp gleich dem Datentyp <code>double</code> gesetzt werden. In der Tat ist die Datenbreite Rechner- und Compilerabhängig. Einige Compiler setzen diesen Datentyp identisch zu <code>double</code>, bei x86 Prozessoren wird aufgrund der Hardwareunterstützung 80-Bit genutzt (wobei in der Tat der Datentyp aufgrund von alignment dann 16-Byte Speicherplatz beansprucht) und einige Systeme nutzen 128-Bit (wobei hier aufgrund ggf. fehlender Hardwareunterstützung Operationen mit diesem Datentyp per Software emuliert werden) (siehe Wikipedia Artikel {{w|lang=en|Long_double|long double}}).
Die genaue Darstellung (Anzahl der Bits für Mantisse und Exponent, Darstellung von NAN/INF, ….) ist in C nicht spezifiziert und somit compiler- und rechnerabhängig. Zumeist wird mittlerweile die {{w|IEEE 754}} Standardisierung genutzt (Norm wurde von Intel mit der Entwicklung der 8087 FPU entworfen).
Grunddatentypen und der Wertebereich (nach {{w|IEEE 754}})
{| class="wikitable"
|-
! Daten-<br/>type !! Speicher-<br />platz !! Exponent !! Mantisse !! Größte Zahl !! Kleinste Zahl !! Genauigkeit !! printf Format Anweisung
|-
| binary32→<code>float</code> || 4 Byte || 8 bit || 23 bit || ~3,4*10<sup>38</sup> || ~1,2*10<sup>-38</sup> || 7..8 Stellen || ---
|-
| binary64→<code>double</code> || 8 Byte || 11 bit || 52 bit || ~1,8*10<sup>308</sup> || ~2,2*10<sup>-308</sup> || 15..16 Stellen || %f %e %g
|-
| binary64 extended→<code>long double</code> || ≥10 Byte || ≥15 bit || ≥63 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 19..20 Stellen || %Lf %Le %Lg
|-
| binary128→<code>long double</code> || 16 Byte || 15 bit || 112 bit || ~1,2*10<sup>4932</sup> || ~3,4*10<sup>-4932</sup> || 34 Stellen || %Lf %Le %Lg
|}
Die tatsächliche Auflösung der Datentyps kann auf Basis nachfolgender Konstanten, definiert in der Header-Datei <code>float.h</code>, ermittelt werden:
:<syntaxhighlight lang="C">
FLT_DIG --> Anzahl der dezimalen Nachkommastellen für float
DBL_DIG --> Anzahl der dezimalen Nachkommastellen für double
LDBL_DIG --> Anzahl der dezimalen Nachkommastellen für long double
FLT_MIN_10_EXP --> Minimaler Exponent zur Basis 10
DBL_MIN_10_EXP
LDBL_MIN_10_EXP
FLT_MAX_10_EXP --> Maximaler Exponent zur Basis 10
DBL_MAX_10_EXP
LDBL_MAX_10_EXP
LDBL_MANT_DIG --> Anzahl der Bits für die Mantisse
LDBL_MANT_DIG
LDBL_MANT_DIG
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <float.h>
int main(){
printf("FLT_DIG =%u\n",FLT_DIG);
printf("DBL_DIG =%u\n",DBL_DIG);
printf("LDBL_DIG =%u\n",LDBL_DIG);
printf("FLT_MIN_10_EXP =%d\n",FLT_MIN_10_EXP);
printf("DBL_MIN_10_EXP =%d\n",DBL_MIN_10_EXP);
printf("LDBL_MIN_10_EXP=%d\n",LDBL_MIN_10_EXP);
printf("FLT_MAX_10_EXP =%d\n",FLT_MAX_10_EXP);
printf("DBL_MAX_10_EXP =%d\n",DBL_MAX_10_EXP);
printf("LDBL_MAX_10_EXP=%d\n",LDBL_MAX_10_EXP);
printf("FLT_MANT_DIG =%d\n",FLT_MANT_DIG);
printf("DBL_MANT_DIG =%d\n",DBL_MANT_DIG);
printf("LDBL_MANT_DIG =%d\n",LDBL_MANT_DIG);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Aufgrund des nicht standardisierten Formates sollte ein Gleitkommadatentyp nicht im Binärformat für den Datenaustausch (mit Netzwerk, über Dateien, ..) genutzt werden. Andere Rechnersysteme/Programmiersprachen würde aufgrund der anderen Interpretation andere Zahlenwerte aus den übertragenen/gespeicherten Binärdaten auslesen!
<syntaxhighlight lang="C">
float var1;
write(file_hdl,&var1,sizeof var1); //Schreiben des Binärwertes
//in eine Datei
double var2;
send(socket_hdl,&var2,sizeof var2,0);//Senden des Binärwertes
//über ein Netzwerk
</syntaxhighlight>
Die Standard-C-Library bietet einige mathematische Funktionen wie <code>sin() / cos() / tan() / atan2() / sqrt() / pow() / exp()/…</code> an. Die Prototypen dieser Funktion sind in der Header-Datei <code>math.h</code> beschrieben, so dass diese bei Nutzung dieser Funktion zu inkludieren ist. Ergänzend ist die Shared Library libm.so über den Compilerschalter '-lm' einzubinden:
<syntaxhighlight lang="C">
#include <math.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ: Wikibooks macht hier Probleme
double sqrt(double);
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double var1=47.11;
double var2=sqrt(var1);
printf("var1=%f var2=%f\n",var1,var2);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen basieren auf den Datentyp <code>double</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist vom Datentyp <code>double</code>. Die Prototypen sehen wie folgt aus:
<syntaxhighlight lang="C">
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double); //Wertebereich der Rückgabe von -PI/2..+PI/2
double atan2(double,double); //Wertebereich der Rückgabe von -Pi .. +PI
double sqrt(double);
double log(double);
</syntaxhighlight>
Über den Suffix f oder l im Funktionsnamen kann der zugrundeliegende Datentyp auf <code>float</code> (Suffix f) oder <code>long double</code> (Suffix l) geändert werden:
<syntaxhighlight lang="C">
float sinf(float);
long double sinl(long double);
</syntaxhighlight>
Ergänzend zu den Prototypen sind die gebräuchlichen Naturkonstanten in <code>math.h</code> definiert (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
M_E Value of e
M_LOG2E Value of log_2 e
M_LOG10E Value of log_10 e
M_LN2 Value of log_e 2
M_LN10 Value of log_e 10
M_PI Value of π
M_PI_2 Value of π/2
M_PI_4 Value of π/4
M_1_PI Value of 1/π
M_2_PI Value of 2/π
M_2_SQRTPI Value of 2/√π
M_SQRT2 Value of √2
M_SQRT1_2 Value of 1/√2
</syntaxhighlight>
Gleitkommazahlen können nicht nur Zahlenwerte, sondern auch Sonderwerte annehmen. Diese Sonderwerte sind ebenfalls in <code>math.h</code> beschrieben (siehe auch: [https://www.man7.org/linux/man-pages/man0/math.h.0p.html math.h]):
<syntaxhighlight lang="C">
INFINITY A constant expression of type float representing
positive or unsigned infinity, if available; else a
positive constant of type float that overflows at
translation time.
NAN A constant expression of type float representing a
quiet NaN. This macro is only defined if the
implementation supports quiet NaNs for the float type.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <math.h>
//Quelle: https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c
#ifdef NAN
#define NAN_STR "NAN is supported"
#else
#define NAN_STR "NAN is not supported"
#endif
#ifdef INFINITY
#define INFINITY_STR "INFINITY is supported"
#else
#define INFINITY_STR "INFINITY is not supported"
#endif
int main(int argc, char *argv[argc]) {
printf("%s\n%s\n",NAN_STR,INFINITY_STR);
double x=0.0;
double y=1/x;
printf("1/%e -> %e\n",x,y);
if(y==INFINITY)
printf("1) Initinity\n");
if(isinf(y)) //besser
printf("2) Initinity\n");
printf("%llx\n%llx\n\n",*(long long *)&y,INFINITY);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
double z=-(x/x);
printf("%e/%e -> %e\n",x,x,z);
if(z == NAN) //funktioniert nicht
printf("1) Not a Number\n");
if(isnan(z)) //besser
printf("2) Not a Number\n");
if(z != z)
printf("3) Not a Number\n");
printf("%llx\n%llx",*(long long *)&z,NAN);
//Hinweis: Fehlerhafte Typkonvertierung bei printf bewusst getätigt
return 0;
} | execCompilerOptions=-lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Mit <code>fesetround()/fegetround()</code> kann gesetzt/gelesen werden, wie mit Ergebnissen umzugehen sind, die nicht exakt darstellbar sind. Mögliche Werte sind 'round to nearest' (default), 'round up', 'round down' und 'round toward zero'.
== Komplexe Zahlen ==
Nach dem Wikipedia Artikel {{w|komplexe Zahlen}} ''stellen komplexe Zahlen eine Erweiterung der reellen Zahlen dar. Ziel der Erweiterung ist es, algebraische Gleichungen wie x<sup>2</sup>+1=0 bzw. x<sup>2</sup>=-1 lösbar zu machen. ... Da die Quadrate aller reellen Zahlen größer oder gleich 0 sind, kann die Lösung der Gleichung x<sup>2</sup>=-1 keine reelle Zahl sein. Man braucht eine ganz neue Zahl, die man üblicherweise i nennt, mit der Eigenschaft i<sup>2</sup>=-1. Diese Zahl i wird als imaginäre Einheit bezeichnet.
Komplexe Zahlen werden nun als Summe a+b*i definiert, wobei a und b reelle Zahlen sind und i die oben definierte imaginäre Einheit ist.''<br />
Der Datentyp für komplexe Zahlen (erst ab C99 enthalten) beinhaltet folglich zwei Gleitkommazahlen, eine für den reelen Teil und eine für den imaginären Teil. Entsprechend den Gleitkommazahlen steht der komplexe Datentyp ebenfalls in drei unterschiedlichen Genauigkeiten zur Verfügung:
{| class="wikitable"
|-
! Datentype !! Speicherplatz
|-
| <code>float _Complex</code> || 2x4Byte
|-
| <code>double _Complex</code><br /><code>_Complex</code> || 2x8Byte
|-
| <code>long double _Complex</code> || 2x10Byte
|}
Wie auch beim Booleschen Datentyp ist in der Header-Datei <code>complex.h</code> für den einfacheren Umgang mit diesem Datentyp das Makro <code>complex</code> als Textersetzung für <code>_Complex</code> gesetzt.
Zur Darstellung von komplexen Konstanten wurde die Gleitkommakonstante um den Suffix i ergänzt. Durch Anhängen von i wird aus dem ansonsten rellen Teil der imaginäre Teil und damit aus der Gleitkommakonstante eine komplexe Gleitkommakonstante:
<syntaxhighlight lang="C">
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
_Complex varc1=2i;
_Complex varc2=1+2i;
printf("%f %f\n",creal(varc1),cimag(varc1));
printf("%f %f\n",creal(varc2),cimag(varc2));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Normale Gleitkommavariablen werden als reellen Teil einer komplexen Zahl angesehen. Bei Operationen von Gleitkommazahlen und komplexen Zahlen wird der imaginäre Teil der Gleitkommazahl auf 0 gesetzt. Beim Zuweisen einer komplexen Zahl an eine Gleitkommazahl wird nur der reele Teil 'gelesen'.<br />
Soll eine Gleitkommavariablen zu einem imaginären Teil gewandelt werden, so muss diese bspw mit der Konstanten 1.0i multipliziert werden:
<syntaxhighlight lang="C">
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double vard1=2i; //Vorsicht, es wird nur der reele Teil
printf("%f\n",vard1); //der komplexen Zahl in vard1 gespeichert!
_Complex varc1=1+2i;
vard1=1;
varc1=varc1+vard1;
printf("%f %f\n",creal(varc1),cimag(varc1));
varc1=varc1+vard1*1.0i;
printf("%f %f\n",creal(varc1),cimag(varc1));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Standard-C-Library bietet diverse mathematische Funktionen wie csin(), ccos(), csqrt(), cpow() und ergänzend Umrechnungsfunktionen von Gleitkommazahlen in komplexe Zahlen (und umgedreht) wie creal(),cimag() ,cabs() für den Umgang mit komplexen Zahlen an:
<syntaxhighlight lang="C">
double _Complex csin(double _Complex);
double _Complex csqrt(double _Complex);
double creal(double _Complex);
double cimag(double _Complex);
</syntaxhighlight>
Zur Nutzung dieser Funktionen muss die Header-Datei <code>complex.h</code> inkludiert und ergänzend die Shared Library libm.so über den Compilerschalter '-lm' eingebunden werden.
<syntaxhighlight lang="C">
#include <complex.h>
//Math-Library mittels Linker-Command '-lm' einbinden
int main(int argc, char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <complex.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
int main(int argc,char *argv[]) {
double _Complex xyz=6+2i; //Reeler-Teil=6 Imaginärer Teil=2
printf("Reeller Teil: %f Imaginärer Teil:%f",creal(xyz),cimag(xyz));
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Funktionen beruhen auf den Datentyp <code>double _Complex</code>, d.h. sowohl der Übergabewert als auch der Rückgabewert ist <code>double _Complex</code> resp. <code>double</code> (bei den Umrechnungsfunktionen). Über den Suffix f und l im Funktionsnamen kann der zugrundeliegende Datentyp geändert werden:
<syntaxhighlight lang="C">
float crealf(float _Complex z);
long double creall(long double _Complex z);
</syntaxhighlight>
Hinweis:
* Der Datentyp <code>_Complex</code> und die dazugehörigen mathematischen Funktionen sind in der C-Spezifikation als optional gekennzeichnet.
== Generische mathematische Funktionen ==
In der <code>tgmath.h</code> Header Datei sind für die mathematischen Funktionen Makros enthalten, welche den Datentyp der Übergabeparameter bestimmen und basierend auf den Datentyp die dazugehörige mathematische Funktion aufrufen.
<code>tgmath.h</code> selbst inkludiert <code>math.h</code> und <code>complex.h</code>, so dass diese nicht weiter zu inkludieren sind.
Steht für den Übergabedatentyp keine passende Funktion zur Verfügung, so ist das Verhalten des Makros undefiniert (bspw. wenn ein komplexes Argument an eine Funktion übergeben wird, die nur für Gleitkommazahlen ausgelegt ist <code>ceil(1+2i);</code> )
Folgendes Regelwerk wird angewendet:
* Ist einer der Übergabeparameter imaginär, so ist die ausgewählte Funktion in der Spezifikation der Funktion beschrieben
* Ist einer der Übergabeparameter Komplexe, so wird die komplexe Variante der Funktion aufgerufen, andernfalls die Gleitkomma Variante
* Ist einer der Übergabeparameter vom Datentyp <code>long double</code>, so wird die <code>long double</code> Variante, bei Ganzzahlen und <code>double</code> die <code>double</code> Variante und andernfalls die <code>float</code> Variante aufgerufen
Beispiel:
<syntaxhighlight lang="C">
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <tgmath.h>
//Math-Library libm.so mittels Linker-Command '-lm' einbinden
long double foo(long double complex parlc,
long double parld,
float parf,
int pari) {
long double ret;
ret =(long double) sqrt(parlc); //Aufruf von csqrtl()
ret+= sqrt(parld); //Aufruf von sqrtl()
ret+=(long double) sqrt(parf); //Aufruf von sqrtf()
ret+= sqrt(pari); //Aufruf von sqrt()
return ret;
}
int main(int argc,char *argv[]) {
foo(1l+1li,2.0l,3.0f,4);
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=c
}} Öffnen im Compiler Explorer] }}
== Boolschescher Datentyp ==
Siehe [[Programmieren in C/C++: Grundlagen#Boolescher-Datentype/Operatoren|Grundlagen: Boolescher-Datentype/Operatoren]]
== void / unvollständiger Datentype ==
Der Datentyp <code>void</code> dient vorrangig dazu, nicht vorhandene Über- und Rückgabewerte von Funktionen anzuzeigen. Ein Rechnen mit <code>void</code>-Argumenten ist nicht möglich, so dass void-Funktionen nicht in Ausdrücken genutzt werden können. Per explizit Cast kann jeder Datentyp nach <code>void</code> konvertiert werden (um beispielsweise zu sagen, dass der Wert/das Ergebnis des Ausdruckes nicht weiter genutzt werden soll). Eine umgedrehte Konvertierung von <code>void</code> in einen beliebigen anderen Datentyp ist jedoch nicht möglich.
<syntaxhighlight lang="C">
void func(void); //void zur Darstellung der nicht vorhandenen Parameter und
//des nicht vorhandenen Rückgabewertes
int a=1,b=2;
a=func()*b; //void kann nicht in Ausdrücken verwendet werden
(void)((1+2i)*3); //Eine Konvertierung nach void ist möglich
(int)(void)3; //Eine Konvertierung von void ist nicht möglich
(void)a; //Zur Anzeige, dass Variable 'bewusst' nicht genutzt wird
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
void func(void) //void zur Darstellung der nicht vorhandenen Parameter und
{ //des nicht vorhandenen Rückgabewertes
}
int main(int argc,char *argv[]) {
int a=1,b=2;
a=func()*b; //void kann nicht in Ausdrücken verwendet werden
(void)((1+2i)*3); //Eine Konvertierung nach void ist möglich
(int)(void)3; //Eine Konvertierung von void ist nicht möglich
(void)a; //Zur Anzeige, dass Variable 'bewusst' nicht genutzt wird
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Variable vom Datentyp <code>void</code> kann nicht angelegt werden. Ein Zeiger vom Datentyp <code>void</code> ist möglich, kann aber nicht dereferenziert werden (siehe Kap. [[Programmieren in C/C++: Zeiger #Void-Zeiger| Zeiger:Void-Zeiger]])
<syntaxhighlight lang="C">
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger ist möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void var; //Eine Variable vom Datentyp void kann nicht angelegt werden
void *ptr; //Void-Zeiger ist möglich
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* <code>sizeof(void)</code> ist nach der C-Spezifikation nicht erlaubt. Dennoch geben viele Compiler hier den Wert 1 zurück!
* Mit einem expliziten Cast auf den Datentyp void wird dem Compiler mitgeteilt, dass diese Variable in Gebrauch ist, der Wert in dieser Operation aber nicht genutzt wird. Hierüber kann die Compilerwarning 'unused Variable' unterbunden werden:
:<syntaxhighlight lang="C">
void func(int par1, int par2) {
int var1=12;
int var2=13;
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
void func(int par1, int par2) {
int var1=12;
int var2=13;
int var3=14; //Nicht genutzte Variable
(void)par2; //Angabe, dass diese Variable genutzt wird.
(void)var2; //Angabe, dass diese Variable genutzt wird.
if(var1==par1) //var1 und par1 werden verwendet
printf("Genutzt\n");
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Datentypkonvertierung ==
Für das Rechnen/Vergleichen müssen beide Operatoren vom identischen Datentyp sein! Sind diese nicht identisch, so müssen die Datentypen 'angeglichen' werden. Dies kann einerseits ‚automatisch‘ mittels 'implizierter' Typumwandlung oder ‚manuell‘ mittels ‚expliziter' Typumwandlung erfolgen.<br />
Beim Zuweisungsoperator (inkl. Parameterzuweisung bei Funktionsaufrufen und Funktionsrückgabewerte mittels return) gilt dies ebenso, nur dass hier der Quelldatentyp an den Zieldatentyp angepasst werden muss. Die impliziten Regeln finden hier keine Anwendung.
Hinweis:
* Empfehlenswert ist, die Datentypen der Variablen so zu wählen, dass der Compiler keine implizite Typumwandlung tätigt. Kann dies nicht vermieden werden, so sollte die explizite Typumwandlung genutzt werden (um sich einen möglichen Datenverlust bewusst zu machen)
* Der Datentyp selbst sollte den möglichen Wertebereich der Variablen entsprechen und nicht unnötig groß gewählt werden
:<syntaxhighlight lang="C">
Datentyp zur Speicherung der Stundenzeit:
Wertebereich: 0 ... 23 -> unsigned char
Datentyp zur Speicherung einer Jahreszahl:
Wertebereich: 2000 v.C. ... 4000 n.C -> signed short
Datentyp zur Speicherung einer Temperatur:
Wertebreich: -273,0°C ... 2000,0°C -> float
</syntaxhighlight>
=== Implizite Typumwandlung ===
Diese Regeln wurden so aufgestellt, dass dabei stets ein Datentyp in einen anderen Datentyp mit höherem Wertigkeit umgewandelt wird [C11 6.3.1.8] und [Harbison: S 199]. Bei Ganzzahlen gilt ergänzend folgende (Rangordnung [C11 6.3.1.1]: long long, long, int, short,char,_Bool):
{| class="wikitable"
|-
! Regel/<br />Priorität !! If either operand<br />has Type !! And the other operand<br />has Type !! Converts both to
|-
| 1 (hoch) || long double || any real type || long double
|-
| 2 || double || any real type || double
|-
| 3 || float || any real type || float
|-
| 4 || any unsigned type || any unsigned type || the unsigned type<br/>with the greater rank
|-
| 5 || any signed type || any signed type || the signed type<br/>with the greater rank
|-
| 6 || any unsigned type || a signed type with a equal<br/> or less rank || the unsigned type
|-
| 7 || any unsigned type || a signed type that can represent<br/>all of values of the unsigned type || the signed type
|-
| 8 (niedrig) || any other type || any other type || both operands are<br/> converted to the unsigned <br/>integer type corresponding<br/> to the type of the operand<br/> with the signed<br/> integer type
|}
Ergänzend gilt das Regelwerk zu Integer Promotion, welche Datentypen kleiner als <code>signed int</code> zu <code>int</code> und kleiner als <code>unsigned int</code> zu <code>unsigned int</code> konvertiert (Compiler kann hiervon abweichen, wenn sichergestellt ist, dass kein Datenverlust eintritt).
Regel 6 und 7 sind der nicht klar definierten Bitbreite der ganzzahligen Datentypen geschuldet und versuchen, Konvertierungsverluste zu vermeiden. Sie lesen sich zunächst kryptisch, lassen sich aber einfach am folgenden Beispiel erklären:
<syntaxhighlight lang="C">
Operand 1: unsigned int (hier 32-Bit)
Operand 2: long (hier 32-Bit / 64-Bit)
</syntaxhighlight>
* Im Fall, dass der Datentyp <code>long</code> 64-Bit breit ist, kann dieser problemlos die vorzeichenlose 32-Bit Zahl ohne Konvertierungsverluste repräsentieren, so dass der Zieltype <code>signed long</code> ist (Regel 7)
* Im Fall, dass der Datentyp <code>long</code> 32-Bit breit ist, kann dieser mit seinen Wertebereich von -2.147.483.648 bis +2.147.483.647 nicht den vorzeichenlosen Zahlenbereich von 0…4.294.967.295 darstellen. In diesem Fall hat der unsigned Datentyp einen höheren Rang, so dass als Zieltyp <code>unsigend long</code> gewählt wird (Regel 6)
'''Regel 6 bedeutet die Gefahr eines Konvertierungsverlustes, dessen man sich bewusst sein sollte!''' Diese tritt insb. dann in Kraft, wenn ein Operand vom Typ <code>unsigned long long</code> ist (64-Bit).
Beispiele von impliziten Typumwandlungen:
<syntaxhighlight lang="C">
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
vari=5.0*(int)sin(vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
//#include math.h //DJ Wikibooks Formatierung schlägt hier fehlt
double sin(double);
int main(int argc,char *argv[]) {
char varc=100;
short vars=100;
int vari=100;
vars=varc + vars;
printf("vars=%hd\n",vars);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vars=(short)((int)varc+(int)vars);
printf("vars=%hd\n",vars);
vari=5.0*(int)sin(vars);
printf("vari=%d\n",vari);
//Wird aufgrund der impliziten Regel wie folgt umgesetzt
vari=(int)(5.0*(double)(int)sin((double)vars));
printf("vari=%d\n",vari);
//Hinweis: da sin() nur Werte im Bereich -1…0…+1 zurückgibt kommen
//als Werte für a hier nur 5, 0 und -5 in Frage!
return 0;
} | execCompilerOptions=-Wall -lm|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Im CompilerExplorer können sie sich die impliziten Typumwandlungen anzeigen lassen. Dazu gehen sie bitte wie folgt vor:
:* Im Source-Fenster mit '+Add new' ein Compiler Fenster öffnen
:* Im Compiler-Fenster mit '+Add new' ein 'GCC Tree/RTL' Fenster öffnen
:* Im GCC Tree/RTL-Fenster unter 'Select a pass…' 'original tree' auswählen
Um implizite Typumwandlung besser erkennen zu können, wird oftmals bei Variablennamen die ''' 'Ungarische Notation' ''' angewendet (siehe {{w|Ungarische Notation}}). Aufgrund der besonderen Namensgebung kann der Programmierer ohne großen Aufwand frühzeitig mögliche Typkonflikte erkennen. Der Variablenname setzt sich wie folgt zusammen:
<syntaxhighlight lang="C">
{Präfix}{Datentyp}{Bezeichner}
</syntaxhighlight>
:'''Präfix''': p->Pointer h->Handle i->index c->count f->flag rg->Array
:'''Datentyp''': ch->Character st->string w->word b->byte…
:'''Bezeichner''': Zum Binden der Variable an eine konkrete Aufgabe (keine Unterstriche).
:Bezeichner ist optional, wenn aus Präfix und Datentyp die 'Aufgabe' der Variable direkt sichtbar ist
Beispiele:
<syntaxhighlight lang="C">
char rgchtemp[10]; //Array (Range) vom Datentyp character
int ich; //Index zum Adressieren eines Arrays vom Datentyp
//character
</syntaxhighlight>
=== Explizite Typumwandlung ===
Programmierer erzwingt durch explizite Typumwandlung (auch CASTen genannt) eine Umwandlung eines Datentyps in einen anderen. Dazu wird der Zieldatentyp in runden Klammern vor Quelldatentype geschrieben:
<syntaxhighlight lang="C">
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
short a=4;
double b=(double)(a+1); //Das Ergebnis von (a+1) wird nach double gecastet
//(Addition erfolgt auf Basis des Datentyps.
//integer)
double c=(double)a+1; //a wird nach double gecastet, so dass nachfolgende
//Addition auf Basis von double basiert.
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
In der Rangfolge der Operatoren steht der Cast-Operator unterhalb von bspw. Funktionsaufrufen, Arrayzugriffen aber auch der Dereferenzierung:
{| class="wikitable"
|-
! Priorität !! Symbol !! Assoziativität !! Bedeutung
|-
| 15 || ... || ... || ...
|-
| 14
||
++/-- (Präfix)<br />
+/- (Vorzeichen) <br />
<nowiki>!</nowiki>/~ <br />
&<br />
<nowiki>*</nowiki><br />
(TYP)<br />
...
|| R-L
||
Präfix-Inkrement/Dekrement<br />
Vorzeichen<br />
Logisches/Bitweises Nicht<br />
Adresse<br />
Zeigerdereferenzierung<br />
'''Typumwandlung (Explizites Cast)'''<br />
...
|-
| 13
||
* / %
|| L-R
|| Multiplikation/Division/Modulo
|-
| 12 || ... || ... || ...
|}
Im Zweifel gilt auch hier, den zu wandelnden Typ ergänzend zu klammern.
Hinweis:
* Bedenke, dass die explizite Typumwandlung so aufgestellt sein sollte, dass der Zieldatentyp dem notwendigen Datentyp entspricht. Andernfalls wendet der Compiler ergänzend eine implizierte Typumwandlung an:
:<syntaxhighlight lang="C">
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
int a;
double b=4.7;
short c1= (long)( (float)a+b );
//b ist vom Typ double, so dass a nach dem Cast auf float
// implizit vom Compiler auf double gecastet wird
//c ist vom Typ short, so dass das Ergebnis der Addtion nach dem expliziten
//Cast auf long auf short gecastet wird.
//Nach Anwendung der impliziten Cast sieht der Ausdruck wie folgt aus:
short c2=(short)(long)( (double)(float)a+4.7);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
h=g
}} Öffnen im Compiler Explorer] }}
Mittels expliziter Typumwandlung können Ganzzahl nach Gleitkommazahlen (und andersherum) und Zeiger in einen anderen Zeiger und auf andere Datentypen gewandelt werden. Eine Konvertierung von Arrays, Strukturen, Unions zu anderen Datentypen als sich selbst ist weiterhin nicht möglich:
<syntaxhighlight lang="C">
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
char *string; //Pointer
int arr[3]; //Array
struct stru {int x,y;} var1; //Strukturen
union unio {int x,y;} var2; //Union
var1 = (struct stru) var2; //Error Conversion to non-scalar type
string=(char *)arr; //OK
arr=(int *)var1; //Error Assignment to expression with array type
string=(char *)var2; //Error cannot convert to pointer type
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Bei den möglichen Konvertierungen sollte Folgendes berücksichtigt werden:
* '''Vorzeichenlose Ganzzahl''' → '''Vorzeichenlose Ganzzahl''': Wenn der Zieldatentyp größer ist, wird die Zahl durch führende '0' erweitert. Wenn der Zieldatentyp kleiner ist, werde die zu vielen Bitstellen abgeschnitten/verworfen (ggf. Datenverlust)
* '''Vorzeichenbehaftete Ganzzahl''' → '''Vorzeichenbehaftete Ganzzahl''': Wenn der Zieldatentyp größer ist, wird vorzeichenrichtig erweitertet (d.h. das Auffüllen erfolgt auf Basis des Vorzeichens). Wenn der Zieldatentyp kleiner ist, werden auch hier die zu vielen Bits abgeschnitten/verworfen (Vorsicht: Negative Zahlen können dabei in positive Zahlen gewandelt werden)
* '''Gleitkommazahl''' → '''Gleitkommazahl''': Hier wird vereinfacht ausgedrückt sowohl die Mantisse als auch der Exponent einzeln kopiert. Wenn die Zielmantisse kleiner ist, gehen 'Nachkommastellen' verloren. Wenn der Quellexponent einen größeren Wert beinhaltet, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf Unendlich gesetzt. Umgedreht, wenn der Quellexponent kleiner ist, als der Zielexponent 'aufnehmen' kann, so wird die Zahl auf 0 gesetzt
* '''Ganzzahl''' → '''Gleitkommazahl''': Hier wird, vereinfacht ausgedrückt, die Ganzzahl in die Mantisse kopiert. Um Datenverluste zu vermeiden, sollte die Bitbreite der Zielmantisse größer gleich der Bitbreite der Ganzzahl sein
* '''Gleitkommazahl''' → '''Ganzzahl''': Im Wesentlichen wird hier die Mantisse übernommen, so dass hier die Bitbreite des Zieldatentyps mindestens der Bitbreite der Mantisse sein sollte
* '''Zeiger''' ↔ '''Ganzzahl''': Die Konvertierung ist möglich. Da bei 64-Bit Systemen der Zeiger 64-Bit und Integer 32-Bit breit ist, meckert ggf. der Compiler. Für solche Fälle existieren die Datentypen 'intptr_t' und 'uintptr_t', über welche sichergestellt ist, dass ein Zeiger in einen Ganzzahldatentyp gespeichert werden kann!
* '''Zeiger''' ↔ '''Gleitkommazahl''': Diese Konvertierung ist nicht möglich!
* '''Struktur/Union''' ↔ '''Ganzzahl/Gleitkommazahl''': Diese Konvertierung ist nicht möglich. Es können nur einzelnen Strukturelemente konvertiert werden, sofern diese vom Typ Ganzzahl/Gleitkommazahl sind
* '''Array''' ↔ '''Ganzzahl/Gleitkommazahl''': Der Arrayname entspricht einen Zeiger, so dass hier ein Zeiger in eine Ganzzahl oder umgedreht konvertiert wird (siehe Zeiger ↔ Ganzzahl)
In C++ gibt es weitere CAST-Operatoren, auf welche hier derzeit noch nicht weiter eingegangen wird!
* Static_cast (Entspricht dem Expliziten Cast)
* Const_cast
* Dynamic_cast
* Reinterpret_cast
== Verbundtyp Struktur/Klasse (nur C++) ==
Nach dem Wikipedia Artikel {{w|Verbund (Datentyp)}} ist ''ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten können wiederum Verbünde enthalten, wodurch auch komplexe Datenstrukturen definiert werden können.<br />
Für jedes Strukturelement wird Speicher reserviert. Alle Strukturelemente liegen hintereinander im Speicher.''
<code>Syntax: struct Strukturname<sub>Opt</sub> {Datentype Strukturelementname; … }<sub>OPT</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Verbund entspricht einer Java Klasse mit dem Unterschied zu C (nicht C++) , dass ein Verbund keine Methoden beinhaltet und keine Zugriffsbeschränkung für die Attribute gesetzt werden können.
Der Syntax erlaubt es, gleichermaßen einen Datentyp (über Strukturname) zu definieren und Variablen von diesem Datentyp (über Variablenliste) anzulegen. Da beide Elemente optional sind, ergeben sich diverse Kombinationsmöglichkeiten:
* Nur Strukturname → Definition eines neuen Datentyps
:<syntaxhighlight lang="C">
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz1 {int x; int y,z;}; //Definition eines neuen Datentyps
struct xyz1 var1; //Definition einer Variablen dieses
//Datentyps
var1.x=7; //Zugriff auf ein Strukturelement
var1.y=2;
var1.z=1;
printf("var1.x=%d var1.y=%d var1.z=%d\n",var1.x,var1.y,var1.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C: Der Strukturname ist nur mit dem vorangestellten <code>struct</code> gültig. Der Strukturname stellt somit einen eigenen Namensraum, getrennt von dem Namensraum der Variablen/Funktionen, dar. Daher kann ein Strukturname identisch zu einem Variablennamen sein:
:<syntaxhighlight lang="C">
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz2 {int x,y,z;}; //Definition des Datentyps 'struct xyz2'
struct xyz2 xyz2; //Definition der Variablen 'xyz2' auf
//Basis des Datentyps 'struct xyz2'
xyz2 var2; //Compilerfehler, zur Nutzung des Datentyps
//'struct xyz2' muss struct vorangestellt
//werden!
xyz2.x=xyz2.y=xyz2.z=1;
printf("xyz2.x=%d xyz2.y=%d xyz2.z=%d\n",xyz2.x,xyz2.y,xyz2.z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:C++: Der Strukturname ist sowohl mit als auch ohne dem vorangestellten <code>struct</code> gültig. Auch hier stellt der Strukturname einen eigenen Namensraum dar, der jedoch eine niedrigere Priorität als der der Variablen hat:
:<syntaxhighlight lang="C++">
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz beschreibt hier die Variable
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz3 {int x,y,z;};
xyz3 xyz3={1,1,1}; //'xyz3' beschreibt hier den Datentypen
xyz3.x=1; //und nach Definition einer Variable die Variable!
xyz3 var2; //Fehler, xyz3 beschreibt hier die Variable
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
* Nur Variablenliste → Definition einer/mehrerer Variablen von einem 'unnamed' Datentyp
:<syntaxhighlight lang="C">
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct {
int x,y,z;
} xyz,arr[3],*ptr=&xyz; //Definition von Variablen des Datentyps
//struct {...}. Da dieser Datentyp nicht benannt
//wurde, kann im späteren keine weitere Variable
//von diesem Datentyp angelegt werden.
xyz.x =8; //Nutzung der Variablen
arr[1].y =9;
ptr->x = arr[1].y;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
:Angewendet wird die Schreibweise gerne, wenn eine Struktur innerhalb einer Struktur definiert wird und die innere Struktur zur besseren Strukturierung dient:
:<syntaxhighlight lang="C">
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct aussen { //Äußere Struktur
struct { //Innere Struktur
int a,b,c;
} anwendung1;
struct { //Innere Struktur
int x,y,z;
} anwendung2;
};
struct aussen var;
var.anwendung1.a=10; //Nutzung der Variablen
var.anwendung2.y=12;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Strukturname und Variablenliste → Definition eines Datentyps und Definition von Variablen. D.h. es können im Nachhinein weitere Variablen von diesem Datentyp angelegt und die hier angelegten Variablen genutzt werden.
:<syntaxhighlight lang="C">
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y; //Nutzung der Variablen
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct xyz{ //Definition eines Datentyps
int x,y,z;
} var1,*ptr1; //und Definition von Variablen dieses Datentyps
struct xyz var2,*ptr2; //Definition weiterer Variablen dieses Datentyps
var1.x=var2.y=1; //Nutzung der Variablen
(void)var1;
(void)ptr1;
(void)ptr2;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Kein Strukturname und keine Variablenliste → "Anonymous Struct", d.h. Definition eines 'unnamed' Datentyps, von der ergänzend keine Variable angelegt wird. Anonymus Structs sind nur innerhalb von Strukturen erlaubt/einsetzbar. Hier dienen sie der besseren Strukturierung und ersparen dem Programmierer die Benennung des normalerweise notwendigen Strukturelementes:
:<syntaxhighlight lang="C">
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct außen {
int a;
struct {
int b,c,d;
} anwendung1; //'Normale' innere Struktur
struct {
int x,y,z;
}; //Anonyme Struct als innere Struktur
} var;
var.a=4711; //Nutzung der Variablen
var.anwendung1.b=1;//Bei Zugriff auf anonyme Struktur ist die Benennung
//des Strukturelementes notwendig
var.x=1; //'Einfacherer' Zugriff auf inneres Element bei
//'anonymous struct'
(void)var;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweise:
* Eine Struktur (und auch eine C++ Klasse) wird mit einem Semikolon abgeschlossen
* Eine alternative Beschreibung zu Strukturen finden sie in [https://abstractexpr.com/2023/06/29/structures-in-c-from-basics-to-memory-alignment/ Structures in C: From Basics to Memory Alignment]
=== Strukturelement ===
Innerhalb der Struktur können beliebige Strukturelemente von beliebigen Datentypen angelegt werden. Einzige Voraussetzung, der Datentyp des anzulegenden Strukturelementes muss zuvor definiert worden sein. Ergänzend kann der neue Datentyp auch in der Struktur selbst definiert werden, sofern mit der Definition des Datentyps auch eine Variable angelegt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b,c;
}; //Definition des Datentyps struct abc
struct xyz { //Definition des Datentyps struct xyz
int x,y,z; //Strukturelement vom Type int
struct abc abc; //Strukturelement vom Type struct abc
struct def { //Definition eines neuen Datentyps innerhalb
int d,e,f; //der Struktur bei gleichzeitigen Anlegen zweier
} def,geh; //Strukturelementen von diesem neuen Datentyp
struct uvw {
int u,v,w; //Warning, reine Datentypdefinition innerhalb
}; //einer Struktur nicht möglich
};
struct def abc; //Innere Datentypbeschreibung auch
//außerhalb der Struktur nutzbar
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zugriff auf Strukturelemente ===
Die Programmiersprachen C/C++ unterscheiden zwei 'Zugriffsarten' auf die Strukturelemente, abhängig vom zugrundeliegenden Datentyp des linken Operanden::
* Handelt es sich beim linken Operanden um eine (struct)Variablen, so erfolgt der Zugriff über den Punkt-Operator <code>.</code>:
:<syntaxhighlight lang="C">
struct {
int a,b,c;
} abc;
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct {
int a,b,c;
} abc;
int main(int argc,char *argv[]) {
abc.a=4711; //abc ist eine Variable einer Struktur
abc.b=abc.c=12;
printf("abc.a=%d abc.b=%d abc.c=%d\n",abc.a,abc.b,abc.c);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Handelt es sich beim linken Operanden um einen Zeiger auf eine (struct)Variable, so erfolgt der Zugriff über den Zeiger-Operator <code>-></code>:
:<syntaxhighlight lang="C">
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
};
struct xyz var1; //Variable von Datentyp struct xyz;
struct xyz *ptr1; //Zeiger auf eine Struktur vom Datentyp struct xyz
int main(int argc,char *argv[]) {
ptr1=&var1; //Initialisierung des Zeigers
//(mit der Adresse der Variablen var1)
var1.x= 7; //Zugriff auf das Strukturelement x über die Variable var1
ptr1->x=7; //Zugriff auf das Strukturelement x über den Zeiger ptr1
(*ptr1).x=7; //Der Zeiger-Operator entspricht dem Zugriff auf ein
//dereferenziertes Strukturelement
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Werden innerhalb von Strukturen weitere Strukturen und Zeiger auf Strukturen angelegt, so müssen diese Regeln auf jedes innere Strukturelement einzeln angewendet werden:
<syntaxhighlight lang="C">
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc { //Äußere Struktur
int a,b,c;
struct xyz {
int x,y,z;
} xyz; //Inneres Strukturelement xyz vom Datentyp struct xyz
struct {
char str[10];
} strstr; //Inneres Strukturelement strstr vom Datentyp
//struct strstr
struct xyz *ptr; //Inneres Strukturelement ptr vom Datentyp Zeiger
//auf struct xyz
} var2,*ptr;
int main(int argc,char *argv[]) {
var2.a=8; //var2 vom Datentyp 'struct abc'. Zugriff über '.'
var2.xyz.x=1; //xyz vom Datentyp 'struct xyz'. Zugriff über '.'
var2.strstr.str[0]='a';//strstr vom anonymes Struct. Zugriff über '.'
ptr=&var2; //ptr mit einer Adresse initialisieren
var2.ptr = &var2.xyz; //Strukturelement ptr mit einer Adresse initialisieren
ptr->a='a'; //ptr vom Datentyp 'Zeiger auf struct abc'
//Zugriff über '->'
var2.ptr->x=3; //ptr vom Datentyp 'Zeiger auf struct xyz'.
//Zugriff über '->'
ptr->xyz.x=3;
ptr->ptr->x=3;
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Strukturen ===
Mit dem Anlegen einer Strukturvariablen kann diese auch initialisiert werden. Eine 'Vorbelegung' der Strukturelemente bei der Definition der Struktur ist in C nicht möglich.<br />
Die Initialisierung erfolgt über eine Initialisierungsliste (siehe Kap [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]). Innerhalb der Initialisierungsliste stehen die Initialisierungswerte entweder in der Reihenfolge der Datentypdefinition oder werden explizit mit dem ‘.‘ Operator angesprochen (designated initializers). Werden einzelne Strukturelemente ausgelassen, so werden diese mit 0 initialisiert:
<syntaxhighlight lang="C">
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <string.h>
struct abc{
int a,b;
int c=3; //KO: Kein Initialisierungswert von Strukturelementen möglich
char str[10];
};
int main(int argc,char *argv[]) {
struct abc v1={1,2,"hallo"}; //Alle Strukturelemente werden initialisiert
struct abc v2={ 1,2 }; //Initialisierung der Strukturlemente a und b
//Rest wird mit 0 initialisiert
struct abc v3={ .b=3}; //Initialisierung einzelner/designated Strukturele.
//Rest wird mit 0 initialisiert
struct abc v4={.a=strlen(v1.str)}; //Initialisierungswert ergibt
//sich erst zur Laufzeit.
//Nur als lokale Variable möglich!
struct abc v5={.b=1,.a=2,.b=12}; //Nur C: Reihenfolge und Doppelbenennung
//der Strukturelemente egal/möglich
struct abc v6={}; //Alle Strukturelemente mit 0 initialisieren
printf("v1.a=%d v1.b=%d v1.str[0]=%d\n",v1.a,v1.b,v1.str[0]);
printf("v2.a=%d v2.b=%d v2.str[0]=%d\n",v2.a,v2.b,v2.str[0]);
printf("v3.a=%d v3.b=%d v3.str[0]=%d\n",v3.a,v3.b,v3.str[0]);
printf("v4.a=%d v4.b=%d v4.str[0]=%d\n",v4.a,v4.b,v4.str[0]);
printf("v5.a=%d v5.b=%d v5.str[0]=%d\n",v5.a,v5.b,v5.str[0]);
printf("v6.a=%d v6.b=%d v6.str[0]=%d\n",v6.a,v6.b,v6.str[0]);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Eine Initialisierung einer Struktur über nachfolgende Art bewirkt etwas anderes, als erwartet:
<syntaxhighlight lang="C">
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
int main(int argc,char *argv[]) {
struct abc { int a,b,c; };
struct abc var={var.b=12,var.c=3};
printf("var.a=%d var.b=%d var.c=%d\n",var.a,var.b,var.c);
//Gerne mal den Compiler Wechseln
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Innerhalb der Initialisierungsliste wird über 'var.b=12' und 'var.c=3' die zu diesem Zeitpunkt noch nicht initialisierte Variable var die Elemente b und c initialisiert. Mit dem Werten der Initialisierungsliste (hier {12,3}) wird nachfolgend die Variable erneut initialisiert und 12 dem Strukturelement a und 3 dem Strukturelement b zugewiesen. Abhängig vom Compiler ist das Strukturelement c entweder 3 oder 0.
Bei verschachtelten Strukturen muss entsprechend obiger Aussage für jede innere Struktur eine eigene Initialisierungsliste erstellt werden. Die inneren Initialisierungslisten können entfallen, was jedoch nicht empfohlen wird und ergänzend vom Compiler bei '-Wall' als Warning angemerkt wird:
<syntaxhighlight lang="C">
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8}}
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={{.x=5,.y=6},{7,8}},
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct abc {
int a,b;
struct xy {
int x,y;
} xy;
struct xy arr[2];
};
struct abc v1={ //Initialisierung über Reihenfolge
1,2,
{3,4},
{ {5,6},{7,8} }
};
struct abc v2={ //Initialisierung über 'designated initializers'
.arr={ {.x=5,.y=6},{7,8} },
.xy={3,4},
.a=1,.b=2
};
struct abc v3={ //Fehlende innere Initialisierungsliste
1,2,
3,4,
5,6,7,8
};
int main(int argc,char *argv[]) {
printf("v1.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v1.a, v1.b, v1.xy.x, v1.xy.y, v1.arr[0].x, v1.arr[0].y, v1.arr[1].x, v1.arr[1].y );
printf("v2.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v2.a, v2.b, v2.xy.x, v2.xy.y, v2.arr[0].x, v2.arr[0].y, v2.arr[1].x, v2.arr[1].y );
printf("v3.a=%d .b=%d .xy.x=%d .xy.y=%d .arr[0].x=%d .arr[0].y=%d .arr[1].x=%d .arr[1].y=%d\n",
v3.a, v3.b, v3.xy.x, v3.xy.y, v3.arr[0].x, v3.arr[0].y, v3.arr[1].x, v3.arr[1].y );
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Zuweisen/Kopieren von Strukturen ===
Strukturen werden über den Namen als 'ganzes' angesprochen, so dass eine Zuweisung als 'ganzes' möglich ist. Bei bspw. einer 12-Byte großen Struktur werden bei Nutzung der Variable die gesamten 12-Byte gelesen/geändert!
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1,var2;
var1=var2; //12-Bytes kopiert
//--> entspricht memcpy(&var1,&var2,sizeof(xyz));
</syntaxhighlight>
Die Zuweisung als 'ganzes' gilt auch bei der Parameterübergabe und -rückgabe von Funktionen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;};
//Funktionsdefinition
struct xyz function(struct xyz par) {
return (struct xyz){par.z,par.y,par.x};
}
//Funktionsaufruf
struct xyz var=function((struct xyz){1,2,3});
//Mit dem Aufruf der Funktion werden 12-Bytes in die Variable par kopiert
//Mit dem Ende der Funktion werden 12-Bytes in die Variable var kopiert
</syntaxhighlight>
Bedenke, dass bei großen Strukturen das Kopieren Rechenzeit benötigt und folglich vermieden werden sollte! Alternativ sollten Zeiger auf Strukturen über- und zurückgeben werden.
Über Compound Literal (siehe Kap. [[Programmieren in C/C++: Grundlagen#Initialisierungsliste_/_Compound_Literal | Grundlagen:Initialisierungsliste / Compound Literal]]) kann einer Strukturvariablen als 'ganzes' einen neuen Wert zugewiesen werden:
<syntaxhighlight lang="C">
struct abc {int a,b,c;};
var1={.a=7}; //KO, Initialisierungsliste kann hier nicht
//angewendet werden
var1=(struct abc){.a=7}; //Wertezuweisung über Compound Literal möglich
</syntaxhighlight>
Formel gesehen entspricht das Compound Literal einer 'unnamed Variable', die als erstes angelegt und initialisiert wird. Der Inhalt dieser Variablen wird im Anschluss der eigentlichen Variable zugewiesen!
=== Prototyp / Deklaration einer Struktur ===
Soll der Datentyp einer Struktur genutzt werden, der erst an weiter hinten liegenden Stellen im Programm definiert wird, so ist wie bei Variablen/Funktionen ein Prototyp/Deklaration notwendig:
<syntaxhighlight lang="C">
struct abc; //Prototyp der Struktur abc
...
struct abc { int a,b,c;}; //Definition der Struktur abc
</syntaxhighlight>
Die Deklaration sagt einzig aus, dass die Struktur später definiert wird, beinhaltet aber nicht die Strukturelemente. Folglich kann auf Basis dieses Prototyps keine Variable definiert werden, sondern einzig ein Zeiger auf solche eine Struktur:
<syntaxhighlight lang="C">
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz; //Deklaration / Prototyp des Datentyps
// d.h. keine Benennung der Strukturelemente
struct xyz var1; //KO, es kann auf Basis der Deklaration keine
// Variable angelegt werden
struct xyz *pttr1; //OK, von einer Strukturdeklaration kann ein Zeiger
// angelegt werden!
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Anwendung:
* Struktur, welche auf sich selbst verweist (Verkettete Liste)
:<syntaxhighlight lang="C">
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl { //Entspricht gleichermaßen einem Prototyp, so dass
//innerhalb dieser Struktur dieser Datentyp zum
//Anlegen eines Strukturelementes genutzt werden kann
struct vl *next; //Zeiger auf das nächste Element
char daten[100];
};
int main(int argc,char *argv[]) {
struct vl *head=NULL;
struct vl a={.daten="Ele a"};
struct vl b={.daten="Element b"};
struct vl c={.daten="c-Eleent"};
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL; //Zur Kennzeichnung des letzten Elementes
for(struct vl*ptr=head;ptr;ptr=ptr->next)
printf("'%s'\n",ptr->daten);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Entsprechend der objektorientierten Programmierung, wenn alle Attribute der Klasse private sind:
:{| class="wikitable"
|-
! !! class.h
|-
|
||<syntaxhighlight lang="C">
struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
</syntaxhighlight>
|-
! main.c !! class.c
|-
|<syntaxhighlight lang="C">
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
..
//Kein Zugriff auf
//Strukturelemente möglich
return 0;
}
</syntaxhighlight>
||<syntaxhighlight lang="C">
#include "class.h"
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *)
malloc(sizeof(struct class));
this->attr1=10;
*me=this;
}
</syntaxhighlight>
|}
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include "class.h"
int main(int argc, char*argv[])
{
struct class *obj1;
konstruktor(&obj1);
//..
//Kein Zugriff auf Strukturelemente möglich
return 0;
}
|class_h=struct class; //Prototyp für Struktur
//so dass Nutzer dieser
//Struktur ein Zeiger auf diese anlegen,
//aber nicht auf die Strukturelemente
//zugreifen können.
//Prototyp der public Methoden
void konstruktor(struct class ** me);
|class_c=#include "class.h"
#include <stdlib.h> //fuer malloc()
#include <stdio.h> //fuer printf()
struct class {
int attr1;
int attr2;
};
void konstruktor(struct class ** me)
{
struct class *this;
this=(struct class *) malloc(sizeof(struct class));
printf("konstructor called\n");
this->attr1=10;
*me=this;
}
| execCompilerOptions=-Wall class.c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Vergleichen von Strukturen ===
Ein Vergleich von Strukturen über den direkten Weg ist nicht möglich. Vielmehr müssen die Strukturelemente händisch verglichen werden:
<syntaxhighlight lang="C">
struct xyz {int inx,y,z;} var1,var2;
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} var1={1,2,3},var2={1,2,3};
int main(int argc,char *argv[]) {
if(var1 == var2) //KO, ein Vergleich von Strukturvariablen ist nicht möglich
//Manueller Vergleich über den Vergleich der Strukturelemente
if(var1.x == var2.x && var1.y == var2.y && var1.z == var2.z)
printf("Strukturelemente von var1 und var2 identisch\n");
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis
* Bei Rechnerarchitekturen mit nicht ausgerichteter Speicherausrichtung (Alignment) kann ergänzend ein Vergleich über memcmp() erfolgen
=== Speicherplatzbedarf einer Struktur ===
Für jedes Strukturelement wird Speicher entsprechend der Größe des Datentyps reserviert. Der Speicherplatzbedarf der Gesamtstruktur ergibt sich aus der Summe der Strukturelemente:
<syntaxhighlight lang="C">
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
sizeof(var1) //ergibt 12
sizeof(struct xyz) //ergibt 12
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x; //Strukturelement belegt 4 Byte Speicher
int y; //Strukturelement belegt 4 Byte Speicher
int z; //Strukturelement belegt 4 Byte Speicher
}var1; //Speicherplatz der Struktur = 4+4+4 = 12 Byte
int main(int argc,char *argv[]) {
printf("sizeof(var1)=%zu Bytes\n",sizeof(var1));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Ermittlung der tatsächlichen Speichergröße einer Struktur erfolgt über den sizeof-Operator:
<syntaxhighlight lang="C">
struct xyz{int x,y,z;} a;
sizeof(a); //=12 OK
sizeof(a.x); //=4 OK
sizeof(struct xyz); //=12 OK
sizeof(struct xyz.x); // KO
//Ist dies dennoch notwendig, so kann dies über den Umweg eines Zeigers
//erfolgen:
sizeof(((struct xyz *)0)->x); //=4 OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz{
int x,y,z;
} a;
int main(int argc,char *argv[]) {
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
printf("sizeof(a.x)=%zu Bytes\n",sizeof(a.x));
printf("sizeof(struct xyz)=%zu Bytes\n",sizeof(struct xyz));
printf("sizeof(struct xyz.x)=%zu Bytes\n",sizeof(struct xyz.x));
printf("sizeof(((struct xyz *)0)->x)=%zu Bytes\n",sizeof(((struct xyz *)0)->x));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Bei Rechnerarchitekturen mit ausgerichteter Speicherausrichtung (Alignment) (siehe {{w|Speicherausrichtung}}) kann der tatsächliche Speicherbedarf größer sein! Hier fügt der Compiler ggf. zwischen den Strukturelemente Füllbytes (Padding Bytes) ein
* Die Reihenfolge der Strukturelemente wird vom Compiler nicht geändert. D.h. die Zuordnung der Speicherstellen zu den Strukturelementen erfolgt in der Definitionsreihenfolge
=== Interne Organisation ===
Compilerintern werden die Strukturelemente über einen Offset dargestellt. Das erste Strukturelement bekommt dabei immer den Offset 0 zugewiesen. Das nachfolgende Element bekommt als Offset die Größe des Datentyps des vorherigen Elementes zugewiesen. Usw.. <br />
Der Compiler setzt den Zugriff auf ein Strukturelement einer (Struktur)Variablen so um, dass er zunächst die Startadresse der Variablen holt und zu dieser den Offset des Strukturelementes addiert. Die Anzahl der zu lesenden/schreiben Bytes ergibt sich aus dem Datentyp des Strukturelementes:
<syntaxhighlight lang="C">
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1; //(Beispielhaft soll var1 die Speicheradressen
//0x100..0x10B belegen). Der Zugriff auf
//die Variable erfolgt immer über die Startadresse
var1.x=7; //Zugriff auf Speicheradresse 0x100+0 (Offset)
var1.y=8; //Zugriff auf Speicheradresse 0x100+4 (Offset)
var1.z=9; //Zugriff auf Speicheradresse 0x100+8 (Offset)
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz { //Das Anlegen der Variable var bedeutet,
int x,y,z; //12Byte Speicher zu reservieren.
} var1;
int main(int argc,char *argv[]) {
//Zugriff siehe Compiler
var1.x=7; //mov DWORD PTR var[rip+0],7
var1.y=8; //mov DWORD PTR var[rip+4],7
var1.z=9; //mov DWORD PTR var[rip+8],7
return 0;
} | execCompilerOptions=-Wall|
h=c|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der Offset eines Strukturelementes kann mit dem offsetof-Operator ermittelt werden:
<code>Syntax: offsetof(type,Strukturelement)</code>
Wie beim sizeof-Operator gilt der offsetof-Operator als Konstantenausdruck und der Rückgabedatentyp ist <code>size_t</code>. Zur Nutzung des Operators muss die Header-Datei 'stddef.h' inkludiert werden:
<syntaxhighlight lang="C">
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var1;
offsetof(struct xyz,z) --> 8
offsetof(var1,z) --> KO: Es wird ein Datentyp und
keine Variable erwartet
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz{
int x,y,z;
} var1;
int main(int argc,char *argv[]) {
printf("offsetof(struct xyz,x)=%zu Bytes\n",offsetof(struct xyz,x));
printf("offsetof(struct xyz,y)=%zu Bytes\n",offsetof(struct xyz,y));
printf("offsetof(struct xyz,z)=%zu Bytes\n",offsetof(struct xyz,z));
printf("offsetof(var1,z)=%zu Bytes\n",offsetof(var1,z));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Unter Nutzung des offsetof-Operators kann man bei gegebener Adresse eines Strukturelementes auf die Startadresse der zugrundeliegenden Struktur zurückrechnen:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} var1;
int *ptri=&var1.y;
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
struct xyz {int x,y,z;} var={1,2,3};
int *ptri=&var.y;
int main(int argc,char *argv[]) {
struct xyz *ptrxyz=(struct xyz *)((char *)ptri-offsetof(struct xyz, y));
printf("ptrxyz->x=%d ptrxyz->y=%d ptrxyz->z=%d",ptrxyz->x,ptrxyz->y,ptrxyz->z);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Dazu wird von der Startadresse des Strukturelementes der Offset abgezogen. Da der offsetof-Operator den Abstand in Bytes zurückgibt, muss der Pointer auf das Strukturelement zuvor ebenfalls in ein 'Byte'-Zeiger gewandelt werden.
Im Linux kernel wird diese Subtraktion über das container_of Makro realisiert:
<syntaxhighlight lang="C">
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
</syntaxhighlight>
Dieses Makro ermöglicht es, bei gegeben Startadresse eines Strukturelementes die Startadresse der zugrundeliegenden Struktur zu berechnen. Anwendung findet dieses Makro bspw. in:
* der objektorientierten Programmierung, um ausgehend vom gegebenen Parent-Element die Startadresse des Child-Elementes zu berechnen:
:<syntaxhighlight lang="C">
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
..
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type,member));})
struct parent {
int attr1,attr2;
};
struct child {
int attr1;
struct parent parent;
};
void parent_methode(struct parent *me){
struct child *child=container_of(me,struct child, parent);
printf("parent.attr1=%d parent.att2=%d\n",me->attr1,me->attr2);
printf("child.attr1=%d\n",child->attr1);
}
int main(int argc,char *argv[]) {
struct child obj1;
obj1.attr1=1;
obj1.parent.attr1=2;
obj1.parent.attr2=3;
parent_methode(&obj1.parent);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* bei verketteten Listen, wenn das Next-Element im Datensatz selbst eingearbeitet ist:
:<syntaxhighlight lang="C">
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h>
#include <stddef.h> //Zur Nutzung des OffsetOf Operators
#define container_of(PTR, TYPE, MEMBER) \
((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
typedef struct vl {
struct vl *next;
} vl_t;
typedef struct {
int daten1;
vl_t *next;
int daten2;
} daten_t;
vl_t head={NULL};
int vl_addfront(daten_t *daten)
{
daten->next=head.next;
head.next=(vl_t *)&(daten->next);
return 0;
}
daten_t *vl_getfront(void) {
vl_t *tmp=head.next;
if(tmp) {
head.next=head.next->next;
}
return container_of(tmp,daten_t,next);
}
int main(int argc,char *argv[]) {
daten_t obj1={.daten1=1,.daten2=2};
daten_t obj2={.daten1=3,.daten2=4};
vl_addfront(&obj1);
vl_addfront(&obj2);
daten_t *ret=vl_getfront();
printf("%d %d\n",ret->daten1,ret->daten2);
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Explizites Cast ===
Eine Struktur kann nicht in einen anderen Datentyp und damit auch nicht in einen anderen Strukturdatentyp mit identischen Strukturelementen konvertiert werden:
<syntaxhighlight lang="C">
struct xyz {int x,y,z;} xyz;
struct abc {int a,b,c;} abc;
int var;
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct xyz {
int x,y,z;
} xyz;
struct abc {
int a,b,c;
} abc;
int var;
int main(int argc,char *argv[]) {
xyz=abc; //KO, Datentyp struct xyz != struct abc
xyz=(struct xyz)abc; //KO, siehe zuvor
int neu1 = (int) xyz; //KO
int neu2 = (int) xyz.x; //OK (Das Strukturelement x ist vom Datentyp int)
struct xyz neu2 = (struct xyz)3; //KO
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Incomplete Array ===
Das letzte Element einer Struktur kann ein Array ohne Angabe einer Dimensionsgröße sein (Incomplete Array/Flexible Array Member). Bei der Definition einer Variablen von solch einem Datentyp wird in der Tat kein Speicher für das letzte Element reserviert, so dass dies 'händisch' erfolgen muss. Auf das Array kann ungeachtet dessen unproblematisch zugegriffen werden:
<syntaxhighlight lang="C">
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert
//wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl a; //Es wird nur Speicher für den next Zeiger reserviert
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(a)=%zu Bytes\n",sizeof(a));
a.data[0]='7'; //Syntax OK, jedoch erzeugt dies ein Laufzeitfehler,
//da kein Speicherplatz für das Incomplete Array reserviert wurde
//Zur Darstellung dieses Sachverhaltes wurde der Sanitizer
//über den Compilerschalter -fsanitize=address aktiviert
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Die Speicherplatzreservierung für das incomplete Array kann auf zwei verschiedene Arten erfolgen:
* Speicherplatzreservierung für das Incomplete Array über Variableninitialisierung (nur GCC-C und nur im Falle einer globalen Variablen)
:<syntaxhighlight lang="C">
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h>
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
struct vl ele1 = {
.next = NULL,
.data = {32, 31, 30} //Durch Initialisierung der einzelnen Array Elemente
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
struct vl ele2 = {
.next = NULL,
.data[3-1] = 0 //Durch Initialisierung des letzten Array Elementes
}; //Vorsicht, sizeof(ele) gibt dennoch nur 4/8 zurück
int main(int argc,char *argv[]) {
printf("sizeof(struct vl*)=%zu Bytes\n",sizeof(struct vl*));
printf("sizeof(ele1)=%zu Bytes\n",sizeof(ele1));
printf("sizeof(ele2)=%zu Bytes\n",sizeof(ele2));
return 0;
} | execCompilerOptions=-Wall|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Speicherplatzreservierung für das Incomplete Array über malloc
:<syntaxhighlight lang="C">
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct vl {
struct vl *next;
char data[]; //incomplete Array / flexible Array Member
};
int main(int argc,char *argv[]) {
struct vl *b=malloc(sizeof(struct vl)+ //Größe der Struktur
sizeof(char[3] )); //Größe des Arrays
if(b==NULL)
return printf("malloc failed\n"),1;
b->data[1]='7'; //OK, da mit dem Anlegen von b Speicher für 2
//data Element reserviert wurde
//zum Beweis Sanitizer über -fsanitize=address eingebunden
free(b);
return 0;
} | execCompilerOptions=-Wall -fsanitize=address|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Das Incomplete Array bietet sich überall dort an, wo Daten gespeichert werden sollen, deren Größe sich erst zur Laufzeit ergibt.
=== Anwendung ===
Die Nutzung des Datentyps struct empfiehlt sich an vielen Stellen:
* Zusammengehörende Daten zu Kapseln (entsprechend der objektorientierten Programmierung
* Verkette Listen
* Aufgrund der Typsicherheit zur Darstellung von sicherheitskritischen Aufgaben
Siehe Übungsbereich!
=== C++ ===
Der wesentliche Syntax von Strukturen wurde in C++ übernommen. D.h.:
* das abschließende Semikolon
* der Zugriff auf die Strukturelemente
* Speicherplatzreservierung
* die Definition von Variablen mit der Definition des Datentyps
* ...
Ergänzend wurde in C++ der Datentyp class eingeführt, der weitestgehend identisch zu struct ist. Geändert/Hinzugefügt wurden folgende Sachverhalte:
* Classen/Strukturen können Methoden haben
* Operatoren (Zuweisungsoperator, Addition, ...) können überladen werden
* Alle Strukturelemente (und Methoden) einer struct sind per default public
* Alle Attribute (und Methoden) einer Class sind per default private
* Zur Nutzung des Datentyps ist das führende struct nicht notwendig (dies bedingt dann auch, dass der Strukturdatentyp kein separater Namensraum ist)
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var_xyz;
</syntaxhighlight>
* Initialisierungswerte für Strukturelemente und Klassenattribute bei der Datentypbeschreibung angegeben werden können:
:<syntaxhighlight lang="C++">
struct xyz {
int x=3;
int y=1;
int z;
};
xyz var={7}; //var.x=7 var.y=1 var.z=0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x=3;
int y=1;
int z;
};
int main(int argc,char *argv[]) {
xyz var={7}; //var.x=7 var.y=1 var.z=0
printf("var.x=%d var.y=%d var.z=%d\n",var.x,var.y,var.z);
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* In C++ kann eine Struktur ebenfalls über 'designated initializers' initialisiert werden. Jedoch muss die Reihenfolge der Initialisierungselement identisch zur Datentypdefinition sein. Auch ist keine Doppeltbenennung erlaubt:
:<syntaxhighlight lang="C++">
struct xyz {
int x,y,z;
};
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stdlib.h> //fuer malloc() free()
struct xyz {
int x,y,z;
};
int main(int argc,char *argv[]) {
xyz var1={.x=1, .y=2, .z=3}; //OK, Reihenfolge identisch
xyz var2={.y=1, .z=3}; //OK, Reihenfolge identisch
xyz var3={.y=1, .x=0}; //KO, Reihenfolge nicht identisch
xyz var4={.x=1, .x=2}; //KO, keine Doppeltbenennung möglich
(void)var1;
(void)var2;
(void)var3;
(void)var4;
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
== Union ==
Ähnlich wie eine Struktur ist ein Union ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wird. Bei sog. Union beginnen jedoch alle Komponenten nicht wie bei Strukturen an nacheinander folgenden Speicheradressen, sondern an der identischen Speicheradresse, d.h. ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union kann folglich zu einem Zeitpunkt nur ein Element enthalten. Der benötigte Speicherplatz ergibt sich aus der größten Komponente.
<code>Syntax: union Unionname<sub>Opt</sub> {Datentyp Variablenname; …}<sub>Opt</sub> Variablenliste<sub>Opt</sub>;</code>
Ein Schutz/Zugriffssteuerung der Unionelemente ist nicht vorhanden. Es kann in beliebiger Reihenfolge auf die einzelnen Elemente zugegriffen werden.
Die Anwendung ist identisch wie bei Strukturen, so dass im Folgenden nur die Abweichungen zu den Strukturen beschrieben werden.
=== Speicherplatzbedarf und interne Struktur einer Union ===
Die Größe der Union ergibt sich aus dem größtem Unionelement. Alle Unionelemente überlappen sich, so dass der Offset zum Basiselement 0 ist:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
printf("Größe: %zu\n",sizeof (union abc)); //-> 4
printf("Offset a:%zu\n",offsetof(union abc,a)); //-> 0
printf("Offset b:%zu\n",offsetof(union abc,b)); //-> 0
printf("Offset c:%zu\n",offsetof(union abc,c)); //-> 0
return 0;
} | execCompilerOptions=-Wall |
lang=c++|
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Wird ein kleineres Unionelement belegt und im Anschluss ein größeres Unionelement gelesen, so ist der Inhalt der durch das kleinere Element nicht beschriebenen Speicherstellen undefiniert:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc.a=0x11;
printf("%08x",abc.c);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
};
void foo(int var) {
int lok=var;
printf("Foo(%#08x) called\n",lok);
}
void bar(void) {
union abc abc;
abc.a=0x11;
printf("abc.a=%#02x\n",abc.a);
printf("abc.c=%#08x\n",abc.c);
}
int main(int argc,char *argv[]) {
//Zur Darstellung des Phänomens muss
//erstmal der Stack mit Daten belegt werden!
foo(0x12345678);
bar();
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Initialisierung von Union ===
Bei einer Union kann nur ein Element initialisiert werden, d.h. die Initialisierungsliste kann nur einen Wert beinhalten. Ohne explizite Benennung des Unionelementes in der Initialisierungsliste wird das erste Element aus der Datentypbeschreibung initialisiert. Mit expliziter Benennung mittels 'designated initializers' können auch andere Elemente initialisiert werden:
<syntaxhighlight lang="C">
union abc {
char a;
short b;
int c;
} abc;
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
#include <stddef.h> //fuer offsetoff()
union abc {
char a;
short b;
int c;
} abc;
int main(int argc,char *argv[]) {
abc=3; //KO keine Initialisierungsliste
abc=(union abc){3}; //OK Initialisierung des ersten Elementes a
abc=(union abc){.b=3}; //OK Initialisierung des Elementes b
abc=(union abc){3,4}; //KO nur ein Initialisiuerngswert erlaubt
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Anwendung ===
Mittels des Datentyps union können diverse Anwendungsfälle abgedeckt werden:
* Über Union lassen sich größere Datentypen in kleinere Datentypen unterteilen, um z.B. einzelne Bytes zu extrahieren:
<syntaxhighlight lang="C">
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union floatu var={1.234};
printf("%f\n",var.var); //Darstellung des Float-Wertes
printf("%x\n",var.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var.byte[0],var.byte[1],var.byte[2],var.byte[3]);
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
union longlong var2={0x123456789ABCDEFULL};
printf("%llx\n",var2.ll);
printf("%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union floatu {
float var; //Float ist 4-Byte groß
unsigned int hex; //Integer ist 4-Byte groß
char byte[4]; //Ohne Worte
};
union longlong {
long long ll; //Long Long ist 8-Byte groß
int i[2]; //Ohne Worte
short s[4];
char c[8];
};
int main(int argc,char *argv[]) {
union floatu var1={1.234};
printf("var1.var=%f\n",var1.var); //Darstellung des Float-Wertes
printf("var1.hex=%x\n",var1.hex); //Darstellung des Float-Wertes 'BinäreZahl'
printf("var1.byte[0..3]=%hhx %hhx %hhx %hhx\n", //Darstellung der einzelnen Bytes
var1.byte[0],var1.byte[1],var1.byte[2],var1.byte[3]);
union longlong var2={0x123456789ABCDEFULL};
printf("var2.ll=%llx\n",var2.ll);
printf("var2.i[0..1]=%x %x\n",var2.i[0],var2.i[1]);
//Vorsicht: Die Aufteilung der Bytes ist von der Rechnerarchitektur
//(Endianes) und von der Ausrichtung durch den Compiler abhängig
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Ein weiterer Anwendungsfall ergibt sich, wenn in einer Struktur unterschiedliche Datensätze gespeichert werden sollen (siehe {{w|Tagged Union}}):
:<syntaxhighlight lang="C">
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct set {
char *index;
char *value;
};
struct get {
char *index;
char *value;
};
struct cli{
//Enum zur Darstellung des aktiven Unionelementes hilfreich
enum {SETTER,GETTER} tag;
union { //Interpretation abhängig von tag
struct set set;
struct get get;
} ;
};
int main(int argc,char *argv[]) {
struct cli var={.tag=SETTER, .set.index="hallo"};
if(var.tag==SETTER)
printf("Set: %s",var.set.index);
else
printf("Get: %s",var.get.index);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Mittels eines Tagged Union kann komfortabel ein Binärbaum realisiert werden:
:<syntaxhighlight lang="C">
//Quelle: https://github.com/Hirrolot/datatype99
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=
#include <stdio.h> //fuer printf()
struct BinaryTree; //Prototyp
struct BinaryTreeNode {
struct BinaryTree *lhs;
int x;
struct BinaryTree *rhs;
} BinaryTreeNode_t;
struct BinaryTree {
enum { Leaf, Node } tag;
union {
int leaf;
struct BinaryTreeNode node;
} data;
};
int sum(const struct BinaryTree *tree) {
switch (tree->tag) {
case Leaf:
return tree->data.leaf;
case Node:
return sum(tree->data.node.lhs) +
tree->data.node.x +
sum(tree->data.node.rhs);
}
return -1; // Invalid input (no such variant).
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Die Eigenschaften des Datentyps union entsprechen den Eigenschaften des Datentyps struct in C++.
== Enum/Aufzählungstyp ==
Nach dem Wikipedia Artikel {{w|Aufzählungstyp}} ist ''ein Aufzählungstyp (englisch enumerated type) ein Datentyp für Variablen mit einer endlichen Wertemenge. Alle zulässigen Werte des Aufzählungstyps werden bei der Deklaration des Datentyps mit einem eindeutigen Namen (Identifikator) definiert, sie sind Symbole.''
<code>Syntax: enum enumname<sub>Opt</sub> {definition-list[=expression]}<sub>Opt</sub> Variablenliste<sub>Opt</sub></code>
Die Anwendung ist identisch wie bei Strukturen, so dass nachfolgend nur die Abweichungen zu den Strukturen beschrieben werden.
=== Datentyp von enum ===
In C entspricht der Datentyp Enum dem Datentyp <code>int</code> so dass Zuweisungen/Vergleiche mit Ganzzahlen möglich sind. Ganzzahloperationen funktionieren ebenso:
<syntaxhighlight lang="C">
enum STATUS {OK,KO=5}; //Definition des Datentyps
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
status++;
status=5.7;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum STATUS {OK,KO=5}; //Definition des Datentyps
int main(int argc,char *argv[]) {
enum STATUS status; //Definition einer Variable dieses Datentyps
status=OK;
if(status == 5)
printf("status == 5\n");
status++;
status=5.7;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== Enumelemente ===
Die Elemente der Definitionsliste sind Integerkonstanten. Diese können auch in Kombination mit anderen Datentypen genutzt werden. Auch gibt es keinen gesonderten Namensraum für Elemente der Definitionsliste. Sie 'konkurrieren' folglich mit allen Variablen- und Funktionsnamen:
<syntaxhighlight lang="C">
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum mode {OK, KO};
enum {FIRST,SECOND,LAST}; //Anonymes Enum!
enum {EINS,ZWEI,LAST}; //KO, Symbolname LAST bereits vergeben
int main(int argc,char *argv[]) {
enum mode var1=OK;
var1=4711; //OK, enum entspricht Datentyp int
int var2=KO; //OK, EnumElement entspricht Datentyp int
int OK=KO; //KO, Symbolname OK bereits für EnumElement vergeben
var1=FIRST; //OK, var1 und FIRST sind zwar unterschiedlich
//Enumtypen,jedoch entspricht beides dem Datentyp int
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Der erste Enumelement der Definitionsliste bekommt den Wert 0 zugewiesen. Folgeelemente bekommen den Wert des Vorgängerelementes +1 zugewiesen.
Enumelemente können mit einer Konstanten (und Konstantenausdruck) initialisiert werden:
<syntaxhighlight lang="C">
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum {bill=10, john=bill+2, fred=john+1} ;
//Negative Werte sind möglich
enum {error=-3, warning, info, ok}; //warning=-2 info=-1 …
//Doppelte Wertzuweisung sind möglich
enum {Ostfalia=10,Wolfenbuettel=10};
//Hinter dem letzten Enumelement kann ein Komma folgen
enum {test=10,};
int main(int argc,char *argv[]) {
printf("bill=%d john=%d, fred=%d\n",bill,john,fred);
printf("error=%d warning=%d info=%d ok=%d\n",error,warning,info,ok);
printf("Ostfalia=%d Wolfenbuettel=%d\n",Ostfalia,Wolfenbuettel);
printf("test=%d\n",test);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
Hinweis:
* Es empfiehlt sich, die Enumelemente in GROSSBUCHSTABEN zu schreiben. Hiermit wird gekennzeichnet, dass es sich um Konstanten und nicht um Variablen/Funktionen handelt
=== Anwendung ===
Die Nutzung des Datentyps enum empfiehlt sich überall dort, wo eine Fallunterscheidung notwendig ist:
* Statusrückgabe von Funktionen:
:<syntaxhighlight lang="C">
enum STATUS {OK,MEMORY_OVERFLOW, DIVISION_BY_ZERO};
enum STATUS funct(…) {
return MEMORY_OVERFLOW;
}
</syntaxhighlight>
* Beschreibung der Zustände und der Ereignisse eines Zustandsautomates:
:<syntaxhighlight lang="C">
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum EREIGNIS {EREIGNIS1,EREIGNIS2,EREIGNIS3};
void zustandsautomat(enum EREIGNIS ereignis) {
static enum {IDLE,OPERAND,OPERATOR,} zustand=IDLE;
switch(zustand) {
case IDLE:
case OPERAND:
//Compiler meckert bei fehlendem Case über OPERATOR
}
}
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Ergänzend zu den Abweichungen bei Structs sind hier weitere Unterscheidungsmerkmale vorhanden:
* Enums stellen einen eigenen Datentyp dar, der nicht mit int kompatible ist. Das bedingt unter anderem, dass einige Operatoren wie z.B. ++ nicht mehr auf Variablen des Datentyps enum angewendet werden. Die Enumelemente als solches sind jedoch kompatibel zum Ganzzahldatentyp:
:<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE};
enum Color var1=RED;
int main(int argc,char *argv[]) {
var1=4; //KO
var1=var1+1; //KO
var1++; //KO
int var2=RED; //OK
if(RED==2) //OK
printf("RED==2\n");
(void)var1;
(void)var2;
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
* Auch enums können Methoden besitzen.
* Über Operatorüberladung können z.B. nicht vorhandene Operatoren wie ++/-- ergänzt werden
* Über unscoped/scoped Enumerations wird der 'Namensraum' gesteuert:
:* Unscoped Enumeration (Elemente der Definitionsliste stehen wie bei C im Zugriff)
::<code>Syntax: enum name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum Color {RED,GREN,BLUE };
Color r = RED;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum Color {RED,GREN,BLUE };
Color r = RED;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
lang=c++
}} Öffnen im Compiler Explorer] }}
:* Scoped enumeration (Elemente der Definitionsliste haben einen eigenen 'Namensraum')
::<code>Syntax: enum '''class|struct''' name<sub>Opt</sub> : type<sub>OPT</sub> {enumerator=constexp, …};</code>
::<syntaxhighlight lang="C++">
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
enum class Color {RED,GREN=20,BLUE };
Color r = Color::BLUE;
int main(int argc,char *argv[]) {
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true|
lang=c++
}} Öffnen im Compiler Explorer] }}
== Bitfelder ==
Nach dem Wikipediaartikel {{w|Bitfeld}} ''bezeichnet in der Informationstechnik und Programmierung ein Bitfeld ein vorzeichenloses Ganzzahldatentyp, in dem einzelne Bits oder Gruppen von Bits aneinandergereiht werden. Es stellt eine Art Verbunddatentyp auf Bit-Ebene dar. Im Gegensatz dazu steht der primitive Datentyp, bei dem der Wert aus allen Stellen gemeinsam gebildet wird.''
Der Syntax entspricht dem struct-Syntax, mit der Ergänzung, dass hinter den Strukturelementen noch die Bitbreite getrennt durch ein Doppelpunkt angegeben wird:
<syntaxhighlight lang="C">
struct time {
unsigned int hour: 5; //0..23 Bits 0..4
unsigned int minute: 6; //0..59 Bits 5..10
Unsigend int second: 6; //0..59 Bits 11..16
} myTime;
</syntaxhighlight>
Als mögliche Datentypen für die Strukturelemente stehen nur die Ganzzahldatentypen <code>int</code>, <code>short</code>, <code>long</code> , <code>long long</code> und <code>char</code> zur Verfügung. Der Datentyp eines Strukturelementes muss mindestens die Anzahl der Bits enthalten, wie diese über die Bitbreite gefordert wird.
Von den Strukturelementen kann keine Adresse bestimmt werden! Auch der <code>offsetf</code> - Operator schlägt fehl.
Der Datentyp entspricht im Wesentlichen einem Ganzzahlzahldatentyp, so dass bei Zugriff auf eine Variable dieses Datentyps eine Ganzzahl gelesen/geschrieben wird. Bei Zugriff auf die einzelnen Strukturelemente werden die entsprechenden Bits dieser Ganzzahlvariablen maskiert, so dass nur die betroffenen Bits geändert werden:
<syntaxhighlight lang="C">
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) | (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) | ((second&0b00001111)<<2);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
struct test {
unsigned char first:2;
unsigned char second:4;
unsigned char third:2;
};
//Nachweis am besen über den Maschinensprachevergleich!
int main(int argc,char *argv[]) {
struct test var={.first=1,.second=1,.third=1};
//entspricht
unsigned char var1=0b01000101;
var.second=1;
//entspricht:
var1=(var1&0b11000011) {{!}} (1<<2);
var.second++;
//entspricht
int second =(var1>>2)&0b00001111;
second++;
var1=(var1&0b11000011) {{!}} ((second&0b00001111)<<2);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true |
h=c
}} Öffnen im Compiler Explorer] }}
=== Anwendung===
* Komprimierte Speicherung der Uhrzeit (wie dies z.B. in Realtimeclocks erfolgt)
:<syntaxhighlight lang="C">
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union {
struct { //Datentyp zum 'Bitweisen' Zugriff
unsigned int hour:5;
unsigned int minute:6;
unsigned int second:6;
};
unsigned int hex; //Datentyp zum Zugriff aller Elemente
} myTime;
int main(int argc,char *argv[]) {
myTime.hour = 13;
myTime.minute = 37;
myTime.second = 59;
printf("Zeit: %02d:%02d:%02d\n", myTime.hour,myTime.minute,myTime.second );
//Alternativer/Händischer Zugriff auf die einzelnen Bits
printf("Es ist jetzt %02d:%02d:%02d Uhr\n",((myTime.hex>> 0)&0b011111),
((myTime.hex>> 5)&0b111111),
((myTime.hex>>11)&0b111111));
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
* Aufteilung von FloatingPoint Zahlen in seine Komponenten
:<syntaxhighlight lang="C">
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
</syntaxhighlight>
{{noprint|
[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|example_c=#include <stdio.h> //fuer printf()
union float_mes {
float flo;
struct ieee { //aus ieee754.h kopiert
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
int hex;
};
//aus ieee754.h kopiert
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
int main(int argc,char *argv[]) {
union float_mes test={0.1};
printf("float: %f\n",test.flo);
printf("hex: %x\n",test.hex);
printf("bin: ");
for(unsigned int flag=0x80000000; flag; flag=flag>>1)
printf("%c%s",test.hex&flag?'1':'0',
flag&0x80800000?":":(flag&1?"\n":""));
printf("bitfield: (%c)%x * 2^(%d-%d)\n",
(test.ieee.negative==1?'-':'+'),
test.ieee.mantissa,
test.ieee.exponent,
IEEE754_FLOAT_BIAS);
return 0;
} | execCompilerOptions=-Wall |
execCompilerOutputShown=true
}} Öffnen im Compiler Explorer] }}
=== C++ ===
Bitfelder existieren mit den bekannten Ergänzungen auch in C++.
<noinclude>
{{Navigation zurückhochvor buch
|zurücklink=Programmieren in C/C++: Grundlagen
|zurücktext=Grundlagen
|hochlink=Programmieren in C/C++
|hochtext=Inhaltsverzeichnis
|vorlink=Programmieren in C/C++: DatentypeSpecifier
|vortext=Datatype-/Storage Class Specifier}}
</noinclude>
guxigwxrsl13kd2xcmx9ma606ffcose
CPRT/6971
0
119123
1090845
1090825
2026-09-15T08:50:58Z
Pelikam
111447
/* Energie G */
1090845
wikitext
text/x-wiki
[[CPRT|< Inhaltsverzeichnis - CPRT]]
== Energie G ==
{|
|-
|| <math> \qquad\qquad </math>
|| <math> dE(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \mu\,dN </math>|| <math> + </math>||<math> t\,dS </math>
|| <math> + </math>||<math> p\,d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> dG(N,t,p) </math>||<math> = </math>
|| <math> + </math>||<math> \mu\,dN </math>||<math> - </math>||<math> S\,dt </math>
|| <math> - </math>||<math> (-V)\,dp </math>
|| <math> \qquad (N,t,p) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> G(N,t,V) </math>||<math> = </math>
|| <math> + </math>||<math> \mu\,N </math>||<math> </math>||<math> </math>
|| <math> </math>||<math> </math>
|| <math> \qquad (N,t,p) \qquad </math>
|}
{|
|-
|| <math> (01a)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> +\,\left[ 0 - S\frac{\partial t}{\partial N} \right] dN
+ \left[ 0 - S\frac{\partial t}{\partial S} \right] dS
+ \left[ 0 - S\frac{\partial t}{\partial (-V)}\right] d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (01a)\qquad </math>
|| <math> -\,(-V)\,dp(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - (-V)\frac{\partial p}{\partial N} \right] dN
+ \left[ 0 - (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> + \left[ 0 - (-V)\frac{\partial p}{\partial (-V)}\right] d(-V) </math>
|| <math> \qquad\qquad </math>
|-
|| <math> (02a)\qquad </math>
|| <math> dG(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\frac{\partial t}{\partial N}
- (-V)\frac{\partial p}{\partial N} \right] dN </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S}
- (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> + </math>||<math> \left[ p - S\frac{\partial t}{\partial (-V)}
- (-V)\frac{\partial p}{\partial (-V)} \right] d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
| <math> (03a)\qquad </math>
|| <math> F(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\frac{\partial t}{\partial N} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ p - S\frac{\partial t}{\partial (-V)}\right] (-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
| <math> (04a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial N} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial (-V)}\right] (-V) </math>
|| <math> \qquad \leftarrow (03a) \qquad </math>
|-
|| <math> (05a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> - </math>||<math> N\,d\left[ \mu - S\frac{\partial t}{\partial N}\right] </math>
|| <math> - </math>||<math> S\,d\left[ 0 - S\frac{\partial t}{\partial S}\right] </math>
|| <math> - </math>||<math> (-V)\,d\left[ p - S\frac{\partial t}{\partial (-V)}\right] </math>
|| <math> \qquad \leftarrow (02a),(03a) \qquad </math>
|-
|| <math> (01b)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial \mu}{\partial S}\right]\,dN </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial t}{\partial S}\right]\,dS </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial p}{\partial S}\right]\,d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (02b)\qquad </math>
|| <math> dF(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\,\frac{\partial \mu}{\partial S}\right] dN </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial t}{\partial S} \right] dS </math>
|| <math> + </math>||<math> \left[ p - S\,\frac{\partial p}{\partial S} \right] d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (03b)\qquad </math>
|| <math> F(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\frac{\partial \mu}{\partial S} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ p - S\frac{\partial p}{\partial S} \right] (-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (04b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial \mu}{\partial S} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial p}{\partial S} \right] (-V) </math>
|| <math> \qquad \leftarrow (03b) \qquad </math>
|-
|| <math> (05b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> - </math>||<math> N\,d\left[ \mu - S\frac{\partial \mu}{\partial S}\,\right] </math>
|| <math> - </math>||<math> S\,d\left[ 0 - S\frac{\partial t}{\partial S}\,\right] </math>
|| <math> - </math>||<math> (-V)\,d\left[ p - S\frac{\partial p}{\partial S}\,\right] </math>
|| <math> \qquad \leftarrow (02b), (03b) \qquad </math>
|}
== Beispielhafte Herleitungen Energie G ==
b8gg7jsox4oe4z079r33fzqupa45ouj
1090846
1090845
2026-09-15T09:14:36Z
Pelikam
111447
/* Energie G */
1090846
wikitext
text/x-wiki
[[CPRT|< Inhaltsverzeichnis - CPRT]]
== Energie G ==
{|
|-
|| <math> \qquad\qquad </math>
|| <math> dE(N,S,V) </math>||<math> = </math>
|| <math> +\,\mu\,dN + t\,dS + p\,d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> dG(N,t,p) </math>||<math> = </math>
|| <math> +\,\mu\,dN - S\,dt -(-V)\,dp </math>
|| <math> \qquad (N,t,p) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> G(N,t,V) </math>||<math> = </math>
|| <math> + \mu\,N </math>
|| <math> \qquad (N,t,p) \qquad </math>
|}
{|
|-
|| <math> (01a)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - S\frac{\partial t}{\partial N} \right] dN
+ \left[ 0 - S\frac{\partial t}{\partial S} \right] dS
+ \left[ 0 - S\frac{\partial t}{\partial (-V)}\right] d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (01a)\qquad </math>
|| <math> -\,(-V)\,dp(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - (-V)\frac{\partial p}{\partial N} \right] dN
+ \left[ 0 - (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - (-V)\frac{\partial p}{\partial (-V)}\right] d(-V) </math>
|| <math> \qquad\qquad </math>
|-
|| <math> (02a)\qquad </math>
|| <math> dG(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] dN
+\left[ 0 - S\frac{\partial t}{\partial S} - (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - S\frac{\partial t}{\partial (-V)} - (-V)\frac{\partial p}{\partial (-V)} \right] d(-V) </math>
|| <math> \qquad\qquad </math>
|-
|| <math> (03a)\qquad </math>
|| <math> G(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] N </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
| <math> (03a)\qquad </math>
|| <math> F(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\frac{\partial t}{\partial N} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ p - S\frac{\partial t}{\partial (-V)}\right] (-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
| <math> (04a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial N} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial (-V)}\right] (-V) </math>
|| <math> \qquad \leftarrow (03a) \qquad </math>
|-
|| <math> (05a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> - </math>||<math> N\,d\left[ \mu - S\frac{\partial t}{\partial N}\right] </math>
|| <math> - </math>||<math> S\,d\left[ 0 - S\frac{\partial t}{\partial S}\right] </math>
|| <math> - </math>||<math> (-V)\,d\left[ p - S\frac{\partial t}{\partial (-V)}\right] </math>
|| <math> \qquad \leftarrow (02a),(03a) \qquad </math>
|-
|| <math> (01b)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial \mu}{\partial S}\right]\,dN </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial t}{\partial S}\right]\,dS </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial p}{\partial S}\right]\,d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (02b)\qquad </math>
|| <math> dF(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\,\frac{\partial \mu}{\partial S}\right] dN </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial t}{\partial S} \right] dS </math>
|| <math> + </math>||<math> \left[ p - S\,\frac{\partial p}{\partial S} \right] d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (03b)\qquad </math>
|| <math> F(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\frac{\partial \mu}{\partial S} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ p - S\frac{\partial p}{\partial S} \right] (-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (04b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial \mu}{\partial S} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial p}{\partial S} \right] (-V) </math>
|| <math> \qquad \leftarrow (03b) \qquad </math>
|-
|| <math> (05b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> - </math>||<math> N\,d\left[ \mu - S\frac{\partial \mu}{\partial S}\,\right] </math>
|| <math> - </math>||<math> S\,d\left[ 0 - S\frac{\partial t}{\partial S}\,\right] </math>
|| <math> - </math>||<math> (-V)\,d\left[ p - S\frac{\partial p}{\partial S}\,\right] </math>
|| <math> \qquad \leftarrow (02b), (03b) \qquad </math>
|}
== Beispielhafte Herleitungen Energie G ==
ofr05fit52zstg7qomc2gzf7ejer0q9
1090847
1090846
2026-09-15T09:16:20Z
Pelikam
111447
/* Energie G */
1090847
wikitext
text/x-wiki
[[CPRT|< Inhaltsverzeichnis - CPRT]]
== Energie G ==
{|
|-
|| <math> \qquad\qquad </math>
|| <math> dE(N,S,V) </math>||<math> = </math>
|| <math> +\,\mu\,dN + t\,dS + p\,d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> dG(N,t,p) </math>||<math> = </math>
|| <math> +\,\mu\,dN - S\,dt -(-V)\,dp </math>
|| <math> \qquad (N,t,p) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> G(N,t,V) </math>||<math> = </math>
|| <math> + \mu\,N </math>
|| <math> \qquad (N,t,p) \qquad </math>
|}
{|
|-
|| <math> (01a)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - S\frac{\partial t}{\partial N} \right] dN
+ \left[ 0 - S\frac{\partial t}{\partial S} \right] dS
+ \left[ 0 - S\frac{\partial t}{\partial (-V)}\right] d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (01a)\qquad </math>
|| <math> -\,(-V)\,dp(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - (-V)\frac{\partial p}{\partial N} \right] dN
+ \left[ 0 - (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - (-V)\frac{\partial p}{\partial (-V)}\right] d(-V) </math>
|| <math> \qquad\qquad </math>
|-
|| <math> (02a)\qquad </math>
|| <math> dG(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] dN
+\left[ 0 - S\frac{\partial t}{\partial S} - (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - S\frac{\partial t}{\partial (-V)} - (-V)\frac{\partial p}{\partial (-V)} \right] d(-V) </math>
|| <math> \qquad\qquad </math>
|-
|| <math> (03a)\qquad </math>
|| <math> G(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] N </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (04a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> +\left[ 0 - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] N </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
| <math> (03a)\qquad </math>
|| <math> F(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\frac{\partial t}{\partial N} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ p - S\frac{\partial t}{\partial (-V)}\right] (-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
| <math> (04a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial N} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial (-V)}\right] (-V) </math>
|| <math> \qquad \leftarrow (03a) \qquad </math>
|-
|| <math> (05a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> - </math>||<math> N\,d\left[ \mu - S\frac{\partial t}{\partial N}\right] </math>
|| <math> - </math>||<math> S\,d\left[ 0 - S\frac{\partial t}{\partial S}\right] </math>
|| <math> - </math>||<math> (-V)\,d\left[ p - S\frac{\partial t}{\partial (-V)}\right] </math>
|| <math> \qquad \leftarrow (02a),(03a) \qquad </math>
|-
|| <math> (01b)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial \mu}{\partial S}\right]\,dN </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial t}{\partial S}\right]\,dS </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial p}{\partial S}\right]\,d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (02b)\qquad </math>
|| <math> dF(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\,\frac{\partial \mu}{\partial S}\right] dN </math>
|| <math> + </math>||<math> \left[ 0 - S\,\frac{\partial t}{\partial S} \right] dS </math>
|| <math> + </math>||<math> \left[ p - S\,\frac{\partial p}{\partial S} \right] d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (03b)\qquad </math>
|| <math> F(N,S,V) </math>||<math> = </math>
|| <math> + </math>||<math> \left[ \mu - S\frac{\partial \mu}{\partial S} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ p - S\frac{\partial p}{\partial S} \right] (-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> (04b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial \mu}{\partial S} \right] N </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial t}{\partial S} \right] S </math>
|| <math> + </math>||<math> \left[ 0 - S\frac{\partial p}{\partial S} \right] (-V) </math>
|| <math> \qquad \leftarrow (03b) \qquad </math>
|-
|| <math> (05b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> - </math>||<math> N\,d\left[ \mu - S\frac{\partial \mu}{\partial S}\,\right] </math>
|| <math> - </math>||<math> S\,d\left[ 0 - S\frac{\partial t}{\partial S}\,\right] </math>
|| <math> - </math>||<math> (-V)\,d\left[ p - S\frac{\partial p}{\partial S}\,\right] </math>
|| <math> \qquad \leftarrow (02b), (03b) \qquad </math>
|}
== Beispielhafte Herleitungen Energie G ==
9jxk9s724f7aebup8ubtiwpb3vc95il
1090848
1090847
2026-09-15T09:47:26Z
Pelikam
111447
/* Energie G */
1090848
wikitext
text/x-wiki
[[CPRT|< Inhaltsverzeichnis - CPRT]]
== Energie G ==
{|
|-
|| <math> \qquad\qquad </math>
|| <math> dE(N,S,V) </math>||<math> = </math>
|| <math> +\,\mu\,dN + t\,dS + p\,d(-V) </math>
|| <math> \qquad (N,S,V) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> dG(N,t,p) </math>||<math> = </math>
|| <math> +\,\mu\,dN - S\,dt -(-V)\,dp </math>
|| <math> \qquad (N,t,p) \qquad </math>
|-
|| <math> \qquad\qquad </math>
|| <math> G(N,t,V) </math>||<math> = </math>
|| <math> +\,\mu\,N </math>
|| <math> \qquad (N,t,p) \qquad </math>
|}
{|
|-
|| <math> (01a)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - S\frac{\partial t}{\partial N} \right] dN
+ \left[ 0 - S\frac{\partial t}{\partial S} \right] dS
+ \left[ 0 - S\frac{\partial t}{\partial (-V)}\right] d(-V) </math>
|| <math> (N,S,V) </math>
|-
|| <math> (01a)\qquad </math>
|| <math> -\,(-V)\,dp(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - (-V)\frac{\partial p}{\partial N} \right] dN
+ \left[ 0 - (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> (N,S,V) </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - (-V)\frac{\partial p}{\partial (-V)}\right] d(-V) </math>
|| <math> </math>
|-
|| <math> (02a)\qquad </math>
|| <math> dG(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] dN
+\left[ 0 - S\frac{\partial t}{\partial S} - (-V)\frac{\partial p}{\partial S} \right] dS </math>
|| <math> (N,S,V) </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - S\frac{\partial t}{\partial (-V)} - (-V)\frac{\partial p}{\partial (-V)} \right] d(-V) </math>
|| <math> </math>
|-
|| <math> (03a)\qquad </math>
|| <math> G(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] N </math>
|| <math> (N,S,V) </math>
|-
|| <math> (04a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> +\left[ 0 - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right] N </math>
|| <math> \leftarrow (03a) </math>
|-
|| <math> (05a)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> +\,N\,d\left[ \mu - S\frac{\partial t}{\partial N} - (-V)\frac{\partial p}{\partial N} \right]
+ S\,d\left[ 0 - S\frac{\partial t}{\partial S} - (-V)\frac{\partial p}{\partial S} \right] </math>
|| <math> \leftarrow (02a), (03a) </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\,(-V)\,d\left[ 0 - S\frac{\partial t}{\partial (-V)}
- (-V)\frac{\partial p}{\partial (-V)} \right] d(-V) </math>
|| <math> </math>
|-
|| <math> (01b)\qquad </math>
|| <math> -\,S\,dt(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - S\frac{\partial \mu}{\partial S} \right] dN
+ \left[ 0 - S\frac{\partial t}{\partial S} \right] dS
+ \left[ 0 - S\frac{\partial p}{\partial S} \right] d(-V) </math>
|| <math> (N,S,V) </math>
|-
|| <math> (01b)\qquad </math>
|| <math> -\,(-V)\,dp(N,S,V) </math>||<math> = </math>
|| <math> + \left[ 0 - (-V)\frac{\partial \mu}{\partial (-V)} \right] dN
+ \left[ 0 - (-V)\frac{\partial t}{\partial (-V)} \right] dS </math>
|| <math> (N,S,V) </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - (-V)\frac{\partial p}{\partial (-V)}\right] d(-V) </math>
|| <math> </math>
|-
|| <math> (02b)\qquad </math>
|| <math> dG(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial \mu}{\partial S} - (-V)\frac{\partial \mu}{\partial (-V)} \right] dN
+\left[ 0 - S\frac{\partial t}{\partial S} - (-V)\frac{\partial t}{\partial (-V)} \right] dS </math>
|| <math> (N,S,V) </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\left[ 0 - S\frac{\partial p}{\partial S} - (-V)\frac{\partial p}{\partial (-V)} \right] d(-V) </math>
|| <math> </math>
|-
|| <math> (03b)\qquad </math>
|| <math> G(N,S,V) </math>||<math> = </math>
|| <math> +\left[ \mu - S\frac{\partial \mu}{\partial N} - (-V)\frac{\partial \mu}{\partial (-V)} \right] N </math>
|| <math> (N,S,V) </math>
|-
|| <math> (04b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> +\left[ 0 - S\frac{\partial \mu}{\partial N} - (-V)\frac{\partial \mu}{\partial (-V)} \right] N </math>
|| <math> \leftarrow (03b) </math>
|-
|| <math> (05b)\qquad </math>
|| <math> 0 </math>||<math> = </math>
|| <math> +\,N\,d\left[ \mu - S\frac{\partial \mu}{\partial S} - (-V)\frac{\partial \mu}{\partial (-V)} \right]
+ S\,d\left[ 0 - S\frac{\partial t}{\partial S} - (-V)\frac{\partial t}{\partial (-V)} \right] </math>
|| <math> </math>
|-
|| <math> \qquad\qquad </math>
|| <math> </math>||<math> </math>
|| <math> +\,(-V)\,d\left[ 0 - S\frac{\partial p}{\partial S}
- (-V)\frac{\partial p}{\partial (-V)} \right] d(-V) </math>
|| <math> \leftarrow (02b), (03b) </math>
|}
== Beispielhafte Herleitungen Energie G ==
lcqvgd0z1r9q9at4pfdbi8ogt70eqt3
Gitarre: CAGED-Stammtöne - Erster Fingersatz
0
123107
1090836
1090768
2026-09-14T14:05:32Z
Mjchael
2222
/* 1. Fingersatz • C-Form */
1090836
wikitext
text/x-wiki
[[Gitarre: CAGED-Stammtöne - Zweiter Fingersatz]]
== Erster Fingersatz ==
=== Eintaktige Sequenzen ===
Du wirst feststellen, dass sich die Sequenzen recht schnell lernen lassen.
==== 1. Fingersatz • C-Form (open) ====
Die erste Lage mit leeren Saiten stellt noch keine Herausforderung dar.
<score sound="1" raw="1">
\version "2.20.0"
\header {
title="1. Fingersatz (C-Form) in C-Dur"
subtitle="Eintaktige Sequenzen"
}
%% Diskant- bzw. Melodiesaiten
Diskant = \relative c'' {
% \set TabStaff.minimumFret = #2
% \set TabStaff.restrainOpenStrings = ##t
\key c \major
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
\once \override NoteHead #'color = #red c1
\bar "|."
}
%% Layout- bzw. Bildausgabe
\score {
<<
\new Voice {
\clef "treble_8"
\time 4/4
\tempo 4 = 120
\set Score.tempoHideNote = ##t
\Diskant \addlyrics {
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
c
}
}
\new TabStaff { \tabFullNotation \Diskant }
>>
\layout {}
}
%% Midiausgabe mit Wiederholungen, ohne Akkorde
\score {
<<
\unfoldRepeats {
\new Staff <<
\tempo 4 = 120
\time 4/4
\set Staff.midiInstrument = #"acoustic guitar (nylon)"
\clef "G_8"
\Diskant
>>
}
>>
\midi {}
}
%% unterdrückt im raw="!"-Modus das DinA4-Format.
\paper {
indent=0\mm
%% DinA4 = 210mm - 10mm Rand - 20mm Lochrand = 180mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
% bookTitleMarkup=##f
scoreTitleMarkup=##f
}
</score>
<br>
==== 1. Fingersatz • A- (Bb-)Form ====
Du musst noch nicht einmal den C-Barré im 3. Bund bemühen, um den Grundton zu finden. Die C-Dur-Tonleiter in den ersten drei Bünden reicht. Natürlich kannst du auch den Startton G suchen. Die Tabulatur sagt dir "D-Saite 5. Bund". Erinnere dich daran, dass dies der Stimmton der D-Saite ist (beim Stimmen nach Bünden). Auch hier ist der Fingersatz leicht.
<div style="float:left; padding:5px;margin:5px; border:black solid 1px; ">
;1. Fingersatz • A- (Bb-)Form
<score raw="1">
\version "2.14.2"
\markup {
\override #'(size . 3.0) {
\override #'(fret-diagram-details . (
(orientation . landscape )
(finger-code . in-dot )
(dot-color . #'black)
(dot-radius . 0.4)
(dot-position . 0.5)
(top-fret-thickness . 6)
(fret-count . 3)
(number-type . roman-upper)
))
\fret-diagram-verbose #'(
(place-fret 4 2 3 darkgrey )
(place-fret 4 3 4 yellow3 )
(place-fret 4 5 5 darkgrey )
(place-fret 5 2 "j7" yellow3 )
(place-fret 5 3 1 black )
(place-fret 5 5 2 darkgreen )
)
}}
\paper{
indent=0\mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
bookTitleMarkup = ##f
scoreTitleMarkup = ##f}
</score>
</div>
<score sound="1" raw="1">
\version "2.20.0"
\header {
title="1. Fingersatz (A- (Bb)-Form) in C-Dur"
subtitle="Eintaktige Sequenzen"
}
%% Diskant- bzw. Melodiesaiten
Diskant = \relative c' {
\set TabStaff.minimumFret = #2
\set TabStaff.restrainOpenStrings = ##t
\key c \major
g8-4 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
\once \override NoteHead #'color = #red c1
\bar "|."
}
%% Layout- bzw. Bildausgabe
\score {
<<
\new Voice {
\clef "treble_8"
\time 4/4
\tempo 4 = 120
\set Score.tempoHideNote = ##t
\Diskant \addlyrics {
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
c
}
}
\new TabStaff { \tabFullNotation \Diskant }
>>
\layout {}
}
%% Midiausgabe mit Wiederholungen, ohne Akkorde
\score {
<<
\unfoldRepeats {
\new Staff <<
\tempo 4 = 120
\time 4/4
\set Staff.midiInstrument = #"acoustic guitar (nylon)"
\clef "G_8"
\Diskant
>>
}
>>
\midi {}
}
%% unterdrückt im raw="!"-Modus das DinA4-Format.
\paper {
indent=0\mm
%% DinA4 = 210mm - 10mm Rand - 20mm Lochrand = 180mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
% bookTitleMarkup=##f
scoreTitleMarkup=##f
}
</score>
<br>
==== 1. Fingersatz • G-Form ====
<div style="float:left; padding:5px;margin:5px; border:black solid 1px; ">
;1. Fingersatz • G-Form
<score raw="1">
\version "2.14.2"
\markup {
\override #'(size . 4.0) {
\override #'(fret-diagram-details . (
(orientation . landscape )
(finger-code . in-dot )
(dot-color . #'black)
(dot-radius . 0.4)
(dot-position . 0.5)
(top-fret-thickness . 6)
(fret-count . 3)
(number-type . roman-upper)
))
\fret-diagram-verbose #'(
(place-fret 2 5 3 darkgrey )
(place-fret 2 6 4 yellow3 )
(place-fret 2 8 5 darkgrey )
(place-fret 3 4 "j7" yellow3 )
(place-fret 3 5 1 black )
(place-fret 3 7 2 darkgreen )
)
}}
\paper{
indent=0\mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
bookTitleMarkup = ##f
scoreTitleMarkup = ##f}
</score>
</div>
Bei der G-Form kommt es zwischen der G- und H-Saite zu einem Lagewechsel. Du musst dir jedesmal eine Strategie zurechtlegen, wann und wie du am besten den Lagewechsel durchführst.
Wenn du Glück hast, findest du im Notenbild einen Hinweis, wie man günstig die Lage wechseln kann. Ich empfehle dir dort wo die 2 über den Noten steht, den Mittelfinger zu nehmen.
*(1 = Z, 2 = M, 3 = R, 4 = K, 0 = leere Saite)
Betrachte solche Hinweis nur als Vorschlag, denn es gibt keine verbindliche Regel, wie der Lagewechsel zu erfolgen hat. Übst du die gleiche Sequenzen ein paar Saiten höher oder tiefer, geht es leichter von der Hand.
Beachte den Lagewechsel zwischen der G- und H-Saite. Den Grundton C kannst du dir auch vom Ringfinger auf der G-Saite des C-Barrés ableiten.
Du musst dir hier eine Strategie zurechtlegen, wann du den Lagewechsel durchführen möchtest. Ich empfehle hier, den Lagewechsel so früh wie möglich zu machen, damit du den Zeigefinger frei hast, um gleich hintereinander zwei Töne in einem Bund zu spielen. Betrachte die Angaben zum Fingersatz nur als Vorschlag.
<score sound="1" raw="1">
\version "2.20.0"
\header {
title="1. Fingersatz (G-Form) in C-Dur"
subtitle="Eintaktige Sequenzen"
}
%% Diskant- bzw. Melodiesaiten
Diskant = \relative c'' {
\set TabStaff.minimumFret = #4
\set TabStaff.restrainOpenStrings = ##t
\key c \major
g8-4 f e f g e f g
f e d-4 e-2 f-3 d e f
e d c d e c-1 d-4 e-2
d c b c d b c d
\once \override NoteHead #'color = #red c1
\bar "|."
}
%% Layout- bzw. Bildausgabe
\score {
<<
\new Voice {
\clef "treble_8"
\time 4/4
\tempo 4 = 120
\set Score.tempoHideNote = ##t
\Diskant \addlyrics {
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
c
}
}
\new TabStaff { \tabFullNotation \Diskant }
>>
\layout {}
}
%% Midiausgabe mit Wiederholungen, ohne Akkorde
\score {
<<
\unfoldRepeats {
\new Staff <<
\tempo 4 = 120
\time 4/4
\set Staff.midiInstrument = #"acoustic guitar (nylon)"
\clef "G_8"
\Diskant
>>
}
>>
\midi {}
}
%% unterdrückt im raw="!"-Modus das DinA4-Format.
\paper {
indent=0\mm
%% DinA4 = 210mm - 10mm Rand - 20mm Lochrand = 180mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
% bookTitleMarkup=##f
scoreTitleMarkup=##f
}
</score>
<br>
Hier eine alternative Lösung. Du kannst einen kleinen Barré über die Noten C und E legen, und den Lagewechsel später ausführen. Das V unter dem C zeigt hier den 5. Bund an, und nicht etwa Abschläge. Der Lagewechsel erfolgt hier im letzten Takt.
<score sound="1" raw="1">
\version "2.20.0"
\header {
title="1. Fingersatz (G-Form) in C-Dur"
subtitle="Eintaktige Sequenzen"
}
%% Diskant- bzw. Melodiesaiten
Diskant = \relative c'' {
\set TabStaff.minimumFret = #4
\set TabStaff.restrainOpenStrings = ##t
\key c \major
g8-4 f e f g e f g
f e d e f d e f
e d-2
\textSpannerDown
\override TextSpanner.bound-details.left.text = "V"
c-1\startTextSpan
d e-1 c-1 d e-1\stopTextSpan
d-4 c b c d b c d
\once \override NoteHead #'color = #red c1
\bar "|."
}
%% Layout- bzw. Bildausgabe
\score {
<<
\new Voice {
\clef "treble_8"
\time 4/4
\tempo 4 = 120
\set Score.tempoHideNote = ##t
\Diskant \addlyrics {
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
c
}
}
\new TabStaff { \tabFullNotation \Diskant }
>>
\layout {}
}
%% Midiausgabe mit Wiederholungen, ohne Akkorde
\score {
<<
\unfoldRepeats {
\new Staff <<
\tempo 4 = 120
\time 4/4
\set Staff.midiInstrument = #"acoustic guitar (nylon)"
\clef "G_8"
\Diskant
>>
}
>>
\midi {}
}
%% unterdrückt im raw="!"-Modus das DinA4-Format.
\paper {
indent=0\mm
%% DinA4 = 210mm - 10mm Rand - 20mm Lochrand = 180mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
% bookTitleMarkup=##f
scoreTitleMarkup=##f
}
</score>
==== 1. Fingersatz • E- (F-)Form ====
<div style="float:left; padding:5px;margin:5px; border:black solid 1px; ">
;1. Fingersatz • E- (F-)Form
<score raw="1">
\version "2.24.4"
\markup {
\override #'(size . 4.0) {
\override #'(fret-diagram-details . (
(orientation . landscape )
(finger-code . in-dot )
(dot-color . #'black)
(dot-radius . 0.4)
(dot-position . 0.5)
(top-fret-thickness . 6)
(fret-count . 3)
(number-type . roman-upper)
))
\fret-diagram-verbose #'(
(place-fret 5 7 3 darkgrey )
(place-fret 5 8 4 yellow3 )
(place-fret 5 10 5 darkgrey )
(place-fret 6 7 "j7" yellow3 )
(place-fret 6 8 1 black )
(place-fret 6 10 2 darkgreen )
)
}}
\paper{
indent=0\mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
bookTitleMarkup = ##f
scoreTitleMarkup = ##f}
</score>
</div>
Den Grundton C auf der E-Saite kannst du dir vom C-Barré der E-Form (wie ein F- Barré) im 8. Bund ableiten. Der Fingersatz ist wieder einfach.
<score sound="1" raw="1">
\version "2.20.0"
\header {
title="1. Fingersatz (E-(F)-Form) in C-Dur"
subtitle="Eintaktige Sequenzen"
}
%% Diskant- bzw. Melodiesaiten
Diskant = \relative c' {
\set TabStaff.minimumFret = #7
\set TabStaff.restrainOpenStrings = ##t
\key c \major
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
\once \override NoteHead #'color = #red c1
\bar "|."
}
%% Layout- bzw. Bildausgabe
\score {
<<
\new Voice {
\clef "treble_8"
\time 4/4
\tempo 4 = 120
\set Score.tempoHideNote = ##t
\Diskant \addlyrics {
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
c
}
}
\new TabStaff { \tabFullNotation \Diskant }
>>
\layout {}
}
%% Midiausgabe mit Wiederholungen, ohne Akkorde
\score {
<<
\unfoldRepeats {
\new Staff <<
\tempo 4 = 120
\time 4/4
\set Staff.midiInstrument = #"acoustic guitar (nylon)"
\clef "G_8"
\Diskant
>>
}
>>
\midi {}
}
%% unterdrückt im raw="!"-Modus das DinA4-Format.
\paper {
indent=0\mm
%% DinA4 = 210mm - 10mm Rand - 20mm Lochrand = 180mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
% bookTitleMarkup=##f
scoreTitleMarkup=##f
}
</score>
==== 1. Fingersatz • D-Form ====
<div style="float:left; padding:5px;margin:5px; border:black solid 1px; ">
;1. Fingersatz • D-Form
<score raw="1">
\version "2.14.2"
\markup {
\override #'(size . 4.0) {
\override #'(fret-diagram-details . (
(orientation . landscape )
(finger-code . in-dot )
(dot-color . #'black)
(dot-radius . 0.4)
(dot-position . 0.5)
(top-fret-thickness . 6)
(fret-count . 3)
(number-type . roman-upper)
))
\fret-diagram-verbose #'(
(place-fret 3 9 3 darkgrey )
(place-fret 3 10 4 yellow3 )
(place-fret 3 12 5 darkgrey )
(place-fret 4 9 "j7" yellow3 )
(place-fret 4 10 1 black )
(place-fret 4 12 2 darkgreen )
)
}}
\paper{
indent=0\mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
bookTitleMarkup = ##f
scoreTitleMarkup = ##f}
</score>
</div>Die Tonhöhe ist die selbe, wie in der G-Form, wo wir uns komplizierte Strategien für den Fingersatz zurechtlegen mussten. In dieser Lage ist alles einfacher. Wenn du später mal einen herausfordernden Lick zwischen der G- und H-Saite hast, wäre eine weitere gangbare Strategie den Lick in eine fingertechnisch günstigere Lage zu verlegen.
<score sound="1" raw="1">
\version "2.20.0"
\header {
title="1. Fingersatz (D-Form) in C-Dur"
subtitle="Eintaktige Sequenzen"
}
%% Diskant- bzw. Melodiesaiten
Diskant = \relative c'' {
\set TabStaff.minimumFret = #9
\set TabStaff.restrainOpenStrings = ##t
\key c \major
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
\once \override NoteHead #'color = #red c1
\bar "|."
}
%% Layout- bzw. Bildausgabe
\score {
<<
\new Voice {
\clef "treble_8"
\time 4/4
\tempo 4 = 120
\set Score.tempoHideNote = ##t
\Diskant \addlyrics {
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
c
}
}
\new TabStaff { \tabFullNotation \Diskant }
>>
\layout {}
}
%% Midiausgabe mit Wiederholungen, ohne Akkorde
\score {
<<
\unfoldRepeats {
\new Staff <<
\tempo 4 = 120
\time 4/4
\set Staff.midiInstrument = #"acoustic guitar (nylon)"
\clef "G_8"
\Diskant
>>
}
>>
\midi {}
}
%% unterdrückt im raw="!"-Modus das DinA4-Format.
\paper {
indent=0\mm
%% DinA4 = 210mm - 10mm Rand - 20mm Lochrand = 180mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
% bookTitleMarkup=##f
scoreTitleMarkup=##f
}
</score>
<br>
==== 1. Fingersatz • C-Form ====
<div style="float:left; padding:5px;margin:5px; border:black solid 1px; ">
;1. Fingersatz • C-Form
<score raw="1">
\version "2.24.4"
\markup {
\override #'(size . 4.0) {
\override #'(fret-diagram-details . (
(orientation . landscape )
(finger-code . in-dot )
(dot-color . #'black)
(dot-radius . 0.4)
(dot-position . 0.5)
(top-fret-thickness . 6)
(fret-count . 3)
(number-type . roman-upper)
))
\fret-diagram-verbose #'(
(place-fret 1 12 3 darkgrey )
(place-fret 1 13 4 yellow3 )
(place-fret 1 15 5 darkgrey )
(place-fret 2 12 "j7" yellow3 )
(place-fret 2 13 1 black )
(place-fret 2 15 2 darkgreen )
)
}}
\paper{
indent=0\mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
bookTitleMarkup = ##f
scoreTitleMarkup = ##f}
</score>
</div> Hier wurde die C-Durtonleiter in den 12. Bund verlegt. Der Grundton ist auf der H-Saite im 13. Bund. (Eine Oktave höher als bei der C-Dur Tonleiter in den ersten drei Bünden.) Wer keine E-Gitarre hat oder wer keine Akkustik mit Cutaway hat, der kann die C-Form auch in einem niedrigeren Bund üben.
<score sound="1" raw="1">
\version "2.20.0"
\header {
title="1. Fingersatz (C-Form) in C-Dur"
subtitle="Eintaktige Sequenzen"
}
%% Diskant- bzw. Melodiesaiten
Diskant = \relative c''' {
\set TabStaff.minimumFret = #12
\set TabStaff.restrainOpenStrings = ##t
\key c \major
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
\once \override NoteHead #'color = #red c1
\bar "|."
}
%% Layout- bzw. Bildausgabe
\score {
<<
\new Voice {
\clef "treble_8"
\time 4/4
\tempo 4 = 120
\set Score.tempoHideNote = ##t
\Diskant \addlyrics {
g8 f e f g e f g
f e d e f d e f
e d c d e c d e
d c b c d b c d
c
}
}
\new TabStaff { \tabFullNotation \Diskant }
>>
\layout {}
}
%% Midiausgabe mit Wiederholungen, ohne Akkorde
\score {
<<
\unfoldRepeats {
\new Staff <<
\tempo 4 = 120
\time 4/4
\set Staff.midiInstrument = #"acoustic guitar (nylon)"
\clef "G_8"
\Diskant
>>
}
>>
\midi {}
}
%% unterdrückt im raw="!"-Modus das DinA4-Format.
\paper {
indent=0\mm
%% DinA4 = 210mm - 10mm Rand - 20mm Lochrand = 180mm
line-width=180\mm
oddFooterMarkup=##f
oddHeaderMarkup=##f
% bookTitleMarkup=##f
scoreTitleMarkup=##f
}
</score>
==Hier gehts weiter==
i5zr6awtbonpiatbzzod6de1o7l530m
Traktorenlexikon: Allis-Chalmers 5015
0
123128
1090835
2026-09-14T13:05:39Z
Baupit
56622
Neue Seite (vgl. [[WB:AZ]])
1090835
wikitext
text/x-wiki
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Allis-Chalmers |HERSTELLER= Allis-Chalmers}}
{{:Traktorenlexikon: Modell-Infobox
| HERSTELLER = ALLIS-CHALMERS
| MODELLREIHE = 5000 er-Baureihe
| MODELL = 5015
| BILD =
| BILDBESCHREIBUNG =
| BAUWEISE = Blockbauweise
| PRODUKTIONSBEGINN = 1982
| PRODUKTIONSENDE = 1985
| STÜCKZAHL =
| EIGENGEWICHT = 581 (4 WD: 658)
| LÄNGE = 2.101
| BREITE = 1.039
| HÖHE = 1.191
| RADSTAND = 1.290
| BODENFREIHEIT = 348
| SPURWEITE =
| SPURWEITE VORNE = 805 (4 WD: 861)
| SPURWEITE HINTEN = 836-965
| WENDERADIUS MIT LENKBREMSE = 1.980 (4 WD: 1.940)
| WENDERADIUS OHNE LENKBREMSE =
| BEREIFUNG VORNE = 4.00-12 ASF (4 WD: 5.00-14 AS)
| BEREIFUNG HINTEN = 8.00-18 AS
| LEISTUNG KW = 13,4
| LEISTUNG PS = 18,2
| NENNDREHZAHL = 2.500
| ZYLINDER = 3
| HUBRAUM = 1.002
| DREHMOMENTANSTIEG =
| KRAFTSTOFF = Diesel
| KÜHLSYSTEM = Wasserkühlung
| ANTRIEBSTYP = Heck- oder Allradantrieb
| GETRIEBE = 9 V/3 R
| HÖCHSTGESCHWINDIGKEIT = 14
| KATEGORIESORTIERUNG = Kompaktschlepper
}}
In den 1970 er- und 1980 er-Jahren stieg die Nachfrage nach kompakten und kleinen Traktoren. ALLIS-CHALMERS reagierte auf diesen Trend und importierte hierzu asiatische Kompaktmodelle. Im Jahr 1982 stellte ALLIS-CHALMERS, auf der Basis des SIMPLICITY-Modell 9518, das Kompaktmodell 5015 vor. Der ALLIS-CHALMERS 5015 konnte als Heckantrieb- oder Allradantriebausführung bestellte werden. Konzipiert war er für leichtere Arbeiten in der Landwirtschaft, Grundstückspflege und im Garten- und Landschaftsbau. Der wassergekühlte Dreizylinder-Dieselmotor verfügte über eine Nennleistung von 18 DIN-PS. Verblockt war dieses Aggregat mit einem unsychronisierten 9/3-Gänge Gruppengetriebe.
==Motor==
* TOYOSHA, Typ: CS-100, stehender-wassergekühlter Viertakt-Dreizylinder-Reihen-OHV-Dieselmotor mit Wirbelkammer-Einspritzverfahren, Fliehkraftregler, Druckumlaufschmierung mittels Zahnradpumpe, Kraftstoffkolbenpumpe, KIKI-Einspritzpumpe, Mehrlochdüse, Zentrifugalölfilter, Düsenhalter, vierfach-gelagerte Kurbelwelle, Trockenluftfilter, Kühlwasser-Kreiselpumpe und Lamellenkühler incl. Lüfter.
* Bohrung = 72,9 mm, Hub = 80 mm
* Verdichtungsverhältnis = 22,5:1
* Max. Drehmoment = 54,9 Nm bei 1.800 U/min.
* Mittlere Kolbengeschwindigkeit = 6,67 m/sec.
* Geregelter Drehzahlbereich = 750 bis 2.600 U/min.
* Einspritzdruck = 175 bis 185 bar
==Kupplung==
* Pedal-betätigte, trockene Einscheibenkupplung, Typ: 7,25"
184,2 mm Scheibendurchmesser
==Getriebe==
* Im Ölbad laufendes nicht-synchronisiertes Schubrad-Gruppengetriebe
* Wechselgetriebe mit drei Vorwärts- und ein Rückwärtsgang
* Reduziergetriebe, in einen langsamen und einen schnellen Bereich unterteilt
* Zusätzliches Vorschaltgetriebe als Kriechganggetriebe ausgebildet
9 Vorwärts- und 3 Rückwärtsgänge
==Geschwindigkeiten vor- und rückwärts==
"Geschwindigkeiten des 9/3-Gänge Triebwerk, mit Bereifung 8.00-18 AS"
{| class="wikitable"
|-
! bei Motordrehzahl (U/min) !! 2.500
|-
! Kriechgang - Gruppe !!
|-
| 1.Gang || 0,16 km/h
|-
| 2.Gang || 0,32 km/h
|-
| 3.Gang || 0,80 km/h
|-
| 1.Rückwärtsgang || 0,48 km/h
|-
! Langsame Gruppe !!
|-
| 1.Gang || 1,13 km/h
|-
| 2.Gang || 1,61 km/h
|-
| 3.Gang || 3,38 km/h
|-
| 2.Rückwärtsgang || 2,41 km/h
|-
! Schnelle Gruppe !!
|-
| 1.Gang || 4,35 km/h
|-
| 2.Gang || 6,44 km/h
|-
| 3.Gang || 13,68 km/h
|-
| 3.Rückwärtsgang || 9,82 km/h
|-
|}
==Zapfwelle==
* Handhebel-betätigte, kupplungsabhängige Getriebezapfwelle
* Stummel = 1 3/8" -6 Keile
* Einfach schaltbar, 540 U/min.
* 540 U/min. bei 2.326 U/min.- Motordrehzahl
* Oder 580 U/min. mit Nenndrehzahl
Übertragbare Leistung = 15,2 DIN-PS
==Bremsen==
* Pedal-betätigte, trockene Trommelbremse auf die Seitenwellen wirkend, als Einzelradbremse ausgebildet
* Handhebel-betätigte unabhängige Feststellbremse, auf eine Bremsscheibe wirkend
==Achsen==
* Pendelnd-gelagerte Stahlvorderachse
Spurweite = 805 mm (4 WD = 861 mm)
* Starre Hinterachse mit Kegelradgetriebe und Stirnraduntersetzung
* Pedal-betätigte Differentialsperre
Verstellbare Spurweite mittels Radumschlag = 836 mm bis 965 mm
==Lenkung==
* Mechanische Lenkung
==Hydrauliksystem und Kraftheber==
* Hydraulischer Block-Kraftheber mit Dreipunktaufhängung
* Ein einfachwirkenden Hubzylinder
* Dreipunktaufhängung der Kategorie I
"Funktionen:"
* Heben, Senken, Schwimmstellung, Positionsregelung und Senkdrossel
OPEN-CENTER Hydrauliksystem mit Zahnradpumpe
* Förderleistung = 17,0 l/min. bei 138 bar
Max. Hubkraft an den Koppelpunkten = 350 kg
==Steuergeräte==
* Ein einfachwirkendes Steuergerät
==Elektrische Ausrüstung==
"12 Volt- Einrichtung"
* Anlasser, Typ: 12 V-1,07 PS
==Maße und Abmessungen==
* Länge über alles = 2.101 mm
* Breite über alles = 1.039 mm
* Höhe über Motorhaube = 1.039 mm
* Höhe über Lenkrad = 1.191 mm
* Radstand = 1.290 mm
* Bodenfreiheit unter der Vorderachse = 348 mm
* Betriebsgewicht = 581 kg (4 WD = 658 kg)
==Bereifung==
"Standardbereifung"
* Vorne = 4.00-12 AS Front (4 WD = 5.00-14 AS)
* Hinten = 8.00-18 AS
==Füllmengen==
* Tankinhalt = 14,0 l
* Motoröl incl. Filter = 2,2 l
* Kühlsystem = 3,0 l
* Triebwerk, Hydraulik und Differential = 17,0 l
* Differential 4 WD = 1,5 l
* Endantrieb 4 WD je 4,0 l
==Verbrauch==
==Kabine==
* Fahrerstand mit Schutzrahmen, gepolsterter Sitz, Lade- und Öldruckanzeige, Kraftstoffanzeige und Temperaturanzeige
==Sonderausrüstung==
* Radgewichte
==Literatur & Weblinks==
* Allis-Chalmers Agricultural Equipment Brochure
* tractorbook.de
* TractorData.com
<references />
{{:Traktorenlexikon: Navigation |HERSTELLER-LINK=Traktorenlexikon: Allis-Chalmers |HERSTELLER= Allis-Chalmers}}
fk13j6fgdfemmjhxteq9bx55j8was4n