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?!
Gibts garantiert auch bei Keil, weil Standard: #include <stdint.h>
:
Bearbeitet durch User
Hein Mück aus Bremerhaven schrieb: > Woher kennt der GCC uint32_t? Aus der <stdint.h> die du inkludieren musst. > Ist das über haupt C konform?! Ja.
Bin mir nicht sicher, ob ich die stdint.h includiert habe. Muss mal am Montag schauen..
Bei Atmel kriegst du die als Nebeneffekt anderer Includes meist automatisch mit rein. Bei Keil möglicherweise nicht.
Hein Mück aus Bremerhaven schrieb: > Ist das über haupt C konform?! Warum sollte es nicht C konform sein? Wer will dir verbieten in deinen Code ein
1 | #define uint32_t unsigned long int |
einzubauen.
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!
meckerziege schrieb: > Beispiel: Auf nem 64-bit Rechner und GCC, ist int 32 bit breit und ein > long int 64-bit breit! In Linux korrekt, in Windows nicht: http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.