Hallo zusammen! Habe gerade einen Code von einem MSP430 auf einen Cortex M3 portiert. Im Code werden eigenen Typdefinitionen und Strukturen verwendet, die "unsigned char, unsigned int" enthalten. Beim 16bit Architektur MSP430 bekam ich mit "sizeof(<mytypedef>)" die gewünschte korrekte Größe von 2 (2Byte; 16 Bit raus). Beim 32biter Cortex allerdings 4 (4Byte, 32bit) raus. Damit passt natürlich nichts mehr. Auf die online verfügbaren Tabellen kann man sich nicht auch blind verlassen: http://homepage.univie.ac.at/Heinz.Kabelka/edv-ueb/variabl.htm http://pronix.linuxdelta.de/C/standard_C/c_programmierung_8.shtml Welche Datentypen muss ich verwenden, dass auf allen Prozessorarchitekturen das gleiche raus kommt!? Danke & Gruß Bernhard
Hallo, wenn der Compiler C99 kann, dann nimm uint16_t für unsigned int 16 bit Breite... #include <stdint.h> nicht vergessen... Gruß, Bernhard
Die Größe eines Integer hängt immer von der Prozessorarchitektur ab. So ist sie auf einer 16-Bit Maschine eben 16 Bit, auf einer 32 Bit Maschine 32 Bit. Daran kannst Du nichts tun. Um Deinen Code portabel zu halten, kannst du z.B. folgendes machen: #define u16 unsigned int (auf 16 Bit Maschinen) #define u16 unsigned short (auf 32 Bit Maschinen) Im Code benutzt Du dann immer u16 als Datentyp. Somit musst Du beim Portieren nur noch das Makro anpassen und alle Datentypen passen wieder
Hab da was gefunden: http://pronix.linuxdelta.de/C/standard_C/c_programmierung_8.shtml Punkt 8.5 > Wollen Sie Programme schreiben, die auf 16-Bit- und 32-Bit-Systemen > richtig laufen sollen, verwenden Sie für Ganzzahltypen die Typen long und > short und verzichten dabei ganz auf den Datentyp int, da dieser wie > gezeigt unterschiedliche Zahlenräume auf verschiedenen Systemen abdeckt. Mit dem, was Guest schrieb im Beitrag #3288534 geschrieben hat: > #define u16 unsigned int (auf 16 Bit Maschinen) > #define u16 unsigned short (auf 32 Bit Maschinen) sollte das gelten und zukünftige Probleme lösen. Könnte ich dann nicht auch meine eigenen defines machen, die dann uint16_t heißen und ich somit unabhängig von der <stdint.h> bin!? Wieso eigentlich #define und nicht typdef!? Danke & Gruß Bernhard
Coder schrieb: > Hab da was gefunden: > http://pronix.linuxdelta.de/C/standard_C/c_program... > Punkt 8.5 >> Wollen Sie Programme schreiben, die auf 16-Bit- und 32-Bit-Systemen >> richtig laufen sollen, verwenden Sie für Ganzzahltypen die Typen long und >> short und verzichten dabei ganz auf den Datentyp int, da dieser wie >> gezeigt unterschiedliche Zahlenräume auf verschiedenen Systemen abdeckt. > long und short sind genauso maschinenabhängig wie int. Die saubere und portable Lösung wurde schon genannnt : stdint.h > Mit dem, was Guest schrieb im Beitrag #3288534 geschrieben hat: >> #define u16 unsigned int (auf 16 Bit Maschinen) >> #define u16 unsigned short (auf 32 Bit Maschinen) > > sollte das gelten und zukünftige Probleme lösen. > Warum das Rad neu erfinden. Verwende Standards! > Könnte ich dann nicht auch meine eigenen defines machen, die dann > uint16_t heißen und ich somit unabhängig von der <stdint.h> bin!? > Warum? Welchen alten Compiler will man heute noch unterstützen der stdint.h nicht kennt? > Wieso eigentlich #define und nicht typdef!? > > Danke & Gruß > > Bernhard
Coder schrieb: > Hab da was gefunden: > http://pronix.linuxdelta.de/C/standard_C/c_programmierung_8.shtml > Punkt 8.5 >> Wollen Sie Programme schreiben, die auf 16-Bit- und 32-Bit-Systemen >> richtig laufen sollen, verwenden Sie für Ganzzahltypen die Typen long und >> short und verzichten dabei ganz auf den Datentyp int, da dieser wie >> gezeigt unterschiedliche Zahlenräume auf verschiedenen Systemen abdeckt. long und short helfen dabei genau gar nichts. > Mit dem, was Guest schrieb im Beitrag #3288534 geschrieben hat: >> #define u16 unsigned int (auf 16 Bit Maschinen) >> #define u16 unsigned short (auf 32 Bit Maschinen) > > sollte das gelten und zukünftige Probleme lösen. Ja, ist aber quatsch. Genau dafür gibt es die stdint Datentypen uint8_t unsigned int mit 8 Bit int8_t signed int mit 8 Bit uint16_t unsigned int mit 16 Bit int16_t signed int mit 16 Bit ... mit diesen Eigen-Define-Sachen hat man sich jahrelang über Wasser gehalten, bis entsprechende typedefs in den Standard mit aufgenommen wurden. Also benutze sie auch! > Könnte ich dann nicht auch meine eigenen defines machen, die dann > uint16_t heißen und ich somit unabhängig von der <stdint.h> bin!? Was soll dir das bringen? Wozu ein eigenes Süppchen kochen, das auch nicht ander schmeckt als das bereits vorhandene? Und wenn du welche machst, dann machst du dir typedefs und keine #define. Im Übrigen: schau in dein stdint.h mit einem Editor hinein! das ist auch nur ein Textfile, das man sich im Editor ansehen kann. Das SIND einfach nur typedefs, die auf die jeweilige Maschine/Compiler abgestimmt sind. Mehr ist das nicht. Hast du kein stdint.h, dann machst du dir eben selber eines auf der Zielmaschine. http://www.cplusplus.com/reference/cstdint/ > Wieso eigentlich #define und nicht typdef!? Musst du ihn selber fragen. Meine Vermutung: weil er nicht weiß, dass es sowas typedef gibt.
Coder schrieb: > > Wieso eigentlich #define und nicht typdef!? In diesem einfachen Fall ist es egal, was Du verwendest. Die #defines werden vom C-Präprozessor/C-Precompiler ersetzt. #define u16 unsigned int // (auf 16 Bit Maschinen) #define u16 unsigned short // (auf 32 Bit Maschinen) oder typedef unsigned int u16 // (auf 16 Bit Maschinen) typedef unsigned short u16 // (auf 32 Bit Maschinen)
Hier gibt es einen ausführlichen Artikel zu dem Thema: http://www.mikrocontroller.net/articles/Plattformunabh%C3%A4ngige_Programmierung_in_C
Guest schrieb: > #define u16 unsigned int (auf 16 Bit Maschinen) > #define u16 unsigned short (auf 32 Bit Maschinen) Sowas sollte man nicht mehr machen. Wenn, dann die Standarddatentypen verwenden -- also uint16_t, und nicht "u16". Sollte der Compiler keine stdint.h haben, dann definiert man sich diese Datentypen selber -- aber mit genau diesen Namen. Keine anderen, eigenen Namen verwenden.
Rufus Τ. Firefly schrieb: > Guest schrieb: >> #define u16 unsigned int (auf 16 Bit Maschinen) >> #define u16 unsigned short (auf 32 Bit Maschinen) > > Sowas sollte man nicht mehr machen. > > Wenn, dann die Standarddatentypen verwenden -- also uint16_t, und nicht > "u16". > > Sollte der Compiler keine stdint.h haben, dann definiert man sich > diese Datentypen selber -- aber mit genau diesen Namen. > > Keine anderen, eigenen Namen verwenden. Sorry, das zeigt wieder die große Klasse von C. :-(
> > Keine anderen, eigenen Namen verwenden. > > Sorry, das zeigt wieder die große Klasse von C. :-( In anderen, besseren Sprachen, kann man keine dämlichen Namen vergeben? Das ist ja endlich mal ein Fortschritt! Mit so einer tollen Sprache kann man dann vielleicht endlich Forensoftware schreiben, die bescheuertes Getrolle wegwirft.
Klaus Wachtler schrieb: >> > Keine anderen, eigenen Namen verwenden. >> >> Sorry, das zeigt wieder die große Klasse von C. :-( > > In anderen, besseren Sprachen, kann man keine dämlichen Namen vergeben? > Das ist ja endlich mal ein Fortschritt! > > Mit so einer tollen Sprache kann man dann vielleicht endlich > Forensoftware schreiben, die bescheuertes Getrolle wegwirft. Es geht nicht um die Namen, sondern dass der Code nicht portabel ist.
DirkZ schrieb: > In diesem einfachen Fall ist es egal, was Du verwendest. Die #defines > werden vom C-Präprozessor/C-Precompiler ersetzt. Nein! typedef ist in jedem Fall vorzuziehen. Grund:
1 | typedef int blub; |
2 | |
3 | void foo () { |
4 | char blub; |
5 | }
|
Geht, aber
1 | #define blub int
|
2 | |
3 | void foo () { |
4 | char blub; |
5 | }
|
Geht nicht! Denn typedefs haben Scope (d.h. werden von inneren Deklarationen überschrieben/versteckt), Macros sind immer global und produzieren hier auch noch unlesbare Fehlermeldungen. Und falls jemand auf die Idee kommt den C-Header, in dem die Typen definiert sidn, aus einem C++ Code zu #includen kann er einen "namespace" drumherum packen und zB. TheCLibrary::blub schreiben; bei Macros geht auch das schief. Und ja, <stdint.h> ist ebenfalls der eigenen Definition von u16 etc. vorzuziehen.
> Es geht nicht um die Namen, sondern dass der Code nicht portabel ist.
In C gibt es portable Dinge und nicht portable.
Wenn man die nicht portablen nutzt und sich darauf verlässt, ist der
Code halt nicht portable.
Da hat aber dann der Schuld, der so programmiert.
Du wirst kaum eine Sprache finden, die halbwegs HW-nahe Dinge zulässt,
andererseits aber unportablen Code sicher verindert. Wie soll das gehen?
modern schrieb: > Es geht nicht um die Namen, sondern dass der Code nicht portabel ist. java ist zB viel besser, da sind Array-Größen/Indices immer einfache 32bit-Ints. D.h. man kann nur max 2^32 Einträge große Arrays erstellen, selbst auf 64bit-Plattformen. Total plattformunabhängig! Und eine ganze Reihe I/O-Funktionen verwenden ebenfalls 32bit-Ints, können also nur bit max 2GB-Dateien umgehen.
Kindergärtner schrieb: > DirkZ schrieb: >> In diesem einfachen Fall ist es egal, was Du verwendest. Die #defines >> werden vom C-Präprozessor/C-Precompiler ersetzt. > Nein! > typedef ist in jedem Fall vorzuziehen. Grund:typedef int blub; > ... So isses!
... während man in C, C++ in solchen Fällen size_t und off_t (wimre) verwendet, was je nach Plattform zB 32 oder 64bit groß ist und somit alles kann, was die Hardware kann.
Kindergärtner schrieb: > modern schrieb: >> Es geht nicht um die Namen, sondern dass der Code nicht portabel ist. > java ist zB viel besser, da sind Array-Größen/Indices immer einfache > 32bit-Ints. D.h. man kann nur max 2^32 Einträge große Arrays erstellen, > selbst auf 64bit-Plattformen. Total plattformunabhängig! Und eine ganze > Reihe I/O-Funktionen verwenden ebenfalls 32bit-Ints, können also nur bit > max 2GB-Dateien umgehen. Eben deshalb wird Java auch immer gerne und erfolgreich genommen, um ernsthafte Dinge wie ein Betriebssystem, FE-Simulationen für Crashtests oder ähnliches zu programmieren.
Klaus Wachtler schrieb: > um ernsthafte Dinge wie ein Betriebssystem, FE-Simulationen Das führt selbst bei der gewöhnlichen 08/15 "Business"-Anwendung für ein bisschen Daten Hin&Herschaufeln zu Problemen...
Klaus Wachtler schrieb: >> Es geht nicht um die Namen, sondern dass der Code nicht portabel > ist. > > In C gibt es portable Dinge und nicht portable. > > Wenn man die nicht portablen nutzt und sich darauf verlässt, ist der > Code halt nicht portable. > Da hat aber dann der Schuld, der so programmiert. > > Du wirst kaum eine Sprache finden, die halbwegs HW-nahe Dinge zulässt, > andererseits aber unportablen Code sicher verindert. Wie soll das gehen? Wo ist C so hardware nahe, dass es nicht portabel geht? Das Beispiel hier zeigt, wie veraltert das Ganze ist.
Hi, ohne jetzt alles gelesen zu haben: Schau dir zum Cortex mal die CMSIS an (core_cm3.h). Dort wird die stdint.h bereits verwendet, da die (u)int<n>_t Datentypen die sicherste Möglichkeit der Kompatibilität darstellen. So musst du dich bei kommenden Codeänderungen nicht um das Umstellen irgendwelcher #defines kümmern, was mEn. sehr fehlerträchtig sein kann. Hast du Strukturen, die du serialisiert, vergiss bitte __packed nicht, sonst gehts auf der Gegenstelle schief (Stichwort padding). VG, /th.
modern schrieb: > Das Beispiel > hier zeigt, wie veraltert das Ganze ist. Warum? Das Beispiel zeigt, dass der Original-Code einen Fehler hatte, der auf der Ursprungs-Plattform nicht aufgefallen ist. Aber dennoch da war. Jetzt beim Portieren auf eine 32-Bit-Plattform fällt der Fehler auf. Jetzt muss er behoben werden und kann nicht mehr ignoriert werden. d.H. C hat sich hier nur zuschulden kommen lassen, dass der 16-Bit-C-Compiler den Denkfehler des Programmierers, der aus mangelnder Kentniss der C-Datentypen resultierte, nicht direkt erkannt und verhindert hat. => Zeig mir den Compiler der das könnte.
modern schrieb: > Wo ist C so hardware nahe, dass es nicht portabel geht? zb indem es die Fähigkeiten einer CPU dahingehend ausnutzt, dass es für int zwar gewissen Mindeststandards vorschreibt, auf der anderen Seite aber dem Programm ermöglicht, mit dem CPU Leib- und Magen- Lieblingsdatentyp zu operieren, der dann auch auf dieser Maschine am schnellsten abgearbeitet werden kann. Wozu eine 64 Bit CPU künstlich auf 16 Bit Operationen runterbremsen, wenn es dazu alle Operanden bzw. Ergebnisse erst mal auf 16 Bit runtercasten muss? Und da alles nur, weil vorgeschrieben ist, dass ein int 16 und nur 16 Bit haben darf? Lass sie in 64 Bit rechnen und gut ists. > Das Beispiel > hier zeigt, wie veraltert das Ganze ist. Wenn überhaupt, dann zeigt das Beispiel nur, dass C schon einige Jährchen um Buckel hat, aber flexibel genug ist um neue Anforderungen auch ohne compilerinterne Spracherweiterungen unterzubringen. Irgendwann hat man erkannt, dass diese Nicht-Normierung der Bitzahl eines int zu einem Problem werden kann und hat sich dafür einen standardisierten Mechanismus ausgedacht. Nur: benutzen müsste man ihn halt. Kommt es dir als Programmierer auf die genauen Bitzahlen an, dann verwendet man die Datentypen aus stdint.h. Sind einem die Bitzahlen egal und will man maximale Rechengeschwindigkeit dann nimmt man plain vanilla int. Ist doch ganz einfach. Klar gibt es in C Altlasten und Dinge, die man heute anders machen würde. Aber für dieses Problem gibt es mit stdint.h eine nicht so schlechte Lösung. Das hier ist also kein Argument.
Ebenfalls nicht zu vergessen sind die in C99 und neuer spezifizierten Datentypen int_leastN_t bzw. uint_leastN_t int_fastN_t bzw. uint_fastN_t mit N aus {8, 16, 32, 64}. Z.B. liefert ein int_least8_t den kleinsten Typ mit mindestens 8 Bit Breite, d.h. fast immer einen 8 Bit-Wert. Für Zählschleifen ist jedoch int_fast8_t besonders interessant, da hierbei der Compiler die Möglichkeit hat, einen möglichst CPU-konformen Typ auszuwählen, solange er die genannte Mindestbreite besitzt. Das wären auf einem ARM z.B. 32 Bit. Auf diese Art und Weise kann man plattformunabhängigen Code schreiben, der nicht mit unnötigen Einschränkungen hinsichtlich der Optimierung belegt ist. Natürlich muss der Programmierer bei jeder Variablendeklaration zwischen int/least/fast entscheiden.
Ich bin ja auf das Chaos gespannt, das eintritt, wenn man in Java endlich zugibt, daß 32 Bit manchmal zu knapp sind :-)
Karl Heinz Buchegger schrieb: > dann nimmt man plain vanilla > int. Oder zB ein uint_fast16_t , der garantiert mindestens 16bit hat aber eben ggf in mehr Bits rechnet, um die CPU besser auszunutzen. Das Overflow-Verhalten ist dann allerdings nicht notwendigerweise das eines 16bit-UInt. Die Standarddatentypen wie short bieten zwar ähnliche Garantieren, aber bei den (u)int_fast* Typen kann man mMn leichter sehen wie viele Bits man will.
Klaus Wachtler schrieb: > Ich bin ja auf das Chaos gespannt, das eintritt, wenn man in Java > endlich zugibt, daß 32 Bit manchmal zu knapp sind :-) Wird auch nicht anders, als die Situation in C vor einigen Jahren/Jahrzehnten war. Es gibt dafür nun mal keine Lösung. Entweder man nagelt die Bitzahlen fest, dann zieht man sich Limits ein bzw. erlegt dem Optimierer unnötige Schranken auf. Oder man nagelt sie nicht fest, dann hat man eben das Problem, dass man nicht mit gesicherten Bitzahlen operieren kann wenn man das braucht. 'One size fits all' funktioniert bei Baseballkappen. Aber auch nur dort.
Karl Heinz Buchegger schrieb: > Wird auch nicht anders, als die Situation in C vor einigen > Jahren/Jahrzehnten war. Nein, ich denke es wird noch viel lustiger - da andere Klientel :-)
Noch was interessantes Die 28xxx-Serie Prozessoren von TI sind reine 16 Bit Maschinen, d.h. es gibt kein Byte mit 8 Bit. Der Speicher ist immer 16 Bit breit. sizeof(short int ) = 1 , also 16 Bit sizeof(char) = 1 , also 16 Bit sizeof(long) = 2 , also 32 Bit. Auch so etwas gibt es. Und wer portabel programmieren möchte, sollte auch diese Architekturen in Betracht ziehen.
PittyJ schrieb: > Die 28xxx-Serie Prozessoren von TI sind reine 16 Bit Maschinen, d.h. es > gibt kein Byte mit 8 Bit. Der Speicher ist immer 16 Bit breit. Und in BCPL gibt es als Datentyp nur das "Maschinenwort". Kein Byte, int und long.
PittyJ schrieb: > Die 28xxx-Serie Prozessoren von TI sind reine 16 Bit Maschinen, d.h. es > gibt kein Byte mit 8 Bit. Der Speicher ist immer 16 Bit breit. > sizeof(short int ) = 1 , also 16 Bit > sizeof(char) = 1 , also 16 Bit > sizeof(long) = 2 , also 32 Bit. Beim TMS320C40 (32-Bit-FP-DSP) war
1 | sizeof(char) == sizeof(short) == sizeof(int) |
2 | == sizeof(long) == sizeof(float) == sizeof(double) == 1 |
:)
G++ schrieb im Beitrag #3289666: > Bin bin dafür, einfach mal für einen Tag alles, was in C(++) geschrieben > wurde, verschwinden zu lassen. Trolloge schrieb im Beitrag #3289671: > Oder wir leben einen Tag ohne Auto Nicht "Oder". Der Vorschlag von G++ impliziert bereits, dass alle moderneren Autos stehenbleiben, da deren Steuergeräte ebenfalls in C programmiert sind ;-)
> Nicht "Oder". Der Vorschlag von G++ impliziert bereits, dass alle > moderneren Autos stehenbleiben, da deren Steuergeräte ebenfalls in C > programmiert sind ;-) Das meinst du doch nicht ernst, oder? Da er sich schon XY++ nennt, sollte er auch wissen, dass C nicht C++ ist. Und um alle zu beruhigen: C sollte nicht verboten werden. Man möge nur akzeptieren, dass es auch andere Dinge gibt. Und wer die nicht kennt und noch nicht ausprobiert hat, möge die Finger still halten.
Tolloge schrieb im Beitrag #3289353: > Klaus Wachtler schrieb: >> Karl Heinz Buchegger schrieb: >>> Wird auch nicht anders, als die Situation in C vor einigen >>> Jahren/Jahrzehnten war. >> >> Nein, ich denke es wird noch viel lustiger - da andere Klientel :-) > > Tja, der Klaus denkt, die C Programmierer sind die besseren. Möge er > weiter in der Höhle wohnen. Was ist denn dein Problem? In Gegensatz zu Java-Programmieren, müssen C-Programmierer solche Sachen wissen und sich ständig damit auseinander setzen. Frag mal einen Java-Programmierer, wie breit ein int ist. "I N T - 3 Buchstaben." mfg.
Klaus Wachtler schrieb im Beitrag #3289963: > Trolloge schrieb: >> Und um alle zu beruhigen: > > 1. weiß ich nicht, wer sich aufregt außer dir Er regt sich halt auf, weil sein Trollen nicht so richtig funktioniert. Aber mal ganz zurück zum Anfang: Coder schrieb: > Habe gerade einen Code von einem MSP430 auf einen Cortex M3 portiert. > Im Code werden eigenen Typdefinitionen und Strukturen verwendet, die > "unsigned char, unsigned int" enthalten. > Beim 16bit Architektur MSP430 bekam ich mit "sizeof(<mytypedef>)" die > gewünschte korrekte Größe von 2 (2Byte; 16 Bit raus). Beim 32biter > Cortex allerdings 4 (4Byte, 32bit) raus. Damit passt natürlich nichts > mehr. Man beachte, dass auch von Strukturen die Rede ist, die nicht mehr passen. Der erfahrene Programmierer weiß, dass es in Strukturen Padding geben kann. Der erfahrene Programmierer weiß auch, dass die Byte-Order zwischen Plattformen unterschiedlich sein kann. Der erfahrene Programmierer weiß daher, im Gegensatz zum Trolltrottel, dass die naive Verwendung von Strukturen um ein reproduzierbares Datenformat zu bekommen, z.B. zum Datenaustausch zwischen Plattformen, eine ziemlich schlechte Idee ist - auch bekannt als übler Programmierfehler.
Du meinst, dann wird es besser? :-) Im Ernst: dummes Rumgetrolle wie in diesem Thread heute wieder macht jede Diskussion platt, das ist schade. Aber Löschen rettet ebensowenig, wie jeden Müll zu akzeptieren. Dummheit kann ma nicht ausrotten, und Trolle sind halt da und haben viel Zeit und Langeweile. Insofern sind nicht die Moderatoren schuld, sondern sie sind in der undankbaren Lage, zwischen zwei Übeln wählen zu müssen.
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.