Hallo liebe Leuts,
ich interessiere mich, rein historischer weise, woher die Bezeichnungen
uint8_t, uint16_t bzw. uint32_t stammen. Also auf wen oder welchen
Standard ist diese Namensgebung zurückzuführen bzw. aus welchem System
wurde dies übernommen?
Mein erster Ansatz war es die Quellen der 'alten' Versionen des Linux
Kernels nach uint8_t mit Hilfe von [1] zu durchsuchen: In Linux tauchte
diese Konvention zum ersten mal in Version 2.1.92 des Kernels in der
Datei /include/linux/types.h auf. Das müsste ungefähr April 1998 gewesen
sein. Hier ein diff zu Kernel Version 2.1.91:
72,93d71
< #ifndef _BIT_TYPES_DEFINED_
< #define _BIT_TYPES_DEFINED_
<
< typedef __u8 u_int8_t;
< typedef __s8 int8_t;
< typedef __u16 u_int16_t;
< typedef __s16 int16_t;
< typedef __u32 u_int32_t;
< typedef __s32 int32_t;
<
< #endif /* !(_BIT_TYPES_DEFINED_) */
<
< typedef __u8 uint8_t;
< typedef __u16 uint16_t;
< typedef __u32 uint32_t;
<
< #if defined(_GNUC_) && !defined(_STRICT_ANSI_)
< typedef __u64 uint64_t;
< typedef __u64 u_int64_t;
< typedef __s64 int64_t;
< #endif
<
Aus dem Wikipedia Artikel über C [2] erfährt man: "1995 wurde erneut ein
Ausschuss gegründet, um C zu erweitern und zu verbessern. Daraus ging
1999 der neue ISO-Standard ISO/IEC 9899:1999 hervor, auch als C99
bezeichnet." ... "Außerdem werden Integer-Typen mit exakter Breite
spezifiziert, aber als optional bezeichnet – zum Beispiel int32_t."
Unter [3] findet sich dann diese Konvention des C99 Standards im
Abschnitt "Integer Types".
Also wurde dieses Vorgehen in C99 eingeführt. Die Entwickler des Linux
Kernels haben sich wohl schon an den (damals aktuellen?) draft für C99
gehalten und dies im Kernel eingeführt.
Nun soweit meine Recherche... aaaaber. hat sich das C99 Komitee dies
einfach so ausgedacht oder war es in anderen Systemen bereits good
practice und wurde übernommen? Ich wäre doch schon neugierig woher genau
diese Konvention stammt bzw. erstmal entstanden ist.
Viele Grüße
Jens
[1] http://lxr.linux.no
[2]
http://de.wikipedia.org/wiki/Varianten_der_Programmiersprache_C#Wichtigste_Neuerungen_von_C99
[3]
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html
Jens schrieb:> Nun soweit meine Recherche... aaaaber. hat sich das C99 Komitee dies> einfach so ausgedacht
Das Komitee denkt sich in den meisten Fällen überhaupt nichts selber
aus.
Sondern da werden Anträge und Vorschläge eingereicht, die vom Komitee
diskutiert, eventuelle abgesegnet, begutachtet und dann im nächsten
Standard auftauchen.
> oder war es in anderen Systemen bereits good> practice und wurde übernommen?
Derartige Typdefinitionen in der einen oder anderen Form gab es, seit
industriell C programmiert wird. Und sie waren ein konstantes Ärgernis,
wenn man Code von einem System auf ein anderes portieren musste. Die
Frage war also nicht ob man so etwas einführen sollte, sondern wie der
'Wortlaut' sein sollte.
Das angehängte _t war relativ logisch, da es einen Datentyp size_t oder
auch time_t auch vorher schon gab. Das die Bitzahl darin vorkommen
würde, es in irgendeiner Art und Weise eine Kennzeichnung für 'mit oder
ohne Vorzeichen' geben würde, die Datentyp Namen nicht zu kurz aber auch
nicht zu lang sein sollten, man dafür sorgen wollte, dass älterer Code
davon nicht beeinträchtigt wird (ist beim C und C++ Komitee immer ein
wichtiger Punkt), ... berücksichtigt man das alles, dann bleiben nicht
mehr allzuviele Alternativen. Und dann nimmt man halt denjenigen
eingereichten Vorschlag, der den meisten gefällt.
Zudem ist der Inhalt der meisten abgesegneten Standards schon Jahre
vorher in Form von Drafts verfügbar, so dass es nicht wirklich wundert,
wenn im 1998 Kernel bereits Dingen vorgegriffen wird, die dann erst 1999
offiziell wurden. Zumal es sich hier im Konkreten nicht wirklich um
etwas schwierig zu Implementierende handelt, was weitreichende
Konsequenzen im Compiler hätte.
Hallo,
der Bedarf ergab sich daraus, dass ursprüngliche Typen maschinenabhängig
waren, so war word anfangs das native Format des Prozessors und daher
auch mal 12bit, z.B. bei PDPs. Und longint ist verschieden auf 32- und
64-bit-Systemen. Das ist manchmal ganz recht so, manchmal möchte man
aber definitiv 32 bit haben.
Gruss Reinhard
Ich glaube _t das steht für type oder typedef. Ich benutzte es
inzwischen selbst sehr oft wenn ich typedefs definiere. Sieht man ja
auch z.b. bei size_t, time_t..., ist wohl eher ne POSIX-Sache
_t -> Typedef
uint16/32 etc. sind für die "schlaue" Technologie von Bedeutung, wie
beim Cortex M3 hat man im Speicher 8-Bit mit 16Bit anordnen, somit wird
kein Speicher verschwendet, was bei ARM7 der Fall war, da man nur
word/half word Zugriffe hatte. Mit uint16_t teilst du dem Compiler mit,
dass dir die 16 bit ausreichen und belegst nicht gleich unnötig
komplette 32Bit.
Schön wäre es, wenn auch alle diese Standarddefinitionen verwenden
würden. In der Praxis sieht es leider oft so aus, dass sich jeder seine
eigenen Integer-Typen definiert. Besonders nervig finde ich das, wenn
die Bezeichnungen sich namentlich sehr von den Standardtypen
unterscheiden oder die Länge eben nicht aus dem Namen ersichtlich
ist(z.B. DWORD).
pks schrieb:> Besonders nervig finde ich das, wenn die Bezeichnungen sich namentlich> sehr von den Standardtypen unterscheiden oder die Länge eben nicht aus> dem Namen ersichtlich ist(z.B. DWORD).
Da musst Du die Historie berücksichtigen. Die Windows-API, der das
entstammt, ist ein paar Jährchen älter als C99, und nur weil es einen
neuen Programmiersprachenstandard gibt, bedeutet das nicht, das sämliche
API-Headerdateien neu geschrieben werden müssten -- ganz zu schweigen
davon, daß Microsoft sich bislang nur damit großtut, C99 komplett zu
ignorieren.
Ein semioffizielles Statement dazu ist, daß man doch einfach C++ nehmen
solle, wenn man C99 benötigt.
Rufus Τ. Firefly schrieb:> Ein semioffizielles Statement dazu ist, daß man doch einfach C++ nehmen> solle, wenn man C99 benötigt.
Oder man benutzt einfach den GCC. :P
♪Geist schrieb:> Mit uint16_t teilst du dem Compiler mit, dass dir die 16 bit ausreichen> und belegst nicht gleich unnötig komplette 32Bit.
Nein. Mit uint16_t teilst du dem Compiler mit, dass du exakt 16 Bits
haben willst, egal was es kostet. Falls die Zielmaschine keinen
solchen Datentypen darstellen kann, lässt sich das Programm auf ihr
nicht übersetzen.
Wenn dir 16 Bits ausreichen, es dir aber egal ist, wieviel es
wirklich sind, dann solltest du entweder uint_fast16_t (mindestens
16 Bits, aber möglichst schnelle oder einfache Verarbeitung) oder
uint_least16_t (mindestens 16 Bits, aber speichersparend) nehmen.
Auf einem ARM dürfte uint_fast16_t ein 32-bit-Integer sein, da es
schneller/einfacher ist, auf der 32-bit-Maschine gleich damit zu
arbeiten (keine Maskierung etc. nötig). Der uint_fast16_t dagegen
dürfte dort tatsächlich 16 Bits sein. Auf einer Maschine, die gar
keine 16-bit-Zahlen darstellen kann (einige ältere DSPs werden gern
als Beispiel angeführt) gibt es hingegen keinen uint16_t (die Maschine
kann das nicht), und der uint_least16_t hat 32 Bits.
Jörg Wunsch schrieb:> Auf einem ARM dürfte uint_fast16_t ein 32-bit-Integer sein, da es> schneller/einfacher ist, auf der 32-bit-Maschine gleich damit zu> arbeiten (keine Maskierung etc. nötig). Der uint_fast16_t dagegen> dürfte dort tatsächlich 16 Bits sein.
In der Redlib (arm-none-eabi-gcc, cortex-m3) sind sowohl für
int_fast8_t, uint_fast8_t als auch für die entsprechenden 16-Bit
Fast-Typen jeweils 32-Bit Integer definiert.
Ich habe mich auch verschrieben: im zweiten Satz oben waren die
“least”-Datentypen gemeint, also:
„Der uint_least16_t dagegen dürfte dort tatsächlich 16 Bits sein.“