Hi, ich hab im Forum hier gelernt, das man anstelle von unsigned long
int auch uint32_t schreiben kann. Unter Atmel Studio 6.1 geht das auch,
aber der Realview von Keil uV3 kennt das nicht. Was muss ich dem
Realview eingeben, damit er das auch kennt? Woher kennt der GCC
uint32_t? Ist das über haupt C konform?!
Hein Mück aus Bremerhaven schrieb:> Ist das über haupt C konform?!
C kennt verschiedenen Standards.
stdint.h ist mit C99 gekommen.
Kann man auch auf Wikipedia nachlesen.
C89 sollten alle Compiler beherschen. Darum gilt das als kleinster
geimeinsamer Nenner und manche benutzen es ausschließlich.
(Das liegt auch daran, dass Microsoft in seinen Compilern keinen neueren
Standard unterstützt.)
DirkB schrieb:> Hein Mück aus Bremerhaven schrieb:>> Ist das über haupt C konform?!>> C kennt verschiedenen Standards.
Eigentlich nur einen - den aktuellsten. Mit erscheinen dessen wird die
Vorgänger-Version für ungültig erklärt und ist nicht mehr erhältlich.
> C89 sollten alle Compiler beherschen. Darum gilt das als kleinster> geimeinsamer Nenner und manche benutzen es ausschließlich.> (Das liegt auch daran, dass Microsoft in seinen Compilern keinen neueren> Standard unterstützt.)
Nicht nur Microsoft, auch andere Compiler-Hersteller sind da leider
teilweise auf einem Stand von vor über einem Viertel Jahrundert stehen
geblieben. Microsoft ist aber das prominenteste Beispiel.
Hein Mück aus Bremerhaven schrieb:> das man anstelle von unsigned long> int auch uint32_t schreiben kann
Der Vollständigkeit halber sei angemerkt, dass ein "unsigned long int"
nur unter bestimmen umständen einem uint32_t gleicht.
Beispiel: Auf nem 64-bit Rechner und GCC, ist int 32 bit breit und ein
long int 64-bit breit!
Um das noch weiter zu vervollständigen: Darum gibt es die
[u]int*_t-Typedefs. Sie garantieren eine fixe Breite im Gegensatz zu den
klassischen Integertypen. Die sind aber eigentlich dafür gedacht, wenn
es wichtig ist, daß die Größe exakt stimmt. Diese Typedefs existieren
auch nur, wenn der Compiler für die Zielplattform entsprechend breite
Integertypen überhaupt anbietet. Außerdem kann es je nach Plattform
sein, daß ein größerer Typ effizienter wäre. Auf 32-Bit-Plattformen kann
es z.B. durchaus sein, daß die Nutzung von 16-Bit-Typen zu etwas
größerem und/oder langsamerem Code führt.
Es gibt deshalb auch noch uint_least32_t, was dem kleinsten verfügbaren
Typ mit mindestens 32 Bit entspricht, sowie uint_fast32_t, das dann der
schnellsten Typ mit mindestsn 32 Bit ist.
Sofern man also nicht gerade mit Hardware-Registern arbeitet oder einem
das Überlaufverhalten des 32-Bit-Typs wichtig ist, gibt es eigentlich
keinen wirklichen Grund, uint32_t zu nutzen.
Rolf Magnus schrieb:> Sofern man also nicht gerade mit Hardware-Registern arbeitet oder einem> das Überlaufverhalten des 32-Bit-Typs wichtig ist, gibt es eigentlich> keinen wirklichen Grund, uint32_t zu nutzen.
Der 32Bit Überlauf ist selten der Grund.
int kann auch 16 Bit sein, long int auch 64 Bit.
Mit uint32_t ist dagegen das Format nicht zu klein und nicht unnötig
groß.
Peter Dannegger schrieb:> Der 32Bit Überlauf ist selten der Grund.>> int kann auch 16 Bit sein, long int auch 64 Bit.> Mit uint32_t ist dagegen das Format nicht zu klein und nicht unnötig> groß.
Außerdem mach die Verwendung der neueren Typen den Code portabler.
Verwendet man die normalen Typen (int usw.) kann es passieren, dass man
den Code duch einen anderen Compiler jagt und dann plötzlich Probleme
durch Überläufe und ähnlichen Kram bekommt.
Das betrifft insbesondere die µConrtroller, eben weil 8bitter, 16bitter
und 32bitter unterwegs sind.
Ich hatte das schon bei der Portierung eines Programms für einen PIC32
auf einen PIC12.
Die Typen mit Angabe der Breite sind einfach sauberer.
WehOhWeh schrieb:> Ich hatte das schon bei der Portierung eines Programms für einen PIC32> auf einen PIC12.
Wobei man in solchen Fällen für lokale Variablen die XXX_fastYYY_t Typen
verwenden sollte, denn eine Verwendung von Registern mit weniger als 32
Bit Breite ist für die PIC32 eine ziemliche Zumutung. Ein uint_fast8_t
ist auf dem PIC12 8 Bit breit, auf dem PIC32 32 Bits, und passt daher
beiden. Ein uint8_t hingegen ist auch auf dem PIC32 im Register nur 8
Bits breit, was zusätzlichen Aufwand für Bitreduktion zur Folge haben
kann.
Peter Dannegger schrieb:> Rolf Magnus schrieb:>> Sofern man also nicht gerade mit Hardware-Registern arbeitet oder einem>> das Überlaufverhalten des 32-Bit-Typs wichtig ist, gibt es eigentlich>> keinen wirklichen Grund, uint32_t zu nutzen.>> Der 32Bit Überlauf ist selten der Grund.
Eben, deshalb ist der Typ auch deutlich seltener sinnvoll, als er
tatsächlich eingesetzt wird.
> int kann auch 16 Bit sein, long int auch 64 Bit.> Mit uint32_t ist dagegen das Format nicht zu klein und nicht unnötig> groß.
Ups, wo ist denn der Rest meines Postings geblieben? Also nochmal:
Peter Dannegger schrieb:> int kann auch 16 Bit sein, long int auch 64 Bit.> Mit uint32_t ist dagegen das Format nicht zu klein und nicht unnötig> groß.
Genau dafür ist uint_least32_t gedacht. Und wenn die Geschwindigkeit
wichtiger ist als die Größe, nimmt man uint_fast32_t. So ist die Angabe
der exakten Größe mit uint32_t eben nur noch in den zwei Fällen nötig,
die ich angegeben habe: Hardware-Register und Überlaufverhalten.
Rolf Magnus schrieb:> So ist die Angabe der exakten Größe mit uint32_t eben nur noch in den> zwei Fällen nötig, die ich angegeben habe: Hardware-Register und> Überlaufverhalten.
Das ist falsch. Ein weiterer, durchaus sehr wichtiger Anwendungsfall ist
die Definition von Strukturen mit festen Größenangaben, z.B. bei Datei-
oder Kommunikationsprotokollen.
Hierbei muss man sich aber ggf. auch auf ein bestimmtes Padding des
Compilers verlassen bzw. dieses per Direktive steuern.
Andreas Schweigstill schrieb:> Hierbei muss man sich aber ggf. auch auf ein bestimmtes Padding des> Compilers verlassen bzw. dieses per Direktive steuern.
Damit ist man sofort nicht mehr portabel, denn der Standard sieht eine
derartige Möglichkeit nicht vor. Padding liegt immer im Ermessen des
Compilers.
Außerdem kann es dadurch zu Problemen mit unaligned access kommen
(genau darum erfolgt ja normalerweise auch das Padding, das ist ja kein
Selbstzweck).
Byteorder-Probleme kommen noch hinzu.
Jörg Wunsch schrieb:> Damit ist man sofort nicht mehr portabel, denn der Standard sieht eine> derartige Möglichkeit nicht vor.
Das ist durchaus korrekt. Rolf hat aber als andere Anwendungsmöglichkeit
Hardwarezugriffe aufgeführt. Diese sind noch weniger portabel und ebenso
wenig durch den Standard abgedeckt.
Andreas Schweigstill schrieb:> Diese sind noch weniger portabel und ebenso wenig durch den Standard> abgedeckt.
Allerdings spielt im Allgemeinen bei Hardwarezugriffen die
Portabilität nur eine untergeordnete Rolle (läuft dann eh' nur auf
der Plattform, und die Zugriffe abstrahiert man für gewöhnlich in
einem passenden Layer).
Kommunikationsprotokolle dagegen möchte man ja vielleicht doch ein
wenig portabel haben, denn der Sinn der Kommunikation ist es meist
nicht, Selbstgespräche zu führen. ;-)
Jörg Wunsch schrieb:> Kommunikationsprotokolle dagegen möchte man ja vielleicht doch ein> wenig portabel haben, denn der Sinn der Kommunikation ist es meist> nicht, Selbstgespräche zu führen. ;-)
Das Protokoll muss portabel sein, nicht dessen Implementierung. Und wenn
wir schon dabei sind: schau doch einmal in diverse TCP/IP-Stacks. Dort
werden die Header häufig auch über Strukturen definiert bzw. zerlegt.
Dabei gibt es aber in der Tat manchmal massive Alignmentprobleme, wie
ich vor längerer Zeit einmal bei einem teuer (>20kEUR) TCP/IP-Stack
erfahren durfte. Insbesondere der 14 Byte große Ethernet-Header führt zu
einem schönen Versatz, nämlich wenn der Compiler davon ausgeht, dass die
Struktur, die den IP-Header bestimmt, an einer 4-Byte-Grenze beginnt...
Rolf Magnus schrieb:> DirkB schrieb:>> Hein Mück aus Bremerhaven schrieb:>>> Ist das über haupt C konform?!>>>> C kennt verschiedenen Standards.>> Eigentlich nur einen - den aktuellsten. Mit erscheinen dessen wird die> Vorgänger-Version für ungültig erklärt und ist nicht mehr erhältlich.
Die ungültigen Vorgängerversionen kann man durchaus noch kaufen.
Allerdings macht es einem die ISO ein bisschen schwer. Alte Versionen
gibt es nur noch auf Papier und auf Anfrage.
Die Gültigkeit liegt sowieso im Auge des Betrachters. Wenn man sich zum
Beispiel in einem Vertrag auf eine Version geeinigt hat, dann ist genau
diese für die Vertragserfüllung gültig.
Andreas Schweigstill schrieb:> Jörg Wunsch schrieb:>> Kommunikationsprotokolle dagegen möchte man ja vielleicht doch ein>> wenig portabel haben, denn der Sinn der Kommunikation ist es meist>> nicht, Selbstgespräche zu führen. ;-)>> Das Protokoll muss portabel sein, nicht dessen Implementierung.
Wenn man die nicht für jede Zielplattform neu schreiben will, ist es
schon sinnvoll, sie auch portabel zu gestalten.
> Insbesondere der 14 Byte große Ethernet-Header führt zu einem schönen> Versatz, nämlich wenn der Compiler davon ausgeht, dass die Struktur, die> den IP-Header bestimmt, an einer 4-Byte-Grenze beginnt...
Ich erinnere mich da an Performance-Probleme mit bestimmten
billig-Ethernet-Karten, weil aufgrund dieses Alignment-Problems kein DMA
benutzt werden konnte und empfangene Pakete immer "von Hand" in einen
Speicherblock mit richtigem Alignment umkopiert werden mussten.
Jay schrieb:> Die ungültigen Vorgängerversionen kann man durchaus noch kaufen.> Allerdings macht es einem die ISO ein bisschen schwer. Alte Versionen> gibt es nur noch auf Papier und auf Anfrage.
Ah, ok. Das war mir nicht bekannt. Ich hatte nur gesehen, daß sie im
Webshop nicht mehr verfügbar sind.
> Die Gültigkeit liegt sowieso im Auge des Betrachters.
Jede neue Version der ISO-Norm sagt gleich auf der ersten Seite, dass
sie mit ihrem Erscheinen alle vorhergehenden Versionen komplett ersetzt
und für ungültig erklärt.
> Wenn man sich zum Beispiel in einem Vertrag auf eine Version geeinigt> hat, dann ist genau diese für die Vertragserfüllung gültig.
Das schon. Der Vertrag wäre dann quasi der Compiler, den man gekauft
hat, bevor die neue Version rausgekommen ist. Daß dieser alte Compiler
nicht plötzlich die neue Version unterstüzt, ist ja klar. Neue Compiler
sollten das aber eigentlich schon. Ist ja bei anderen ISO-Normen auch
so.
Meiner Meinung nach kann sich eine aktuelle Version eines Compilers
nicht ISO- (oder ANSI-) C-konform schimpfen, wenn er nicht die aktuelle
Version unterstützt.