Hallo Gemeinde Kann mir jemand erklären, warum mann bei Variablen Deklarationen in BeispielCode oft zB "uint8_t" statt "char" lesen kann ? Weil es in der " stdint.h" so definiert ist ! Ja! Aber warum weicht diese vom C-Standard ab ? Danke Torsten
Gast
#3021061
Torsten B. schrieb: > BeispielCode oft zB "uint8_t" statt "char" lesen kann ? weil für char nicht mal festgelegt ist ob es signed oder unsigned ist.
Gast
#3021064
Also ich benutze uint8_t für Variablen, die Zahlen aufnehmen und char für welche die Zeichen aufnehmen. Dem µC bzw. Compiler ist das wohl total egal, aber ich finde es einfach passender z.B. die Laufvariable i als uint8_t zu deklarieren als als char...
Weil ein uint8_t unsigned ist. Und vor allem, weil ein uint8_t auf den ersten Blick deutlich macht, wie groß der Datentyp ist. Gerade bei plattformübergreifender Entwicklung ist das wichtig. Nicht überall ist ein int 32 Bit groß.
Gast
#3021073
Ronny Spiegel schrieb: > Weil ein uint8_t unsigned ist. was sagt das?
Torsten B. schrieb: > Kann mir jemand erklären, warum mann bei Variablen Deklarationen in > BeispielCode oft zB "uint8_t" statt "char" lesen kann ? uint8_t exakt 8 Bits ohne Vorzeichen. uint_fast8_t mindestens 8 Bits ohne Vorzeichen, laufzeitoptimiert. char Zeichen mit oder ohne Vorzeichen, 8 oder mehr Bits. Bei plattformunabhängigem Code ist also uint_fast8_t sinnvoll, da uint8_t bei 16/32-Bit Prozessoren ineffizient sein kann.
Torsten B. schrieb: > Kann mir jemand erklären, warum mann bei Variablen Deklarationen in > BeispielCode oft zB "uint8_t" statt "char" lesen kann ? Hab ich noch nie gesehen, zeig mal ein Beispiel. "uint8_t" hab ich nur statt "unsigned char" gesehen und da spart es deutlich Schreibarbeit.
Peter II schrieb: > Ronny Spiegel schrieb: >> Weil ein uint8_t unsigned ist. > > was sagt das? Es stimmt, wenn damit wortwörtlich "ohne Vorzeichen" gemeint ist, nicht der Typ "unsigned int".
Vervollständigt: uint8_t exakt 8 Bits ohne Vorzeichen. uint_fast8_t mindestens 8 Bits ohne Vorzeichen, laufzeitoptimiert. uint_least8_t mindestens 8 Bits ohne Vorzeichen, platzoptimiert. char Zeichen mit oder ohne Vorzeichen, 8 oder mehr Bits. uint_least8_t ergibt Sinn, wenn man eines Tages in Gefahr läufen könnte, eine Maschine zu erwischen, die keinen 8-Bit Datentyp unterstützt und folglich uint8_t nicht kennt.
Also das versteh ich nicht. Ein char ist definiert als ein Zeichen (Byte) welches genau 8 Bit hat. Mir ist noch nie untergekommen dass ein char signed sein könnte. Vorallem wäre mal interessant: Wer kommt denn auf die Idee ein signed char zu verwenden? Und vorallem: Wo??
Florian Trück schrieb: > Also das versteh ich nicht. Ein char ist definiert als ein Zeichen > (Byte) welches genau 8 Bit hat. Mir ist noch nie untergekommen dass ein > char signed sein könnte. Was nicht heißt, das es das nicht gibt. Du brauchst nur den gcc mit der entsprechenden Option aufrufen und schon sind deine char alle signed.
Karl Heinz Buchegger schrieb: > Was nicht heißt, das es das nicht gibt. > Du brauchst nur den gcc mit der entsprechenden Option aufrufen und schon > sind deine char alle signed. Das mag ja sein, aber wozu braucht man ein signed char mit dem Wertebereich (-127) - (127) ?
Florian Trück schrieb: > Ein char ist definiert als ein Zeichen > (Byte) welches genau 8 Bit hat. Nein. > Mir ist noch nie untergekommen dass ein char signed sein könnte. Das war früher ziemlich verbreitet und ist irgendwo bestimmt noch so. > Vorallem wäre mal interessant: Wer kommt denn > auf die Idee ein signed char zu verwenden? Die erste C Implementierung, also die auf einer DEC PDP-11. Deren 8-Bit Operationen arbeiteten nämlich implizit mit Vorzeichen. Bei nachfolgenden Implementierungen wurde es lange Zeit ebenso gehandhabt, auch wenn es ohne Vorzeichen sinnvoller gewesen wäre.
Florian Trück schrieb: > Karl Heinz Buchegger schrieb: >> Was nicht heißt, das es das nicht gibt. >> Du brauchst nur den gcc mit der entsprechenden Option aufrufen und schon >> sind deine char alle signed. > > Das mag ja sein, aber wozu braucht man ein signed char mit dem > Wertebereich (-127) - (127) ? Es geht nicht darum, ob du oder ob man das braucht. Es geht darum, was dein Compilerbauer für eine gute Idee auf einer bestimmten Plattform gehalten hat, bzw. was die CPU an Assemblerbefehlen mitbringt. Im Ernst. Wo liegt denn das Problem? uint8_t für 'kleine Zahlen' ohne Vorzeichen. (Im Volksmund auch Byte genannt) int8_t für 'kleine Zahlen' mit Vorzeichen. zb Schleifensteuerungen die auch mal negativ werden können char für alles was mit Textverarbeitung zu tun hat. Ist doch ganz einfach. Und zusätzlich hat man auch noch im Programm eine schöne Trennung, wo man es mit Textverarbeitung und wo man es mit Bytes im weitesten Sinne zu tun hat. Denn Textverarbeitung impliziert zusätlich noch, dass Strings eine terminierende \0 enthalten.
Gast
#3021141
Florian Trück schrieb: > Mir ist noch nie untergekommen dass ein > char signed sein könnte. im gcc ist es immer signed
1 | |
2 | |
3 | |
4 | |
5 | |
na was kommt raus?
Gast
#3021142
Florian Trück schrieb: > Also das versteh ich nicht. Ein char ist definiert als ein Zeichen > (Byte) welches genau 8 Bit hat. Mindestens 8 Bit. Es könne nauch mehr sein. Florian Trück schrieb: > Mir ist noch nie untergekommen dass ein > char signed sein könnte. Vorallem wäre mal interessant: Wer kommt denn > auf die Idee ein signed char zu verwenden? Und vorallem: Wo?? Da ASCII nur ein 7-Bit Code ist, reicht das signed da vollkommen aus. Es ist im C-Standard nicht festgelegt ob char signed oder unsigned ist. Ich erinnere mich auch an keinen Compiler, der unsigned wäre. (oder es ist sooo lange her)
Florian Trück schrieb: > Das mag ja sein, aber wozu braucht man ein signed char mit dem > Wertebereich (-127) - (127) ? Man braucht es genauso dringend, wie einen Knopf an der Backe, aber es wurde von den C-Erfindern nun einmal so festgelegt. Es fällt einem auch regelmäßig auf die Nase, z.B. wenn man in einem Stream Text und Zahlenwerte überträgt bzw. manche Programme können deshalb keine Zeichen >127 darstellen.
Florian Trück schrieb: > Also das versteh ich nicht. Ein char ist definiert als ein Zeichen > (Byte) welches genau 8 Bit hat. Mir ist noch nie untergekommen dass ein > char signed sein könnte. Vorallem wäre mal interessant: Wer kommt denn > auf die Idee ein signed char zu verwenden? Und vorallem: Wo?? Der Visual Studio Compiler, den ich in der Arbeit verwende(n muss). Ein char x = 254; spuckt eine entsprechende Warnung aus, wohingegen char x = -12; anstandslos funktioniert. Mit Typdefinitionen, die explizit angeben, ob ein Typ vorzeichenbehaftet ist oder nicht, treten solche Sachen gar nicht erst auf.
Gast
#3021150
Hey Ho, Ich weiß von Atmel Studio 6 das dort ein char default mäßig als unsigned char betrachtet wird, kann man aber in den Projekteinstellungen ändern. Ich benutze in meinen Projekten für 1-Byte Variablen immer den char-Typ und hatte damit noch nie Probleme. Und das bisschen was man da an Schreibarbeit sparen könnte...naja, ist wohl ansichts sache. ;) In .Net soll ein char wohl 16-Bit haben. Ich glaube allerdings das wir uns hier auf C/C++ beziehen. Weiterhin denke ich das "Platformunabhängigkeit" auf einem µC ziemlich Latte ist, solange man sicht nicht auf der Himbeere befindet bzw. sonst irgendein OS benutzt. In diesem Sinne, Grüße
Ronny Spiegel schrieb: > Der Visual Studio Compiler, den ich in der Arbeit verwende(n muss). Ein > > char x = 254; > > spuckt eine entsprechende Warnung aus, wohingegen > > char x = -12; > > anstandslos funktioniert. > > Mit Typdefinitionen, die explizit angeben, ob ein Typ vorzeichenbehaftet > ist oder nicht, treten solche Sachen gar nicht erst auf. Auf die Nase fällt man zb dann, wenn der char in einem Vergleich vorkommt. Denn da spielt es dann eine Rolle char c = 254; if( c == 254 ) printf( "juhu" ); auf einem Compiler, bei dem ein char signed ist, wird der if nie genommen. Und das Rätselraten ist groß, warum nicht. Mit expliziten uint8_t, int8_t, char (je nach Anwendungszweck) gibt es diese Probleme erst gar nicht.
Gast
#3021161
Kaj schrieb: > In .Net soll ein char wohl 16-Bit haben. Nicht nur da. Verwende z.B. mal die Piccolo-Serie von TI! Da ist das kleinste was Du bekommst eine 16 Bit Variable ;-)
Peter Dannegger schrieb: > Man braucht es genauso dringend, wie einen Knopf an der Backe, aber es > wurde von den C-Erfindern nun einmal so festgelegt. Es war nicht festgelegt. Von Anfang an war offen, ob char mit oder ohne Vorzeichen implementiert ist. Es war einfach nur üblich, weil "schon immer so gemacht".
Kaj schrieb: > denke ich das "Platformunabhängigkeit" auf einem µC ziemlich Latte ist, Würde ich nicht sagen. Beispiel: Im Code für den Temperatursensor DS18S20 ist ausschliesslich die Pinwackelei direkt hardwareabhängig, und das sind sehr wenige Operationen. Folglich kann fast der gesamte Code wiederverwendet werden.
Schon mal überlegt, warum
char c;
while( (c = getchar()) != EOF )
...
in C überhaupt wie angedacht funktioniert?
wenn c ein unsigned char wäre, funktioniert es nämlich nicht mehr :-)
Es funktioniert so auch nicht wie angedacht, egal ob signed oder nicht.
Der korrekte und überall zu findende Code ist
int c;
while( (c = getchar()) != EOF )
...
und genau dieser Aspekt gehört m.W. zum Grundwissen in C. Dass getchar
bei den üblichen Plattformen tatsächlich 257 mögliche Werte zurück gibt
und solche Zeichen deshalb nicht als char definiert werden dürfen.
Die Perversion dabei ist, dass auf Plattformen, bei denen "char" mit
Vorzeichen definiert und EOF dennoch wie üblich -1 ist, getchar() die
Werte 0..255 zurück gibt, nicht -128..127.
Wirklich verstehen muss man das nicht. Einfach akzeptieren. ;-)
Peter II schrieb: > Florian Trück schrieb: >> Mir ist noch nie untergekommen dass ein >> char signed sein könnte. Vermutlich sitzt du genau in diesem Augenblick vor einem Rechner bei dem das genau so ist. > > im gcc ist es immer signed Das hat nichts mit gcc zu tun, sondern mit der Platform. x86 und x86_64 haben z.B. üblicherweise signed char, während ARM, MIPS und PowerPC unsigned char haben. Der Grund für solche Unterschiede sind z.T. historisch und oftmals Performancefragen. Einige Architekturen müssten z.B. Konvertierungen durchführen um chars auf eine andere Weise zu unterstützen. In C/C++ sind die Eigenschaften der intrinsischen Datentypen aus Performancegründen von der zugrundeliegenden Architektur bestimmt und man geht normalerweise davon aus, dass ein kompetenter Programmierer mit signenness/unsignedness von char, den plattformspezifischen Größen von short, int, long und all dem anderen Kram umgehen kann.
A. K. schrieb: > Es funktioniert so auch nicht wie angedacht, egal ob signed oder nicht. Ja, ok. 'funktioniert' ist zu hoch gegriffen. Aber bei 7-Bit ASCII und signed char kommt man damit durch. (Nicht das ich das propagieren würde. Gott bewahre.)
Korrektur: MIPS hat unter Debian und NetBSD signed char. Sparc hat ebenfalls signed char, s390 dagegen unsigned char.
Nochn schönes Beispiel für die "signed char" Fallgrube ist auch das Ummappen der deutschen Umlaute für ein LCD. Wenn man nicht nach unsigned castet, funktioniert es nicht. Wenn man aber zur Umgehung all dieser Probleme die Stringpuffer als unsigned anlegt, meckert einem der AVR-GCC ständig die Hucke voll.
Gast
#3021329
Torsten B. schrieb: > Aber warum weicht diese vom C-Standard ab ? Zum Rest wurde ja schon alles gesagt, aber man sollte vielleicht noch erwähnen, dass stdint.h und damit uint8_t natürlich voll und ganz dem C-Standard entsprechen. Das ist ja gerade das schöne, dass man endlich mal ohne große Verrenkungen Datentypen hat, bei denen man sich drauf verlassen kann, dass sie einen klar bestimmten numerischen Umfang und Platzbedarf haben. Bei "char" drängt sich einem das noch nicht so auf, wobei signed-vs.-unsigned auch ein echtes Arschloch sein kann. Noch viel mehr Spaß hat man mit "int" und "long". Ob das dann 32 oder 64 oder gar nur 16 Bit sind, hängt von CPU, Betriebssystem, 32-/64-Bittigkeit des Betriebssystems, gewähltem Speichermodell (x86/x86_64/x32) und der Mondphase ab. Und weil der ursprüngliche C-Standard absichtlich so viele Unwägbarkeiten enthielt (man dachte das ist ne super Idee: jede Plattform nimmt was am "besten" für sie ist), und man gelernt hat, dass der Ansatz nicht so toll funktioniert wie man dachte, gibt es eben inzwischen die zusätzlichen Datentypen in stdint.h.
Ich schreibe uint8_t, weil ich die Trivialnamen hasse. Man sieht sofort, dass das 8bit sind. mf
Florian Trück schrieb: > Mir ist noch nie untergekommen dass ein char signed sein könnte. Mir schon oft. Ist auch konsistenter, da alle anderen Integer-Typen ja auch signed sind, wenn nicht explizit ein 'unsigned' davor steht. Da man damit aber eh niemals rechnet, sondern nur Zeichen drin abspeichert, ist es auch völlig wurscht, ob's nun signed oder unsigned ist. Peter Dannegger schrieb: > Nochn schönes Beispiel für die "signed char" Fallgrube ist auch das > Ummappen der deutschen Umlaute für ein LCD. Wenn man nicht nach unsigned > castet, funktioniert es nicht. > > Wenn man aber zur Umgehung all dieser Probleme die Stringpuffer als > unsigned anlegt, meckert einem der AVR-GCC ständig die Hucke voll. Deswegen macht man das ja auch nicht so. Alle Stringpuffer sind char. Und an einer einzigen Stelle, wo man den Wert dann in ein Register schreibt, macht man die Konvertierung. Es gibt eben getrennte Typen für "Zeichen" und für "Bytes", und char ist eben der Typ ausschließlich für Zeichen. Das ist auch keine Eigenheit von C. Auch bei den meisten anderen Sprachen muß ich eine Konvertierung durchführen, wenn ich ein Zeichen habe und dieses als Bytewert nutzen will. Wenn in C unsigned char und signed char stattdessen unsigned byte und signed byte heißen würden, char ohne signed und unsigned aber seinen Namen behalten würde, wäre das wahrscheinlich jedem sofort klar. Joachim минифлоть schrieb: > Ich schreibe uint8_t, weil ich die Trivialnamen hasse. Man sieht sofort, > dass das 8bit sind. mf Allerdings gibt es den Fall, daß die Variable zwingend exakt 8 Bit groß sein muß, gar nicht so oft.
Gast
#3021932
Sam P. schrieb: > Und weil der ursprüngliche C-Standard absichtlich so viele > Unwägbarkeiten enthielt (man dachte das ist ne super Idee: jede > Plattform nimmt was am "besten" für sie ist), und man gelernt hat, dass > der Ansatz nicht so toll funktioniert wie man dachte, gibt es eben > inzwischen die zusätzlichen Datentypen in stdint.h. Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist, egal auf welcher Maschine. Diese an den Haaren herbeigezogenen Pseudotypen 'x'int'n'_t sind eklig zu lesen und kein Compiler kennt sie wirklich. stattdessen werden sie per #define überall wieder vom Preprozessor auf die althergebrachten Typen char, int, long zurückübersetzt, bevor der Compiler sie zu lesen bekommt. Wozu also dieser unleserliche Mumpitz? Wenn überhaupt, wäre das ne Sache, die als echter Datentyp direlt in den Compiler gehört hätte. Aber laßt mal, woanders wird mittlerweile der gleiche Murks gemacht. Siehe 'char' und chr(x) im aktuellen Delphi XE3. Wahrscheinlich haben dort auch C-Programmierer angefangen... W.S.
Du solltest auf PL/I umsteigen. ;-) http://www.uni-muenster.de/ZIV.EberhardSturm/PL1andC.html
W.S. schrieb: > Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits > existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit > man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist, > egal auf welcher Maschine. Tja. Das 'Problem' mit den ISO-Gremien ist, dass sie nichts mehr ändern (oder nur mit vorgehaltener Waffe), wenn etwas mal im Standard steht. Die Idee war es halt, dass ein int sowas wie die Leib- und Magengröße einer CPU sein sollte. Gewisse Mindeststandards werden garantiert. Alles was darüber hinausgeht, legt der Compilerbauer und/oder die CPU fest. War nicht unbedingt die stärkste Idee, ermöglicht aber auf der anderen Seite Programme (die sich nur auf die zugesicherten Mindesteigenschaften verlassen), vom kleinen 8-Bitter bis hinauf zu einem Supercomputer unverändert laufen zu lassen und auf jeder Maschine wird der jeweils schnellste Code dafür erzeugt.
W.S. schrieb: > Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits > existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit > man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist, > egal auf welcher Maschine. Es gibt auch DSPs mit 24 Bit natürlicher Wortbreite. Darauf wäre C dann nicht mehr sinnvoll möglich. > Diese an den Haaren herbeigezogenen Pseudotypen 'x'int'n'_t sind eklig zu > lesen Ich finde sie eigentlich sehr gut zu lesen, weil der Name schon genau verrät, was es ist. > und kein Compiler kennt sie wirklich. Das ist aber die Schuld der Compiler-Hersteller und nicht die von C. Dort ist das seit 14 Jahren bereits genormt, und jeder ISO-konforme Compiler muß das mit dabei haben. > Wenn überhaupt, wäre das ne Sache, die als echter Datentyp direlt in den > Compiler gehört hätte. Wozu? Welchen Vorteil hätte das denn?
Rolf Magnus schrieb: > Wozu? Welchen Vorteil hätte das denn? Ich hatte oben nicht zufällig PL/I genannt. Da wird die Genauigkeit per Stellenzahl direkt in die Deklaration geschrieben. Wenn man also eine binäre Variable mit 13 Bits ohne Vorzeichen braucht, dann schreibt man das einfach da rein: dcl x fixed bin(13) unsigned; Was der Compiler intern daraus macht ist dann seine Sache. Dummerweise waren PL/I Compiler anfangs äusserst unhandliche Kolosse, weil da noch ein paar mehr gute und schlechte Ideen drin sind. So wie Unix als Gegenentwurf zu Multics entstand - was in PL/I programmiert war - entstand C als Gegenentwurf zu PL/I. Als Sprache, die auch auf kleinen Computern umgänglich war, grad wie Unix ein Betriebssystem für kleine Computer war. PS: Ich finde PL/I insgesamt grauslich. Aber es illustriert den Punkt.
Gast
#3022124
Joachim минифлоть schrieb: > Ich schreibe uint8_t, weil ich die Trivialnamen hasse. Man sieht sofort, > dass das 8bit sind. mf Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t", sondern nur U8, S8, U16 ...
Gast
#3022125
_t schrieb: > Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t", > sondern nur U8, S8, U16 ... wie wie sehen signed aus?
Gast
#3022143
W.S. schrieb: > Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits > existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit > man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist, > egal auf welcher Maschine. Sie haben eine saubere Bedeutung, nur nicht die, die du gerne hättest. "int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll auf dieser Machine arbeiten kann." Weder macht es Sinn, einen 8-Bit-µC zu 32 Bit ints zu zwingen, noch bringt es irgendeinen Vorteil, Rechner mit vielen Gigabytes RAM (und entsprechend vielen Datensätzen etc. im Programm) bei 65535/32767 zu deckeln. Die Grundidee hinter "int" ist gut, sie macht nur nicht das, was viele damit versuchen zu erreichen. Aber es gibt da diese anderen Datentypen im C-Standard, die ebenfalls eine saubere Bedeutung haben und so definiert sind wie du es möchtest. Wie hiessen die nur nochmal? > Diese an den Haaren herbeigezogenen > Pseudotypen 'x'int'n'_t sind eklig zu lesen und kein Compiler kennt sie > wirklich. stattdessen werden sie per #define überall wieder vom > Preprozessor auf die althergebrachten Typen char, int, long > zurückübersetzt, bevor der Compiler sie zu lesen bekommt. stdint.h ist integraler Bestandteil der C-Laufzeitumgebung. Es sind keine Pseudotypen und es findet keine Textersetzung im Präprozessor statt. Es sind ordentlich per typedef definierte Typen, die genau auf den Compiler zugeschnitten sind. Nur weil man eine Headerdatei einbinden muss, ist das noch lange kein Fremdkörper. Nenne mir eine Sprache, in der du nicht einige Bestandteile der Standard-Laufzeitumgebung über eine Import-Deklaration einbinden musst, wenn du sie nutzen willst. Dein offenbar bevorzugtes Delphi macht es doch nicht anders. > Wozu also > dieser unleserliche Mumpitz? Wenn überhaupt, wäre das ne Sache, die als > echter Datentyp direlt in den Compiler gehört hätte. Ich finde ein 16-Bit "int" ziemlich unleserlich. Selbst beim ATMega, wo 16-Bit-int Sinn macht, hab ich mich manchmal ertappt, wie ich ungewollt einen Overflow produziert habe. Ein int16_t zeight dagegen deutlich und direkt, was man da gerade deklariert. Es ist standardisiert, jeder Compiler aus diesem Jahrtausend versteht es, und es bedeutet immer das gleiche. Viel schlimmer ist die Pest an Bibliotheken und APIs, die alle noch nicht begriffen haben, dass es stdint.h gibt und überall funktioniert, und dann hat man in einem einzigen Programm plötzlich 4 verschiedene Namen plus "int" für eine vorzeichenbehaftete 32-Bit-Ganzzahl. Das ist unleserlich... _t schrieb: > Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t", > sondern nur U8, S8, U16 ... ... dankeschön. Hoffentlich muss ich nie deinen Code warten.
Gast
#3022145
Peter II schrieb: > _t schrieb: >> Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t", >> sondern nur U8, S8, U16 ... > > wie wie sehen signed aus? _t schrieb: > sondern nur U8, S8, U16 ... ^^
Gast
#3022195
Ein ganzer Sack voll Irrtümer resultiert aus der Unkenntnis der C-Datentypen. Das ist allerdings verständlich, da der Hauptdatentyp von "C" ein Witz ist. Ich musste mal lernen: Integer ist der "natürliche" Datentyp des Rechners. Keine Ahnung ob es zu 4 Bit-Zeiten auch schon jemanden mit Namen Integer gab. Anno 8080/86/186 (Z80, 68xx und wie sie alle hießen) waren das 8 Bit. Später bekamen "Rechners" Zuwachs und das Kind war plötzlich 16 Bit breit. Das hüpfende Komma aber war - das Baby hieß auch Integer. Irgendwo war hier die Phantasie in Sachen Namensgebung verschütt jegangen. Heute streiten sich die Gelehrten, ob dem Baby die 32-er oder die 64-er Klamotten passen - es geht natürlich um (Trommelwirbel) Integer. Etwas aber hat all das Überlebt und das ist der Datentyp char. Ohne Vornamen oder mit signed davor ist er von -128 über 0 bis 127 spezifiziert. Heißt er aber unsigned, so geht er von 0 bis 255. Damit das Ganze aber nicht so langweilig wird wurden, z.T. weil man bestimmte Genauigkeiten benötigte, immer neue Datentypen geschaffen. Vielleicht aber auch, weil man sich die ganzen Namen nicht mehr merken konnte. byte, short, word, longint u.s.w. Zum Teil mit, zum Teil ohne Vornamen. Damit der Begriff: "Lebenslanges Lernen" auch mit Inhalt gefüllt wird, sind dann die Hardwarenahen Buben und Mädels dazu übergegangen so "C"-Krücken wie "uint8_t" oder "uint16_t" in die Welt zu setzen. Keine Ahnung ob sie das Benötigten oder ob sie glaubten das wir alle von Alzheimer befallen sind. Also beteiligen Sie sich alle an dem Wettbewerb: "Wer findet einen Begriff für den neuen Datentypen mit 127 Bit Breite plus Zusatzzahl".
amateur schrieb: > Ohne Vornamen oder mit signed davor ist er von -128 über 0 bis 127 > spezifiziert. Ohne Vornamen ist nicht spezifiziert ob signed oder unsigned. Zudem gibt es mittlerweile 3 formal verschiedene char Typen, nämlich char signed char unsigned char wovon zwar 2 einen identischen Wertebereich haben, aber dennoch als separate Typen behandelt werden. Was bei Pointern eine Rolle spielt: char c; signed char *scp = &c; unsigned char *ucp = &c; führt mit -Wall zu 2: warning: pointer targets in initialization differ in signedness 3: warning: pointer targets in initialization differ in signedness
Gast
#3022245
@A.K. Ich habe in meinem ganzen Leben noch keinen signed char verwendet. Dafür sind mir meine Fingerkuppen einfach zu schade. Aus diesem Grunde stellt sich das Problem, für mich, auch nicht. Natürlich: Wenn ich dem einen Kind den Namen "Hans" gebe und dem Anderen den Namen "Karl", so muss der Compiler meckern, wenn ich die Behauptung aufstelle: Hans = Karl; Für mich gilt aber, bis zum Beweis des Gegenteils: char = signed char; Egal was ein Compiler dazu zu sagen hat.
amateur schrieb: > Ein ganzer Sack voll Irrtümer resultiert aus der Unkenntnis der > C-Datentypen. Wie du gerade eindrucksvoll unter Beweis stellst.
Gast
#3022261
amateur schrieb: > Ich musste mal lernen: Integer ist der "natürliche" Datentyp des > Rechners. Du möchtest also keinen Datentyp haben, der für die Zielmaschine optimal ist und als allgemeiner Ganzzahl-Datentyp sinnvoll bzw. ausreichend ist? amateur schrieb: > Anno 8080/86/186 (Z80, 68xx und wie sie alle hießen) waren das 8 Bit. Nicht für C. Ein "int" ist schon immer wenigstens 16 Bit gewesen, darf aber beliebig groß werden. 8 Bit "int" wäre dann doch etwas zu nutzlos. amateur schrieb: > Damit der Begriff: "Lebenslanges Lernen" auch mit Inhalt gefüllt wird, > sind dann die Hardwarenahen Buben und Mädels dazu übergegangen so > "C"-Krücken wie "uint8_t" oder "uint16_t" in die Welt zu setzen. Keine > Ahnung ob sie das Benötigten oder ob sie glaubten das wir alle von > Alzheimer befallen sind. Du möchtest also nicht in der Lage sein, Präzision bzw. Speicherbedarf von Daten genau spezifizieren zu können, wenn es nötig ist? Junge, junge, was du dir wohl für Datentypen wünschst. Leider kannst du dir für den 8080 nix mehr wünschen, die Geschichte ist geschrieben. Aber wenn wir dann die Zeitmaschine erfinden, dann kannst du es ja besser machen. 64-Bit Integer sind auf dem 4004 bestimmt ein Kassenschlager. Ach was, ich steig da selbst rein und erfinde für C einfach ein Haufen Typen die klar definiert sind, in offiziellen Standards, die aber keiner liest. Ich nenn die dann "int", "short" und so weiter, nur um dich zu ärgern. :)
Gast
#3022265
amateur schrieb: > Ohne Vornamen oder mit signed davor ist er von -128 über 0 bis 127 Ach so, verlass dich auf die "-128" nicht allzusehr. Nirgendwo wird verlangt, dass negative Zahlen im Zweierkomplement dargestellt werden. Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann nicht mehr funktioniert, aber erlaubt wäre es. Und auf irgendwelchen speziellen µCs/DSPs mag das sogar seinen Sinn haben.
amateur schrieb: > Für mich gilt aber, bis zum Beweis des Gegenteils: char = signed char; > Egal was ein Compiler dazu zu sagen hat. Lol. Interessante Herangehensweise. Sam P. schrieb: > Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht > natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann > nicht mehr funktioniert, aber erlaubt wäre es. Warum sollten Programme dann nicht mehr funktionieren?
Gast
#3022440
>Du möchtest also nicht in der Lage sein, Präzision bzw. Speicherbedarf >von Daten genau spezifizieren zu können, wenn es nötig ist? Es werden ja keine neuen Datentypen geschaffen sondern neue Namen. Wenn ich mal die Krabbelkommazahlen außen vor lasse, hat sich seit char, word, int oder longint nichts neues mehr ergeben. Konstrukte wie uint8_t, uint16_t oder der große Bruder uint32_t sind ja nix als neue Namen für alte Kollegen.
amateur schrieb: > uint8_t, uint16_t oder der große Bruder uint32_t sind ja nix als neue > Namen für alte Kollegen. Ja und? Was machen Schlüsselworte besser als Typedefs?
Rolf Magnus schrieb: > Warum sollten Programme dann nicht mehr funktionieren? Die negative Null dürfte für gewisse Irritationen gut sein.
"Ach so, verlass dich auf die "-128" nicht allzusehr. Nirgendwo wird verlangt, dass negative Zahlen im Zweierkomplement dargestellt werden. Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann nicht mehr funktioniert, aber erlaubt wäre es. Und auf irgendwelchen speziellen µCs/DSPs mag das sogar seinen Sinn haben." Die Frage ist vor allem wieviel zu Bruch geht wenn man die Annahme dass der Zahlenwert 0 intern bei jedem numerischen Typ 0x00/0x0000/0x00000000/... entspricht - und damit selbst bei brutalstem Type Punning einem "false"! - aushebelt.
Kaj schrieb: > In .Net soll ein char wohl 16-Bit haben. Das kommt daher, weil in .NET für Strings normalerweise nicht ASCII zum Einsatz kommt, sondern Unicode bzw. UTF-16. http://de.wikipedia.org/wiki/Unicode http://de.wikipedia.org/wiki/UTF-16
amateur schrieb: >>Du möchtest also nicht in der Lage sein, Präzision bzw. Speicherbedarf >>von Daten genau spezifizieren zu können, wenn es nötig ist? > > Es werden ja keine neuen Datentypen geschaffen sondern neue Namen. Natürlich. Was sollte es auch bringen, komplett neue Typen in die Sprache aufzunehmen, die exakt gleich wie die alten sind, außer daß sie halt andere Namen haben? > Wenn ich mal die Krabbelkommazahlen außen vor lasse, hat sich seit char, > word, int oder longint nichts neues mehr ergeben. Konstrukte wie > uint8_t, uint16_t oder der große Bruder uint32_t sind ja nix als neue > Namen für alte Kollegen. Ein uint32_t ist garantiert 32 Bit groß, ein int nicht.
Gast
#3026019
Sam P. schrieb: > Sie haben eine saubere Bedeutung, nur nicht die, die du gerne hättest. > "int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll auf dieser > Machine arbeiten kann." Weder macht es Sinn, einen 8-Bit-µC zu 32 Bit > ints zu zwingen, noch bringt es irgendeinen Vorteil, Rechner mit vielen > Gigabytes RAM (und entsprechend vielen Datensätzen etc. im Programm) bei > 65535/32767 zu deckeln. Die Grundidee hinter "int" ist gut, sie macht > nur nicht das, was viele damit versuchen zu erreichen. Du hast ne ziemlich seltsame Denkweise, die ich nicht teile. Als Programmierer muß man sich auf die verwendeten Datentypen verlassen können, was in C nicht der Fall ist. Natürlich brauche ich auch auf einem 8 Bit uC 32 Bit Integerzahlen, gelegentlich auch int64, und auch auf der größten und dicksten Maschine ist es öfter als du denkst nötig, Integers bei 16 Bit "zu deckeln", wenn die Daten nämlich in Strukturen hineinpassen müssen, die von anderswo vorgegeben sind. Mir ist ein bissel rätselhaft, wie du zu deinen Auffassungen kommst, deswegen hier ein paar Beispiele, damit du merkst, worum es geht: Fall 1: Ich will das Ergebnis eines ADC's lesen. z.B. AD7714. Kommt bei Leuten, die mit Mikrocontrollern zu tun haben vor, sowas. Was kann ich dazu nehmen? int oder long? Natürlich nehme ich long, weil das am wahrscheinlichsten die 24 Bit aufnehmen kann, die der IC ausgibt. Auf manchen Zielsystemen könnte ich auch int nehmen, aber wer garantiert mir das? Merkst du was? Wohldefinierte Datentypen sind für saubere und portable Programmierung wichtiger als die Befindlichkeit einer Maschine. Fall 2: Ich will Daten auf eine SD-Karte schreiben und muß dazu die SD-Karte ansprechen, also initialisieren, die diversen Parameterblöcke auslesen, dann ein Filesystem aufsetzen usw. Natürlich richtet sich auch hier kein SD-Karten-Hersteller nach den Befindlichkeiten des verwendeten uC und auch kein Filesystem schert sich drum. Ich muß mich also mit meinen Structs nach den Karten richten und nicht umgekehrt. Und jetzt tönst du ""int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll..." Kann man sinnvoll mit so einer verqueren Definition arbeiten? Nee, natürlich nicht. Man muß leider stattdessen nachschauen, wie int, long usw. auf dem konkreten Ziel definiert ist und seine Quelle danach richten, sonst wird nix - insbesondere nix mit Zeigern. Aber damit ist man eben überhaupt nicht portabel, sondern tanzt auf dem Schlappseil. soviel zu der angeblich 'sauberen' Bedeutung. Sam P. schrieb: > stdint.h ist integraler Bestandteil der C-Laufzeitumgebung. Es sind > keine Pseudotypen und es findet keine Textersetzung im Präprozessor > statt. Ach ja? Lies mal (Auszug aus aktueller Yagarto) typedef signed char int8_t ; typedef unsigned char uint8_t ; Du weißt, daß man mit typedef keine Typen definieren kann, ja? Mit typedef kann man - salopp gesagt - einem bereits vorhandenen Typ einen anderen Namen geben. Eben ein Pseudotyp Es ist 'int8_t' für den Compiler also tatsächlich nix anderes als ein schnöder 'signed char' - und wenn du ne inkompatible Verwendung im Quelltext machst, dann lautet die Fehlermeldung etwa so: "Error 123456: cannot convert signed char to blablabla." Da wirst du eben nicht finden "...cannot convert int8_t to blablabla". Was ich gemeint habe wäre, daß genau SOLCHE Zeilen eben nicht mehr vorkommen dürften, sondern sowas wie 'int8_t' als solches vom Compiler verstanden wird. Als echtes Schlüsselwort mit einer Bedeutung, die für ALLE Maschinen gleich ist. Weil man nämlich beim Programmieren Probleme lösen muß und dazu Datentypen benötigt, die den Problemen angepaßt sind. (über den konkreten Namen von sowas läßt sich streiten, 'byte' find ich deutlich besser als 'uint8_t'). Also, hast du es jetzt gerafft? W.S.
W.S. schrieb: > Als Programmierer muß man sich auf die verwendeten Datentypen verlassen > können, was in C nicht der Fall ist. Dann lies das ABI und die Spezifikation der Implementierung! Beispiel: avr-gcc ABI: http://gcc.gnu.org/wiki/avr-gcc#ABI Da steht nämlich drinne, wie groß ein int ist, wie breit ein Zeiger, ob ein char signed ist oder nicht, wie Bitfelder gelayoutet sind, wie Funktionsparameter übergeben wwerden, etc. Und wenn die das mit dem int nicht gefällt, nimm eben in int32_t, int32_fast_t oder int32_least_t. Oder nimm Java oder Assembler wenn dir C nicht passt.
Gast
#3026183
> Dann lies das ABI und die Spezifikation der Implementierung!
Der Murks geht dann los, wenn der Code portiert werden soll. Viel Spaß
beim umwursteln und durchsehen aller Variablen auf richtiges Format. :-(
Ich benutze schon lange kein int und co mehr. Totaler Mist.
int-Hasser schrieb: >> Dann lies das ABI und die Spezifikation der Implementierung! > > Der Murks geht dann los, wenn der Code portiert werden soll. Viel Spaß > beim umwursteln und durchsehen aller Variablen auf richtiges Format. :-( > > Ich benutze schon lange kein int und co mehr. Totaler Mist. Ja was wollt ihr denn? - int etc. ist euch nicht genehm - uint32_t etc. auch nicht - eine andere Spache auch nicht Hauptsache Rummeckern. Wie die Leute die stänfig übers Wetter nörgeln anstatt nach auszuwandern, gescheite Klamotten zu kaufen, sich abzuhärten oder einfach am Kamin sitzen zu bleiben wenn's Wetter nicht passt. Und das niemand mehr Doku, Spezifikation, Spezifikaton der Implementierung, (E)ABI, etc. durchliest -- oder wenigstens nicht bei jeder sich bietenden Gelegenheit seine Unwissenheitsfrust rausposant -- ist im Zeitalter der 1-Click Mentalität wohl als gegeben hinzunehmen...
Gast
#3026335
> Ja was wollt ihr denn? Maoam? :) > uint32_t etc. auch nicht doch - das ist ok. Da weiß man ja was man hat. Es geht ja grade darum, dass man als Programmierer etwas haben will, was eindeutig und unabhängig von der Bitbreite der Zielhardware definiert ist. so kommt es dazu, dass code wie dieser hier auf einem Cortex korrekt funktioniert aber nicht auf einem Atmega (weil dort ein int nur 16 bit hat):
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
Viel Spaß beim Portieren! Hätte man statt int einfach int32_t genommen wäre das nicht passiert und der code wäre ohne änderung portierbar geblieben.
Gast
#3026515
W.S. schrieb: > Du hast ne ziemlich seltsame Denkweise, die ich nicht teile. > Als Programmierer muß man sich auf die verwendeten Datentypen verlassen > können, was in C nicht der Fall ist. Natürlich kann man sich auf "int" verlassen. Nämlich darauf, dass ein "int" relativ effizient in Berechnungen eingesetzt werden kann und dabei nicht unnütz klein ist. Das ist auf jedem System so, das einen gescheiten C-Compiler hat. Selbstverständlich kannst du dich nicht auf etwas verlassen, was gar nicht versprochen wird. "int" verspricht nicht, dass es eine feste Größe hat, aber jeder C-Neuling glaubt, das wäre so. Das ist das (zugegeben unglückliche) Missverständnis. Und darum ist es gut, dass es "jetzt endlich" (seit ~15 Jahren) zusätzliche Typen gibt, die eben eine bestimmte Größe versprechen, dabei aber eventuell langsam sein könnten. > Natürlich brauche ich auch auf > einem 8 Bit uC 32 Bit Integerzahlen, gelegentlich auch int64, und auch > auf der größten und dicksten Maschine ist es öfter als du denkst nötig, > Integers bei 16 Bit "zu deckeln", wenn die Daten nämlich in Strukturen > hineinpassen müssen, die von anderswo vorgegeben sind. Da hast du völlig recht. Darum gibt es int16_t/int32_t/int64_t. short/int/long/long long sind dafür weder gedacht noch geeignet. Guck dir ein beliebiges C-Projekt an, das in irgendeiner Form von genauen Größen abhängig ist und auf wenigstens 2 Plattformen läuft (und wenn's nur Win32 und Win64 sind). Ist die Software nur alt genug, haben die Programmierer genau das gemacht, was mit stdint.h nun vereinheitlicht ist. Keiner, der mal etwas real portieren musste, benutzt int&Co, wenn die genaue Speicherbelegung relevant ist. > Fall 1: Ich will das Ergebnis eines ADC's lesen. z.B. AD7714. Kommt bei > Leuten, die mit Mikrocontrollern zu tun haben vor, sowas. Was kann ich > dazu nehmen? int oder long? Natürlich nehme ich long, weil das am > wahrscheinlichsten die 24 Bit aufnehmen kann, die der IC ausgibt. Auf > manchen Zielsystemen könnte ich auch int nehmen, aber wer garantiert mir > das? Merkst du was? Wohldefinierte Datentypen sind für saubere und > portable Programmierung wichtiger als die Befindlichkeit einer Maschine. long? Wenn du Pech hast, hat ein long auch nur 16 Bit. "Am wahrscheinlichsten"? Seltsame Art zu programmieren. Jemand, der C kann, nimmt einen int32_t, da hast du deine klare Definition. Du willst klar definierte Typen, lehnst aber die klar definierten Typen ab. > Fall 2: Ich will Daten auf eine SD-Karte schreiben und muß dazu die > SD-Karte ansprechen, also initialisieren, die diversen Parameterblöcke > auslesen, dann ein Filesystem aufsetzen usw. Natürlich richtet sich auch > hier kein SD-Karten-Hersteller nach den Befindlichkeiten des verwendeten > uC und auch kein Filesystem schert sich drum. Ich muß mich also mit > meinen Structs nach den Karten richten und nicht umgekehrt. Uh, structs. Ein weiteres Minenfeld. Grobe Faustregel: Bei structs hast du keinerlei Garantien, wo die Variablen landen. Nur die Reihenfolge wird eingehalten. Es gibt Architekturen (z.B. ARMv4), die können auf keine int32_t zugreifen, die nicht auf durch 4 teilbaren Adressen liegen. Auf einem solchen System muss eine
1 | |
2 | |
3 | |
4 | |
8 Bytes lang sein, statt der 6 die man erwarten könnte. Da kann man bei vielen Compilern per #pragma oder _attribute_ etwas anderes erzwingen, aber der ARMv4 kann gar nicht anders. Und darum ist C so schwammig, weil eben die Hardware Vorrang vor der Bequemlichkeit des Programmierers hat. Das ist nicht das was du hören möchtest oder von einer bequemen Programmiersprache erwartest, aber beim hardwarenahen Programmieren geht es eben nicht anders. Hätte man einen Standard verabschiedet, der alle Plattformen über einen Kamm schert, dann wäre das einzige Resultat, dass jede abweichende Plattform einen Scheiss auf den Standard gibt und eigene Regeln erlässt. Das Resultat wäre das gleiche wie jetzt, nur jetzt ist klar standardisiert, wo ein Compiler auf welche Weise abweichen darf, und wo nicht. > Und jetzt tönst du > ""int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll..." > > Kann man sinnvoll mit so einer verqueren Definition arbeiten? Nee, > natürlich nicht. Man muß leider stattdessen nachschauen, wie int, long Da die Definition nicht verquer ist, sondern nur etwas verspricht, was dir egal ist, kann ich sehr gut mit sowas arbeiten. Ich weiss, worauf ich mich bei einem int verlassen kann, und worauf nicht. int64_t verspricht mir etwas anderes, und lässt dafür die Frage nach der Effizienz offen. Meine Schleifenindizes sind ints oder unsigned ints, solange ich nicht aufgrund besonderer Umstände mit besonders großen Zahlen rechnen muss. Meine Arrays sind per uintXX_t genauer spezifiziert, weil dort der Speicherbedarf relevant ist und man "int" da nicht vertrauen kann. > usw. auf dem konkreten Ziel definiert ist und seine Quelle danach > richten, sonst wird nix - insbesondere nix mit Zeigern. Aber damit ist > man eben überhaupt nicht portabel, sondern tanzt auf dem Schlappseil. Eben. Ich verwende ja auch keinen Schraubenzieher als Meissel. Das geht ne Weile gut, für einen Quick&Dirty-Job kommt man auch damit durch, aber irgendwann merkt man, dass ein Meissel andere Versprechen hält als ein Schraubenzieher. > soviel zu der angeblich 'sauberen' Bedeutung. Lies den C-Standard, dann weisst du wie sauber das definiert ist. Du kannst dir gerne ein anderes C herbeiwünschen, aber weder du noch ich machen die Regeln, sondern das ISO-Gremium. Und die sagen klipp und klar, was geht und was nicht geht. > Sam P. schrieb: >> stdint.h ist integraler Bestandteil der C-Laufzeitumgebung. Es sind >> keine Pseudotypen und es findet keine Textersetzung im Präprozessor >> statt. > > Ach ja? Lies mal (Auszug aus aktueller Yagarto) > > typedef signed char int8_t ; > typedef unsigned char uint8_t ; > > Du weißt, daß man mit typedef keine Typen definieren kann, ja? > Mit typedef kann man - salopp gesagt - einem bereits vorhandenen Typ > einen anderen Namen geben. Eben ein Pseudotyp Es ist aber kein Präprozessor-Makro, es basiert nicht auf Textersetzung, es funktioniert wie jedes andere Symbol auch. Damit hält es sich an alle Regeln der Sprache und ist für den Programmierer ununterscheidbar von einem vom Compiler vordefinierten Typ. Wie das unter der Haube realisiert wird, ist doch vollkommen egal. Schreib dir halt einen Patch für deinen Compiler, der "uint8_t" intern definiert, sobald er die magische Zeile "#include <stdint.h>" liest. Die interne Datenstruktur, die du dabei anlegst, wird bis auf den Namen exakt die von "signed char" sein. Und nun rate mal, was bei einem typedef passiert. Genau das gleiche. > Es ist 'int8_t' für den Compiler also tatsächlich nix anderes als ein > schnöder 'signed char' - und wenn du ne inkompatible Verwendung im Och, "char" könnte ja auch 16 Bit haben. Kein Compilerhersteller wäre so verwegen, aber erlaubt wäre es. Dann wäre "int8_t" irgendwas anderes als "char", z.B. ein interner 8-Bit-Datentyp. > Quelltext machst, dann lautet die Fehlermeldung etwa so: > "Error 123456: cannot convert signed char to blablabla." > Da wirst du eben nicht finden "...cannot convert int8_t to blablabla". Das liegt an deinem Compiler, nicht am C-Standard. Meiner ist so hilfreich und nennt sowohl den verwendeten Typennamen, als auch die zugrundeliegende Definition des Typen. Das ist sogar noch hilfreicher, weil ich damit zusätzliche Informationen zur impliziten Typumwandlung bekommen (gleich der nächste Fettnapf-Klassiker für C-Neulinge). Ich gebe dir recht, dass Compiler-Fehlermeldungen einem das Leben schon schwer machen können. Ich habe z.B. C++ STL lange gehasst, wegen der undurchschauberen Fehlermeldungen. Aber das ist nicht die Schuld von C(++), sondern des Compiler-Herstellers. Wenn das der einzige haltbare Grund ist, ist das Jammern auf hohem Niveau. > Was ich gemeint habe wäre, daß genau SOLCHE Zeilen eben nicht mehr > vorkommen dürften, sondern sowas wie 'int8_t' als solches vom Compiler > verstanden wird. Als echtes Schlüsselwort mit einer Bedeutung, die für > ALLE Maschinen gleich ist. Weil man nämlich beim Programmieren int8_t ist für alle Maschinen gleichbedeutend, solange wir vom Speicherbedarf reden. Darum gibt es diese Typen doch. Das ist genau das, was du die ganze Zeit herbeisehnst. Klare Ansage, auf jeder Plattform vorhanden, gehorcht überall den gleichen Regeln, ist nicht von anderen Datenypen zu unterscheiden, wo war nochmal das Problem? Ach ja, Compiler-Fehlermeldungen. Nimm demnächst gcc-4.8, der ist so dermaßen ausführlich, dass da niemand mehr auch nur irgendwas missverstehen kann. Der zeigt dir sogar die Quelltext-Zeile mit der genauen Position des Fehlers. Da wo dann "int8_t" steht. Ich hoffe das reicht dir. Wird wohl nicht mehr lange dauern, bis der 4.8er offiziell herausgegeben wird. Die Prereleases funktionieren schon ganz gut. > Probleme lösen muß und dazu Datentypen benötigt, die den Problemen > angepaßt sind. Lautet dein Problem "Messwerte mit Zahlenwerten zwischen 0 und 3 Millarden speichern", dann nimm einen uint32_t pro Messwert. Lautet dein Problem "So viele Messwerte, wie ins RAM passen, in einer Schleife erfassen und abspeichern", dann ist "unsigned int" die einzige sinnvolle Wahl für den Schleifenzähler/Array-Index. uint16_t wäre auf einer 32-Bit-Architektur zu klein, uint32_t wäre auf einem 8-Bitter zu langsam. > Also, hast du es jetzt gerafft? Offensichtlich nicht. Es gibt das was du dir wünschst, wenn auch mit Namen, die deiner Ästhetik nicht ganz entsprechen. Es ist offiziell, es ist überall verfügbar, überall gleich definiert und voll in die Sprache integriert. Willst du jetzt allen Ernstes über Compiler-Fehlermeldungen schmollen, wo ohenhin jeder Compiler-Hersteller tun und lassen kann was er will, und deswegen so eine sinnvolle Einrichtung ablehnen? Rolf Magnus schrieb: > Sam P. schrieb: >> Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht >> natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann >> nicht mehr funktioniert, aber erlaubt wäre es. > > Warum sollten Programme dann nicht mehr funktionieren? Sehr viel Code macht Annahmen über die konkreten Bitmuster, die einer bestimmten Zahl entsprechen. Heutzutage gibt es bei Integern den Quasi-Standard "Zweierkomplement", der auch viel Sinn macht. Aber nirgendwo steht geschrieben, dass das in C unbedingt so sein muss. "~0" kann entweder "-1" oder "-0" sein. "-0" alleine ist schon kurios (gibts bei Fliesskomma immer noch). "(-1) << 1" ist -2, -3 oder +2, je nachdem ob man Zweierkomplement, Einerkomplement oder "positive Zahl plus Vorzeichenbit" hat. -127 - 1 als int8_t kann -128, +127 oder +0 sein. Darum ist Überlauf bei vorzeichenbehafteten Zahlen in C auch offiziell undefiniert. Das ändert aber nichts an der Realität, dass ganz oft damit gearbeitet wird. Gerade die Shift-Operatoren werden gerne als angeblich effiziente Multiplikation/Division verwendet, wo doch jeder Compiler der letzten 10 Jahre ein "* 4" automatisch zu einem "<< 2" umschreibt, dabei aber die Zahlenformate korrekt berücksichtigt. Für ein ganz perverses Beispiel von Bitmuster-Hacking google mal nach 0x5f3759df. Nu is aber gut, das ist ja furchtbar lang. Ich hoffe, die Ausführlichkeit hat wenigstens zu etwas Erkenntnisgewinn beigetragen.
Gast
#3026524
U8 S8 U16.... ist bei Silabs sehr gebräuchlich und keines wegs schlecht zu verstehen, habe das auch schon bei anderen gesehen... glaube auch bei peda :-)
Sam P. schrieb: > long? Wenn du Pech hast, hat ein long auch nur 16 Bit. Nein. Muss mindestens 32 Bits haben. > Meine Schleifenindizes sind ints oder unsigned ints, solange ich nicht > aufgrund besonderer Umstände mit besonders großen Zahlen rechnen muss. Yep. Konsequente Verwendung von [u]intNN_t mit NN <= 16 kann zu recht ineffizientem Code führen, da mangels entsprechender Operationen bei RISCs wie ARM immer wieder das Resultat auf NN Bits reduziert werden muss. Offiziell sind dafür deshalb die Typen [u]int_fastNN_t vorgesehen, aber an Stelle von [u]int_fast16_t kann man für lokale Variablen de fakto ebenso gut [unsigned]int verwenden. > Och, "char" könnte ja auch 16 Bit haben. Kein Compilerhersteller wäre so > verwegen, aber erlaubt wäre es. Dann wäre "int8_t" irgendwas anderes als > "char", z.B. ein interner 8-Bit-Datentyp. In diesem Fall würde int8_t wahrscheinlich nicht geben. Diesen Typ gibt es nur, wenn ein Typ mit exakt 8 Bits überhaupt existiert.
Gast
#3026549
Peter II schrieb: > im gcc ist es immer signed > #include <stdio.h> > int main() { > char c = 0xff; > int i = c; > printf("test:%d\n", i ); > > na was kommt raus? Moin, das heißt nur, das du von C programmieren keine Ahnung hast. Wenn du dem natürlich sagst, dass er es als signed interpretieren soll... versuch mal den Umkehrschluss mit printf("test:%u\n", i ); und int. Das wird dich überraschen. Ich weiß, das ist Uhralt, aber mich hats grad in den Fingern gejukt^^ Grüße,
Gast
#3026584
Nette Diskussion. Wenn jemand int benutzen möchte, soll er das. Man sollte niemanden zu seinem Glück zwingen.
@ Sam P.: Super Beitrag. Damit ist wohl so ziemlich alles abgedeckt, was man zu dem Thema sagen kann. :) A. K. schrieb: > Yep. Konsequente Verwendung von [u]intNN_t mit NN <= 16 kann zu recht > ineffizientem Code führen, da mangels entsprechender Operationen bei > RISCs wie ARM immer wieder das Resultat auf NN Bits reduziert werden > muss. > > Offiziell sind dafür deshalb die Typen [u]int_fastNN_t vorgesehen, aber > an Stelle von [u]int_fast16_t kann man für lokale Variablen de fakto > ebenso gut [unsigned]int verwenden. Auf 8-Bit-Mikrocontrollern reichen für viele Dinge wie Schleifen und Statusvariablen allerdings auch schon 8 Bit. In solchen Fällen ist man mit uint_fast8_t am besten bedient. Dafür gibt es keine Entsprechung in den nativen Typen. Ich bin allerdings auch nicht besonders konsequent bei der Verwendung, wenn ich nicht schon weiß, dass der Code auf mehreren Plattformen laufen muss. Werde dank des Threads da mal wieder genauer drauf achten ... :)
Gast
#3026820
Hallo, habt Ihr bitte einen guten Artikel, aus dem die richtige und sinnvolle Verwendung der verschiedenen Datentypen hervorgeht? Von "uint_fast8_t" hatte ich bis dato leidr noch nicht mal was gehört... aber man lernt ja gerne dazu Danke
A. K. schrieb: >> Meine Schleifenindizes sind ints oder unsigned ints, solange ich nicht >> aufgrund besonderer Umstände mit besonders großen Zahlen rechnen muss. > > Yep. Konsequente Verwendung von [u]intNN_t mit NN <= 16 kann zu recht > ineffizientem Code führen, da mangels entsprechender Operationen bei > RISCs wie ARM immer wieder das Resultat auf NN Bits reduziert werden > muss. Das sieht man besonders häufig bei Code, der aus der 16-Bit Ära überlebt hat — und das ist eher die Regel als die Ausnahme, etwa bei den Automotives. Der Code ist dann gepflastert mit hausbackenen NIH-Typen* wie U16, S16, WORD, sint16 oder uint16. Und selbst [u]int16_t ist da voll exotisch. Auf einem 32-Bit µC bremst knabbert das natürlich merklich an der Performance: Der Code wird langsamer und größer. > Offiziell sind dafür deshalb die Typen [u]int_fastNN_t vorgesehen, aber > an Stelle von [u]int_fast16_t kann man für lokale Variablen de fakto > ebenso gut [unsigned]int verwenden. Die sind mir in freier Wildbahn allerdings noch nie begegnet, was mehrere Gründe haben mag: Mangelndes Wissen der Anwender, Paranoide Coding-Rules, NIH-Attitüden, oder es liegt schlicht und ergreifend kein C99 vor wegen M$-Compiler etc. *) NIH = "Not invented here". Alles was nicht auf unserem Mist gewachsen ist, ist Schrott.
W.S. schrieb: > Du hast ne ziemlich seltsame Denkweise, die ich nicht teile. Die ist nicht seltsam. > Mir ist ein bissel rätselhaft, wie du zu deinen Auffassungen kommst, > deswegen hier ein paar Beispiele, damit du merkst, worum es geht: > > Fall 1: Ich will das Ergebnis eines ADC's lesen. > Fall 2: Ich will Daten auf eine SD-Karte schreiben und muß dazu die > SD-Karte ansprechen, also initialisieren, die diversen Parameterblöcke > auslesen, dann ein Filesystem aufsetzen usw. Beides Lowlevel-Interfaces nach außen. Für die braucht man natürlich einen passenden Typen. Aber der muß nicht nur die richtige Größe haben, sondern auch die richtige Byteorder und andere Dinge. Willst du die dem Compiler auch global vorschreiben, auch wenn die auf dem Zielsystem höllisch langsam sind, nur damit man beim Ansprechen einer SD-Karte nicht nachdenken muß? Der Löwenanteil des C-Codes, der auf einem System läuft besteht in der Regel nicht aus lowlevel-Interfaces. Und dort sind effiziente Typen wichtiger als welche, die sich an starre Vorgaben von außen halten, insbesondere, wenn diese Vorgaben bei mehreren Interfaces auch noch unterschiedlich sein können. > Kann man sinnvoll mit so einer verqueren Definition arbeiten? Ja. Konnte ich bisher zumindest immer. > Es ist 'int8_t' für den Compiler also tatsächlich nix anderes als ein > schnöder 'signed char' - und wenn du ne inkompatible Verwendung im > Quelltext machst, dann lautet die Fehlermeldung etwa so: > "Error 123456: cannot convert signed char to blablabla." > Da wirst du eben nicht finden "...cannot convert int8_t to blablabla". Ach ja? Bei
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
spuckt mein gcc aus:
1 | |
2 | |
Die Sache ist also eher ein Problem der Qualität des Compilers, denn es ist diesem nicht verboten, bei Warnungen den typedef-Namen auszugeben statt des Namens, auf den der typedef verweist. > Was ich gemeint habe wäre, daß genau SOLCHE Zeilen eben nicht mehr > vorkommen dürften, sondern sowas wie 'int8_t' als solches vom Compiler > verstanden wird. Als echtes Schlüsselwort mit einer Bedeutung, die für > ALLE Maschinen gleich ist. Sie ist für alle Maschinen gleich. Es ist halt ein typedef, statt eines Schlüsselwortes. Einen Nachteil kann ich dabei nicht erkennen.
Nebenbei: Der Unterschied zwischen Schlüsselworten und Typedefs ist syntaktisch betrachtet nicht sonderlich gross. Typedefs wurden erst nachträglich in C eingeführt, allerdings schon zu K&R Zeiten, und passen eigentlich nicht in eine Syntax, in der Deklarationen durch ein einleitendes Typ-Schlüsselwort wie "int" erkannt werden. Das gibt Typedef-Namen eine Sonderrolle, da sie keine einfachen Identifier sein können. Folglich wird ein Compiler mit schematischem Parser wie Bison bereits in der lexikalischen Analyse einen Identifier danach untersuchen, ob es ein Typedef-Name oder ein anderer Name ist, und ein entsprechendes anderes Token an den Parser reichen. Eingeschränkt dadurch, dass der Name an einigen wenigen Stellen wieder ein normaler Name ist, beispielsweise direkt hinter enum/struct/union, was Lexer und Parser enger koppelt, als Reitern von Sprachprinzipien lieb ist.
C-Gast schrieb: > Hallo, > habt Ihr bitte einen guten Artikel, aus dem die richtige und sinnvolle > Verwendung der verschiedenen Datentypen hervorgeht? > Von "uint_fast8_t" hatte ich bis dato leidr noch nicht mal was gehört... > aber man lernt ja gerne dazu > Danke Du musst Dir im Prinzip einfach drei Fragen beantworten: 1. Können die zu speichernden Werte negativ sein? Wenn nein, nimmt man einen vorzeichenlosen Typ (unsigned, uintXX_t). Wenn ja, einen vorzeichenbehafteten (signed, intXX_t). 2. Wie groß können die Werte maximal werden? Davon hängt die erforderliche Breite des Typs in Bit ab.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
3. Muss der Datentyp auf jeder Plattform gleich groß sein?
Wenn ja, dann nimmt man uint8_t, int16_t etc. Damit weiß man genau, wie
viele Bytes die Daten im Speicher belegen. Das ist inbesondere bei
Datenstrukturen wichtig, die man mit anderen Komponenten austauscht.
In den meisten anderen Fällen genügt es aber, wenn man weiß, dass der
Typ mindestens den erforderlichen Wertebereich abdeckt. Es macht aber
nichts, wenn man auch größere Zahlen darin speichern könnte. Das gilt
besonders für lokale Variablen für Berechnungen, Schleifenzähler,
Statusvariablen usw.. Dafür gibt es die Typen (u)int_leastXX_t und
(u)int_fastXX_t. Die garantieren, dass sie mindestens XX Bit breit sind,
können aber auch größer sein.
Der Typ int_fastXX_t hat den Hintergrund, dass es auf
32/64-Bit-Prozessoren in der Regel aufwändiger ist, mit nur 8 oder 16
statt den vollen 32/64 Bit des Registers zu rechnen, da die oberen Bits
immer noch extra ausmaskiert werden müssen. Bei so einer Plattform
bremst man das Programm also unnötig aus, wenn man auf kleinere
Bitbreiten für die Berechnungen besteht. Mit int_fastXX_t erhält man
immer den Typ, der sich am effizientesten verarbeiten lässt, aber
mindestens XX Bits aufnimmt. Ein int_fast8_t wird auf einem
32-Bit-Prozessor also höchstwahrscheinlich 32 Bit breit sein, auf einem
8-Bit-Mikrocontroller dagegen nur 8 Bit.
Die int_leastXX_t sind dagegen afaik eher akademischer Natur. Sie bieten
mindestens XX Bit und sind der kleinstmögliche Typ, der mit dieser
Breite zur Verfügung steht. In aller Regel dürften sie daher genau XX
Bit breit sein, sofern die Plattform nicht über eine ganz exotische
Speicherorganisation verfügt. Bitte korrigieren, falls ich da falsch
liege ...
So, und dann gibt es noch die traditionellen C-Datentypen:
Breite
char mind. 8 Bit
short int mind. 16 Bit
int mind. 16 Bit
long int mind. 32 Bit
long long int mind. 64 Bit
Jeder davon ist auch unsigned möglich.
Der einfache int entspricht normalerweise entweder dem short int oder
long int, jenachdem, was auf der Plattform effizienter zu rechnen ist.
Damit ist ein int praktisch äquivalent zu einem int_fast16_t. Für
int_fast8_t gibt es dagegen keine Entsprechung. Auf einem
Mikrocontroller müsste man (signed) char benutzen, auf größeren
Plattformen dagegen int.
Fabian O. schrieb: > Die int_leastXX_t sind dagegen afaik eher akademischer Natur. Sie sind dort relevant, wo ein exakter Typ nicht vorliegt. Mangels entsprechender Maschinenoperationen hatte ich bei einem Compiler für Transputer in der 32-Bit Fassung keinen 16-Bit Datentyp implementiert. int16_t wird in einem solchen Fall nicht existieren, int_least16_t hingegen schon.
Fabian O. schrieb: > Der einfache int entspricht normalerweise entweder dem short int oder > long int, jenachdem, was auf der Plattform effizienter zu rechnen ist. Nein. Das in Linux übliche 64-Bit Programmiermodell LP64 verwendet 64 Bits für "long", 32 Bits für "int" und 16 Bits für "short". Nur in der Windows-Variante LLP64 muss für 64 Bits auf "long long" ausgewichen werden.
A. K. schrieb: > Sie sind dort relevant, wo ein exakter Typ nicht vorliegt. Dorgh, ich muss aus Versehen auf Absenden statt Vorschau geklickt haben. Beim Durchlesen ist es mir nämlich auch aufgefallen. Beim Absenden kam dann die Meldung, ich dürfte nich mehr editieren ... Hier die richtige Fassung: Die int_leastXX_t sind dagegen afaik eher ungebräuchlich. Sie bieten mindestens XX Bit und sind der kleinstmögliche Typ, der mit dieser Breite zur Verfügung steht. In der Regel sind sie also genau XX Bit breit. Nur falls die Plattform keine kleineren Typen addressieren kann, sind sie größer. Das ist beispielsweise bei manchen DSPs der Fall, bei denen ein char dann 16 Bit breit ist. Man kann die int_leastXX_t also nutzen, wenn einem wichtig ist, dass möglichst wenig RAM gebraucht wird, der Code aber auch auf Plattformen läuft, auf denen es z.B. kein int8_t gibt.
A. K. schrieb: > Fabian O. schrieb: >> Der einfache int entspricht normalerweise entweder dem short int oder >> long int, jenachdem, was auf der Plattform effizienter zu rechnen ist. > > Nein. Das in Linux übliche 64-Bit Programmiermodell LP64 verwendet 64 > Bits für "long", 32 Bits für "int" und 16 Bits für "short". Nur in der > Windows-Variante LLP64 muss für 64 Bits auf "long long" ausgewichen > werden. OK, wieder was gelernt. Habe mir schon fast gedacht, dass es da Ausnahmen von gibt, daher "normalerweise" ... Dass das bei Linux Standard ist, war mir aber nicht bewusst. :)
Könnte sich lohnen, wenn du einen Artikel draus machst.
Fabian O. schrieb: > Davon hängt die erforderliche Breite des Typs in Bit ab. > 8 Bit | 0 | 255 | -128 | 127 Der Vollständigkeit halber: Der Standard garantiert nur -127..+127. Grössere Typen analog. Ist aber eine eher exotische Einschränkung.
A. K. schrieb: > Könnte sich lohnen, wenn du einen Artikel draus machst. Stimmt schon, hier im Thread findet man es schlecht wieder. Ich habe mal einen Artikel erstellt, werde ihn in den nächsten Tagen noch erweitern. Wenn eh grad der Wettbewerb läuft ... :) http://www.mikrocontroller.net/articles/Plattformunabh%C3%A4ngigkeit
Fabian O. schrieb: > A. K. schrieb: >> Könnte sich lohnen, wenn du einen Artikel draus machst. > > Stimmt schon, hier im Thread findet man es schlecht wieder. Ich habe mal > einen Artikel erstellt, werde ihn in den nächsten Tagen noch erweitern. > Wenn eh grad der Wettbewerb läuft ... :) > > Plattformunabhängigkeit Diskussion:Plattformunabhängigkeit: Was noch fehlt
Gast
#3027330
Sam P. schrieb: >> Also, hast du es jetzt gerafft? > > Offensichtlich nicht. Es gibt das was du dir wünschst, wenn auch mit > Namen, die deiner Ästhetik nicht ganz entsprechen. Es ist offiziell, es > ist überall verfügbar, überall gleich definiert und voll in die Sprache > integriert... Es ist ein Manko, ein Geburtsfehler der Sprache C - und keiner hat es bisher geschafft, damit mal wirklich aufzuräumen. Leider. Immer nur ein Workaround auf den anderen. Wer in C programmiert, muß damit irgendwie zurechtkommen. Wie auch immer. Die Ästhetik finde ich Mist. Aber da all diese Pseudotypen ja ohnehin nicht zum Sprachumfang gehören, kann sich jeder nach eigenem Gusto U8, W16, N24, uint16_t und noch viele weitere Hausausdrücke einfallen lassen. Babylon ist überall. Aber mal zum Kern der Sache: Es (s.o.) ist weder voll noch irgendwie in die Sprache integriert, sondern völlig unintegriert als Hilfs-Headerdatei vorliegend. Wäre "ES" integriert, dann würde man die von dir genannte Headerdatei überhaupt nicht benötigen, weil es die betreffenden Schlüsselwörter in der Sprachdefinition gäbe. Aber es ist nicht integriert und man benötigt diese compilerherstellerabhängige Headerdatei, um das Konstrukt (u)int(n)_t in eine dem Compiler verständliche Folge von Schlüsselwörtern zurückzuübersetzen. Das war und ist es, was ich dir klarmachen will. So. Man kann mit all dem zurechtkommen. Irgendwie. Du, ich und all die anderen. Aber man sollte es beim Namen nennen. Mist ist Mist - und es ist eben kein Gold bloß weil man es selber nicht ändern kann. Ich zumindest versuche nicht, mir die Dinge schönzureden. Und nun zurück zur Ausgangsfrage: Torsten B. schrieb: > Weil es in der " stdint.h" so definiert ist ! Ja! > Aber warum weicht diese vom C-Standard ab ? Antwort: Weil die entscheidenden Gremien es nicht geschafft haben, die Sprache C wirklich zu modernisieren und sie stattdessen Workarounds (im Klartext "Hilfskrücken") wie stdint.h sich ausgedacht haben. Dort darf dann jeder, der sich berufen fühlt, diese Pseudotypen in geeigneter Form auf das herunterbrechen, was sein Compiler denn so tatsächlich versteht. W.S.
W.S. schrieb: > Die Ästhetik finde ich Mist. Aber da all diese Pseudotypen ja ohnehin > nicht zum Sprachumfang gehören, ... Doch tun sie. Es ist C99. Sie gehören also seit weit über 10 Jahren zum Standard. Wenn dir das zu wenig ist, kann die niemand helfen. Es ist auch nicht unüblich, Sprachen zu erweitern: Python, Java, Fortran, Ada, um nur ein paar wenige zu nennen. Aber dass es dor nicht darum geht, sondern ums Nörgeln, ist inzwischen mehr als klar und jeder hat es verstanden.
Gast
#3027372
C-Gast schrieb: > Hallo, > habt Ihr bitte einen guten Artikel, aus dem die richtige und sinnvolle > Verwendung der verschiedenen Datentypen hervorgeht? > Von "uint_fast8_t" hatte ich bis dato leidr noch nicht mal was gehört... > aber man lernt ja gerne dazu > Danke http://stackoverflow.com/questions/1953796/performance-benefit-when-using-uint-fast8-t
W.S. schrieb: > Aber mal zum Kern der Sache: > Es (s.o.) ist weder voll noch irgendwie in die Sprache integriert, > sondern völlig unintegriert als Hilfs-Headerdatei vorliegend. > > Wäre "ES" integriert, dann würde man die von dir genannte Headerdatei > überhaupt nicht benötigen, weil es die betreffenden Schlüsselwörter in > der Sprachdefinition gäbe. Hätte man es direkt integriert (das wäre trivial gewesen), wäre der neue Standard inkompatibel zum alten. Es gäbe neue Schlüsselwörter und bisher gültige Programme ließen sich mit aktualisierten Compilern unter Umständen nicht mehr übersetzen. Dadurch, dass für die neuen Typen in C99 explizit ein #include <stdint.h> (und für die booleans ein #include <stdbool.h>) gemacht werden muss, haben die neu definierten Typen keinen Einfluss auf ältere Programme. Und natürlich stehen die Typen in der Sprachdefinition, woher kämen wohl sonst die Namen stdint.h und stdbool.h?
W.S. schrieb: > Es ist ein Manko, ein Geburtsfehler der Sprache C - und keiner hat es > bisher geschafft, damit mal wirklich aufzuräumen. Leider. Immer nur ein > Workaround auf den anderen. Es gibt zwei wesentliche Kriterien bei der Erweiterung von Programmiersprachen: 1. sauber und ästhetisch 2. abwärtskompatibel Da diese Kriterien teilweise im Widerspruch zueinander stehen, wird einem von beiden eine höhere Priorität eingeräumt. Ein Beispiel für (1) ist Python, wo immer wieder einmal aufgeräumt wird, um die Sprache als Ganzes möglichst rund und aus einem Guß dastehen zu haben. Bei C hingegen steht ganz klar (2) im Vordergrund, weil von vielen Firmen C-Code über Jahrzehnte hinweg wiederverwendet wird. Wird (1) priorisiert, meckern die Leute, dass ihre alten Programme nicht mehr laufen. Wird hingegen (2) priorisiert, meckern die Leute, dass die Sprache ihre klinische Reinheit verliert. Wer nur in einem der beiden Fälle meckert, wählt einfach eine andere Programmiersprache. Wer in beiden Fällen meckert, der sollte mit dem Programmieren aufhören :) > Wäre "ES" integriert, dann würde man die von dir genannte Headerdatei > überhaupt nicht benötigen, weil es die betreffenden Schlüsselwörter in > der Sprachdefinition gäbe. Eine gute Integration von Datentypen bedeutet nicht, dass für sie Schlüsselwörter reserviert werden. Ich empfinde es sogar eher als unästhetisch, wenn Datentypen, Systemvariablen, Standardfunktionen u.ä. als Schlüsselwörter definiert werden, denn für mich ist kein Grund ersichtlich, warum der Name eines vordefinierten Datentyps ein Schlüsselwort sein soll, der Name eines benutzerdefinierten Datentyps aber nicht. Konsequenterweise ist in vielen modernen Programmiersprachen kein einziger Datentyp als Schlüsselwort definiert¹. > Aber es ist nicht integriert und man benötigt diese > compilerherstellerabhängige Headerdatei Ja, und das Tolle an der Sache ist, dass man dieser Headerdatei auch einfach weglassen kann, wenn sich die darin enthaltenen Typdeklarationen mit bestehendem Programmcode beißen. > Aber man sollte es beim Namen nennen. Mist ist Mist - und es ist eben > kein Gold bloß weil man es selber nicht ändern kann. Ich zumindest > versuche nicht, mir die Dinge schönzureden. Aber noch viel größerer Mist (wenn auch anderer Art) wäre es, wenn eine Softwarefirma bei jedem neuen C-Standard ihren kompletten Code-Bestand anpassen müsste. Ich verstehe auch nicht ganz, warum du immer wieder auf diesen stdint- Typen herumreitest. Du kannst in den meisten Fällen auch ganz gut ohne sie leben: Der C-Standard gibt für alle "normalen" Integertypen (also char, short, int, long und long long, jeweils signed und unsigned) einen minimalen Wertebereich an. Du wählst also einfach immer denjenigen Typ aus, dessen garantierter Wertebereich für deine Berechnungen ausreichend ist. Wie groß der (implementierungsabhängige) tatsächliche Wertebereich ist, ist meist relativ uninteressant. Mir fallen spontan nur zwei Fälle ein, wo die tatsächliche Bitgröße der Integer-Typen von Bedeutung ist: 1. wenn beim Speicherverbrauch des Programms jedes einzelne Byte zählt 2. wenn man aus Effizienzgründen mit überlaufenden Variablenwerten als Ersatz für die Modulo-2^n-Arithmetik herumtricksen möchte Aber diese Fälle treten doch eher selten auf. ––––––––––––– ¹) Manchmal wird beim Unit-Typ eine Ausnahme gemacht, was der Ästhetik auf Grund der Sonderrolle dieses Typs aber keinen Abbruch tut.
W.S. schrieb: > Aber mal zum Kern der Sache: > Es (s.o.) ist weder voll noch irgendwie in die Sprache integriert, > sondern völlig unintegriert als Hilfs-Headerdatei vorliegend. Wir haben unterschiedliche Ansichten darüber, was zur Sprache gehört und was "völlig unintegriert ist". Für mich ist alles, was in der Sprachdefinition steht, Teil der Sprache. Das ist bei stdint.h und den [u]int*-Typen der Fall, also gehören sie zur Sprache. Bei C war es schon immer so, daß man versucht hat, den - nennen wir es mal Sprachkern - möglichst klein zu halten und alles, was da nicht unbedingt drin sein muß, in die Standardbibliothek zu stecken. So gibt's z.B. auch die Möglichkeit zur Textausgabe (printf) nur in der Bibliothek und nicht, wie bei manchen anderen Sprachen, als Schlüsselwort. Stört dich auch, daß du dafür einen Header einbinden mußt und daß es "weder voll noch irgendwie in die Sprache integriert" ist? Ist printf deshalb kein Teil von C? Du hast es immer noch nicht geschafft, auch nur einen einzigen Vorteil zu nennen, diese [u]int*-Typen als Schlüselwort statt per Header zu definieren.
Gast
#3040420
Rolf Magnus schrieb: > Ist printf deshalb > kein Teil von C? Richtig. 'printf' ist genauso wie alles was in separaten Headerdateien steht eben kein Bestandteil der Sprache. Da zählt nur genau das, was als Schlüsselwort definiert ist und nichts, was in irgendwelchen Headerdateien steht. Das sind alles nur Workarounds, wenn es um Datentypen geht. Auch die ganzen Funktionen der diversen Standardbibliotheken gehören nicht zu den Bestandteilen der Sprache, sondern sind lediglich "üblicherweise vorhandene Funktionen". 'printf' kann, muß aber nicht in den Libraries einer Toolchain enthalten sein. Nur so als Beispiel. Andreas B. schrieb: > Hätte man es direkt integriert (das wäre trivial gewesen), wäre der neue > Standard inkompatibel zum alten. Es gäbe neue Schlüsselwörter... Ja. Eben, siehe "Int64" als Beispiel. Es wäre ganz gewiß kein Beinbruch gewesen, 'int' als 16 Bit Zahl und 'long' als 32 Bit Zahl festzuschreiben. Das wäre überhaupt nicht inkompatibel zum Bisherigen gewesen - und ich möchte hier nur mal dran erinnern, daß der Schritt von K&R zu ANSI ein viel größerer Schnitt in der Syntax gewesen ist. Es geht - man muß bloß wollen. Und man hätte es wollen sollen. Das wäre was wirklich Gutes gewesen. Nochmal im Klartext: das Festschreiben eines 'int' auf exakt 16 Bit und 'long' auf exakt 32 Bit wäre absolut KEINE Inkompatibilität zu bisherigen Programmen gewesen - bis auf solche, bei denen die Autoren sich ohnehin an nix gehalten haben. Ich halte es auch nicht für verwerflich, neue Schlüsselwörter einzuführen, wenn das mit der gebührenden Zurückhaltung erfolgt. Dazu unser Mod: Yalu X. schrieb: > Ich empfinde es sogar eher als > unästhetisch, wenn Datentypen, Systemvariablen, Standardfunktionen u.ä. > als Schlüsselwörter definiert werden Genau DAS ist wieder mal die Übertreibung - hier mal deinerseits. Systemvariablen und Standardfunktionen gehören nicht zu einer Sprachdefinition und sollen deshalb eben nicht eigene Schlüsselworte erhalten. Aber grundlegende Datentypen gehören zu den echten Grundlagen einer jeden Programmiersprache und damit in den eigentlichen Sprachumfang mit eigenem Schlüsselwort. Und da gibt es in C eben nix anderes als char, int und long nebst ihren unsigned Versionen. Alles Andere ist in C nicht definiert. Warum in aller Welt wollen die hier versammelten Diskutierer das nicht einsehen und einfach mal sagen "ja, so isses eben." Yalu X. schrieb: > Ich verstehe auch nicht ganz, warum du immer wieder auf diesen stdint- > Typen herumreitest. Um der Klarheit willen. Das isses. Klarheit. Mit dem Gegebenen leben kann ich schon seit Jahren, ich hab in der Praxis damit keine Probleme bis auf solche Fälle, wo ich mich mal wieder durch unleserliche Fremdquellen durchackern muß. Aber ich akzeptiere Krummheiten eben nicht derart, daß ich mich selber krumm mache, bloß um sie als 'Geradheiten' ansehen zu können. Klaro? W.S.
W.S. schrieb: > daß der Schritt von K&R zu ANSI ein viel größerer Schnitt in > der Syntax gewesen ist. Es war eine Erweiterung und eine klarere Spezifikation, aber kein Schnitt. Alte Programme blieben übersetzbar, es sei denn sie hatten das Pech und verwendeten die neuen Keywords - aber sowas ist trivial zu fixen. Einzig jene Programme, die bei der impliziten Typkonvertierung auf Bewahrung der Vorzeicheneigenschaft (sign preservation) an Stelle des Wertes (value preservation) gesetzt hatten, die bissen ins Gras. Denn das findest du nicht so leicht im Code. Aber das war vorher schlicht nicht festgelegt. Ich hatte im Compiler deshalb vorsorglich beides ermöglicht. > Nochmal im Klartext: das Festschreiben eines 'int' auf exakt 16 Bit > und 'long' auf exakt 32 Bit wäre absolut KEINE Inkompatibilität zu > bisherigen Programmen gewesen Bereits K&R erwähnt Implementierungen mit 32-Bit int (IBM 370, Interdata 8/32) und 36-Bit short+int (Honeywell 6000). Anno ANSI-C 1989 waren bereits viele C Compiler mit 32-Bit int im Einsatz. > - bis auf solche, bei denen die Autoren > sich ohnehin an nix gehalten haben. Anno K&R gab es keine klare Definition des Wertebereichs von Datentypen, also auch nichts wogegen man hätte verstossen können. Dafür aber gab es viele Programme, die faktisch von sizeof(int) == sizeof(char *) ausgingen. Schon weil das in vielen Fällen der einzige wachsweichen Spezifikation entsprach, dass "int" der natürlichen Wortbreite entspräche. Diese einzige Regel hätte int=16bit definitiv verletzt, das kam also ohnehin nicht in Frage. Natürlich kann man sich auf "zum Teufel mit denen, die nicht meiner Ansicht sind" verlegen, aber weit kommt man mit diesem Ansatz aufgrund der normativen Kraft des Faktischen nicht. Man hatte auf diesem Weg einen Seitenzweig eröffnet. Mit dem Ansatz "vor mir die Sintflut" hätte man besser dran getan, die miserable Deklarationssystax von C gleich ganz über Bord zu werfen und durch eine saubere zu ersetzen. Und ein paar andere Stellen gleich mit. > Ich halte es auch nicht für verwerflich, neue Schlüsselwörter > einzuführen, wenn das mit der gebührenden Zurückhaltung erfolgt. Es war ein fundamentaler syntaktischer Fehler von C, Datentypen überhaupt erst zu Keywords zu machen. > Systemvariablen und Standardfunktionen gehören nicht zu einer > Sprachdefinition Bibliotheken können sehr wohl Bestandteil eines Standards sein. Anno K&R wurde das de fakto so gesehen, weil das ganze Buch als Standardwerk betrachtet wurde. Ab ANSI-C waren bestimmte Includes und ihre Inhalte definitiv Teil der Standards. Haarspalter könnten nun versucht sein, diesen Standard in 2 Substandards zu differenzieren, einen für Syntax und Semantik und einen andere für eine mindestens erforderliche Bibliothek, aber das bringt nicht viel ein.
W.S. schrieb: > Rolf Magnus schrieb: >> Ist printf deshalb kein Teil von C? > > Richtig. 'printf' ist genauso wie alles was in separaten Headerdateien > steht eben kein Bestandteil der Sprache. Sehr eigenartige Sichtweise. Ich glaube nicht, daß du die mit irgendwem hier teilst. > Da zählt nur genau das, was als Schlüsselwort definiert ist und nichts, > was in irgendwelchen Headerdateien steht. Das sind alles nur Workarounds, > wenn es um Datentypen geht. Ich weiß ehrlich gesagt nicht, was daran "Workaround" sein soll. Die funktionieren prima und ohne Probleme. Und es gibt keinerlei sinnvollen Grund, mit neuen Schlüsselwörtern um sich zu werfen, nur um eine gut funktionierende Lösung zu ersetzen durch etwas, das nicht besser ist. > Auch die ganzen Funktionen der diversen Standardbibliotheken gehören > nicht zu den Bestandteilen der Sprache, sondern sind lediglich > "üblicherweise vorhandene Funktionen". > > 'printf' kann, muß aber nicht in den Libraries einer Toolchain enthalten > sein. Nur so als Beispiel. C definiert zwei Arten von Implementationen, nämlich "freestanding" und "hosted". Bei ersterer ist sehr vieles optional, bei letzerer nicht. Dort sind auch printf() und die ganzen Typen aus stdint.h zwingend vorgeschrieben und müssen bei einem konformen Compiler dabei sein. Sind sie das nicht, ist es kein ISO-C-Compiler. > Es wäre ganz gewiß kein Beinbruch gewesen, 'int' als 16 Bit Zahl und > 'long' als 32 Bit Zahl festzuschreiben. Das wäre überhaupt nicht > inkompatibel zum Bisherigen gewesen Mal abgesehen von Plattformen, die z.B. gar keinen 16-Bit-Typen kennen. Dort müßte man dann mit viel Aufwand einen solchen emulieren, was schnarchlahme Progrmame zur Folge hätte. Und ja, solche Plattformen gibt es. > Systemvariablen und Standardfunktionen gehören nicht zu einer > Sprachdefinition und sollen deshalb eben nicht eigene Schlüsselworte > erhalten. Aber grundlegende Datentypen gehören zu den echten Grundlagen > einer jeden Programmiersprache und damit in den eigentlichen > Sprachumfang mit eigenem Schlüsselwort. Die grundlegenden Datentypen sind ja auch da. Und für entsprechende Anforderungen sind eben noch Alias-Namen mit dabei, die man optional nutzen kann. > Und da gibt es in C eben nix anderes als char, int und long nebst ihren > unsigned Versionen. Alles Andere ist in C nicht definiert. Hast du die Sprachdefinition mal gelesen? > Warum in aller Welt wollen die hier versammelten Diskutierer das nicht > einsehen und einfach mal sagen "ja, so isses eben." Weil es Unsinn ist.
Gast
#3040938
W.S. schrieb: > Du hast ne ziemlich seltsame Denkweise, die ich nicht teile. > Als Programmierer muß man sich auf die verwendeten Datentypen verlassen > können, was in C nicht der Fall ist. Du besitzt eine interessante "Meinung" und fundiertes Halbwissen. Respekt. Leider wird diese Meinung allerdings nicht von der C-Idee getragen. C ist immer und wird immer eine möglichst hardwarenahe Sprache sein. Solltest Du den von dir propagierten Grad an Abstraktion und Typensicherheit brauchen musst du ein anderes Sprachmittel wählen. Vielleicht ist JAVA was für dich. Der Standard gibt für seine Typen durchaus einen begrenzten Wertebreich an. Wenn ich Variablen in diesen Wertebereich deklariere kann ich dem Compiler die Wahl eines möglichst natürlichen Formats für die Maschine lassen. Für exakt definierte Typen braucht es allerdings plattformangepasste Typendefinitionen, wie in den Strukturen für Kommunikationsprotokolle. Das kannst du getrost deinem Compilerhersteller überlassen, denn der liefert ja das stdint.h mit. Und im Grunde kommen diese Strukturen eh nicht ohne deinen Einfluss auf den Compiler aus (du musst mit #pragma meistens das Padding verhindern).
"Es wäre ganz gewiß kein Beinbruch gewesen, 'int' als 16 Bit Zahl und " Int steht nunmal für "ein Maschinenwort ala Maison, egal wie gross das ist solang da 16 Bit reinpassen", und das ist ein sinnvoller Typ, warum sollte man das anders handhaben?
W.S. schrieb: > Rolf Magnus schrieb: >> Ist printf deshalb kein Teil von C? > > Richtig. 'printf' ist genauso wie alles was in separaten Headerdateien > steht eben kein Bestandteil der Sprache. Zu einer Sprache gehört alles, was in der Spech-Spezifikation steht > Da zählt nur genau das, was als Schlüsselwort definiert ist und > nichts, was in irgendwelchen Headerdateien steht. Das sind alles > nur Workarounds, wenn es um Datentypen geht. Auch die ganzen > Funktionen der diversen Standardbibliotheken gehören nicht zu den > Bestandteilen der Sprache, sondern sind lediglich "üblicherweise > vorhandene Funktionen". Eine Sprache in Sprachkern und Bibliotheken aufzuspalten ist nun wirklich kein Nachteil von C. Das gleiche Konzept findet sich bei C++, Fortran, Java, Ada, Python und zig anderen Sprachen, denn es ist überaus sinnvoll, einen kompakten und überschaubaren Sprachken zu haben. Da es dir um dein Hobby C-Bashing geht: C hat wahrlich genug Schwächen und Kritikpunkte, so daß es wirklich nicht erforderlich ist, Kritikpunkte an den Haaren herbei zu ziehen. Die Aufteilung in Sprachkern und Standard-Bibliothek und -Header gehört nämlich nicht zu den Schwächen, sondern zu den Stärken der Sprache.
Beitrag #5409776 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.