Hallo,
ja wie der Titel schon sagt, würde ich gerne den Unterschied zwischen
den beiden Datentypdeklarationen "uint8_t" und "unsigned int" erfahren.
Beides sind doch 8 Bit vorzeichenlose Variablentypen. Beide müssten
gleich "funktionieren". Jedoch scheint letztgenanntere bei Weitem mehr
Programmcode beim kompilieren zu erzeugen. Warum das? Wo ist denn nun
der Unterschied zw. beiden?
Vielen Dank!
> ein "unsigned integer" hat auf x86> vier Bytes, also 32 Bits.
Sofern x86 = 386 und aufwärts im 32-Bit-Modus.
Bei üblichen 8-Bit-Systemen wie AVR, MSP430 etc. ist ein unsigned
integer 16 Bit groß, bei x86 im 16-Bit-Modus ("real mode") auch.
Was Du schreibst, ist doch schon der Widerspruch in sich. Der integer
(egal ob signed oder unsigned) ist eben NICHT 8 Bit sondern 16 bzw. 32
Bit gross. Er entspricht der "natürlichen" Verarbeitungsbreite des
Prozessors. So, und nun lasst uns darüber diskutieren, was das konkret
bedeutet.
Das bedeutet, daß ein Mega 8 mit "natürlicher" Breite von 8 Bit
(daher auch MEGA 8 ;)) ein Integer von 8 Bit hat.
(Mega 16 dann 16 Bit Integer)
Nur seltsam beim Tiny 13 !
Gruß hans
Tom wrote:
> Ja, aber warum ist ein unsigned int 2 bzw. 4 Byte groß? Es handelt sich> doch hier um einen 8 Bit, also 1 Byte Datentyp? Versteh ich nicht ganz.
Nein, ein "int" egal ob signed oder nicht, bezeichnet zunächst nur den
Datentyp und nicht die Bitbreite. Tatsächlich handelt es bei "int" nur
in den seltensten Fällen um 8Bit. Für sowas ist in der Regel der
Datentyp "char" zuständig. Aber auch hier ist die Bitbreite
hauptsächlich vom System und Plattform abhängig.
Nur "uint8_t" ist hier explizit, gehört damit aber wohl nicht zum
Standard, da C ursprünglich als Programmiersprache vorallem portabilität
bringen sollte. Unter diesen Gesichtspunkten spielt die Bitbreite eines
Datentyps eine nur untergeortnete Rolle.
Der Unterschied:
'int' ist in der Sprache C/C++ wie folgt definiert:
sizeof(long) >= sizeof(int) >= sizeof(short)
Die exakte Bit-Größe ist also nicht festgelegt. Sie hängt vom Compiler
(nicht vom Prozessor) ab.
Ein int8_t ist dafür immer 8 Bit Groß, ist aber, wie schon monarch35
erwähnte, kein Standard-Datentyp der Sprache.
Gruß
hans wrote:
> Das bedeutet, daß ein Mega 8 mit "natürlicher" Breite von 8 Bit> (daher auch MEGA 8 ;)) ein Integer von 8 Bit hat.> (Mega 16 dann 16 Bit Integer)>> Nur seltsam beim Tiny 13 !
Richtig interessant wird so eine Betrachtung erst beim ATtiny861!
lol?
Diese uint8_t oder auch int8_t, etc. sind selbstdefinierte Typen aus der
AVRlib. Erspart geringfügig Tipparbeit. Ein uint8_t ist schlicht ein
unsigned char, ein int8_t ist ein char. Mehr nicht. Achja, ein 'int'
(integer) ist auf dem AVR 16bit breit. Ich habe es mir mittlerweile
angewöhnt, die bei C üblichen Typen-Bezeichner zu verwenden. Da braucht
man sich dann nicht umzugewöhnen.
Gruß
Jadeclaw.
Jadeclaw Dinosaur wrote:
> Diese uint8_t oder auch int8_t, etc. sind selbstdefinierte Typen aus der> AVRlib.
Neee, sind es nicht. Die gehören zur GCC Standardlibrary.
Beziehungsweise sogar zum C-Standard.
> Erspart geringfügig Tipparbeit. Ein uint8_t ist schlicht ein> unsigned char, ein int8_t ist ein char. Mehr nicht. Achja, ein 'int'> (integer) ist auf dem AVR 16bit breit.
Es erspart nicht (nur) Tipparbeit. Hauptsächlich soll man damit die
Programme weitgehend portabel halten. Ein großer Vorteil ist aber auch,
dass man der Variable den Wertebereich sofort ansieht, ohne großartig
suchen zu müssen, wie dieser wäre.
Jadeclaw Dinosaur wrote:
> Diese uint8_t oder auch int8_t, etc. sind selbstdefinierte Typen aus der> AVRlib. Erspart geringfügig Tipparbeit. Ein uint8_t ist schlicht ein> unsigned char, ein int8_t ist ein char. Mehr nicht. Achja, ein 'int'> (integer) ist auf dem AVR 16bit breit.
Da hast du natürlich recht. In der uC-Welt spielt es ohnehin keine
Rolle, ob man sich an Standards hält oder nicht, da der Code meist sehr
Hardware- bzw Plattformabhängig ist.
Wer allerdings portabel bleiben will, bzw die Anpassung auf andere
mögliche Hardware vereinfachen will, sollte bei den "selbstdefinierten"
Datentypen zurückgreifen, wenn eine Variable bitbreitenabhängig wird.
Simon K. wrote:
.
> Neee, sind es nicht. Die gehören zur GCC Standardlibrary.> Beziehungsweise sogar zum C-Standard.hust sorry, aber das stimmt ganz gewiss nicht!
Standarddatentypen im Ganzzahlenbereich sind char, short, int und long.
Mehr nicht! Ihre Bitbreiten sind zur Compile-Zeit festgelegt und laut
Ansi- standard in der limits.h festgelegt bzw abrufbar.
Bezeichner wie "uint8_t" haben sich lediglich als Beiwerk zum Standard
durchgesetzt.
mal eine Frage zur Portabilität: hat das wirklich schon mal einer
gemacht? Also ein Programm, z.B. für den 8051, auf AVR oder M16 laufen
lassen? Also ich noch nicht :-)
Niels Hüsken wrote:
> Simon K. wrote:> .>> Neee, sind es nicht. Die gehören zur GCC Standardlibrary.>> Beziehungsweise sogar zum C-Standard.>> hust sorry, aber das stimmt ganz gewiss nicht!> Standarddatentypen im Ganzzahlenbereich sind char, short, int und long.> Mehr nicht! Ihre Bitbreiten sind zur Compile-Zeit festgelegt und laut> Ansi- standard in der limits.h festgelegt bzw abrufbar.>> Bezeichner wie "uint8_t" haben sich lediglich als Beiwerk zum Standard> durchgesetzt.
Was stimmt nicht?
stdint.h is a header file in the C standard library introduced in the
C99 standard library section 7.18 to allow programmers to write more
portable code by providing a set of typedefs that specify exact-width
integer types, together with the defined minimum and maximum allowable
values for each type, using macros.
http://en.wikipedia.org/wiki/Stdint.h
crazy horse wrote:
> mal eine Frage zur Portabilität: hat das wirklich schon mal einer> gemacht? Also ein Programm, z.B. für den 8051, auf AVR oder M16 laufen> lassen? Also ich noch nicht :-)
Das hängt natürlich vom Bedarf ab, da hierfür ein mehr oder
minder-erheblicher Aufwand betrieben werden muss. Aber ich halte es auf
keinen Fall für undenkbar, daß man hardwarespezifische Programmteile in
austauschbare Header packt um damit eine mögliche Portierung zu
vereinfachen.
tja, dann muss man aber von Anfang an genau drauf achten. Meine Frage
war ja auch nicht, ob es geht (ja, dass geht), sondern ob es schon mal
jemand gebraucht/gemacht hat?
Der C99-Standard wurde nachträglich zum bestehenden ISO-Standard
adaptiert. In meinen Augen ist der Grauzone, da längst nicht alle
Compiler diesen Standard implementieren.
Zugegeben, beim GCC scheint man jedoch auf der sicheren Seite zu sein,
was die implementierung der so genannten exact-width-integer Typen
betrifft.
Das ein 'int' der 'natürlichen' Wortbreite des Prozessors entspricht
war vielleicht mal so gedacht, trifft aber in der Realität nicht zu.
Der C-Standard schreibt lediglich eine Mindestbreite von 16Bit vor.
Auf vielen Platformen entspricht die Größe des ints tatsächlich
der Wortbreite. Spätestens bei den 64Bit Architekturen ist da aber
Schluß. Dort hat der int üblicherweise nur 32 Bits, der long Typ ist
aber 64 Bits groß.
Den int bei 64-Bit Architekturen bei 32 Bits zu belassen ist aber
sicherlich sinnvoll. Bei der Mehrheit der existierenden 32Bit
Programme würde die Umstellung auf 64-Bit sonst zu einem unnötigen
Speicherverbrauch führen - sofern sie überhaupt laufen würden.
> mal eine Frage zur Portabilität: hat das wirklich schon mal einer> gemacht? Also ein Programm, z.B. für den 8051, auf AVR oder M16 laufen> lassen? Also ich noch nicht :-)
Das ist nicht ungewöhnlich. Algorithmen sind platformunabhängig.
Wer mit mehreren Architekturen zu tun hat tut gut daran jene Code-Teile
die nicht wirklich hardwareabhängig sind möglichst portabel zu halten.
Das gängigste Vorgehensmodell bei Mikrocontrollern dürfte die HAL
(Hardware Abstraction Layer) sein. Dabei wird der Code in platform-
abhängige und platformunabhängige Teile Zerlegt. Wenn also z. B.
an einer Stelle auf einen Tastendruck gewartet werden soll würde
man im Code nicht direkt den Pin abfragen, sondern eine Funktion
wie z. B. hal_getKey() aufrufen. Diese wird hardwareabhängig
implementiert.
Der Hersteller Chipcon macht des sehr konsequent bei seinen
Beispielcodes.
Und natürlich gehört uint8_t zum C-Standard. Das sich nicht alle
Compiler daran halten (und auch nach neun Jahren bestenfalls C89
unterstützen) ist eine andere Geschichte. Da es sich bei den
neuen Datentypen aber nur um eine Handvoll typedefs handelt
dürfte das kein großes Problem darstellen.
USB 2.0 oder 100MBit Ethernet wird auch nicht von jedem Computer
unterstützt.
let wrote:
> Und natürlich gehört uint8_t zum C-Standard. Das sich nicht alle> Compiler daran halten (und auch nach neun Jahren bestenfalls C89> unterstützen) ist eine andere Geschichte.
Ich bleibe dabei: der C99-Standard ist ein Beiwerk, der in seinem vollen
Umfang nicht mal vom GCC unterstützt wird. Das sagt auch der
Wiki-Artikel:
"GCC, despite its extensive C99 support, is still not a completely
compliant implementation; some features are missing or do not work
correctly."
> Ich bleibe dabei: der C99-Standard ist ein Beiwerk, der in seinem vollen> Umfang nicht mal vom GCC unterstützt wird.
Es ist der Standard im Sinne von "Norm". Allerdings implementieren nur
sehr wenige Compiler diesen Standard, die meisten halten sich noch an
C89 ("ANSI-C").
> Ich bleibe dabei: der C99-Standard ist ein Beiwerk
Blödsinn. Der ist ganz brav 1999 als Nachfolger vom alten ANSI/ISO C
verabschiedet worden. Der hat alle höheren Weihen eines ISO-Standards:
http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=29237
ISO/IEC 9899:1999
Programming languages -- C
Stage 90.93
(Stage 90.93 bedeutet International Standard confirmed)
Für den alten Standard findet man
ISO/IEC 9899:1990
Programming languages -- C
Stage 95.99
(Stage 95.99 bedeutet Withdrawal of International Standard)
Übrigens, "withdrawel" war am 16.12.1999. Du kannst dir natürlich deine
eigene Lalala-Welt machen und von "Beiwerk" träumen. Das ändert nichts
daran, das C99 seit 1999 ein Standard ist und der alte Standard am 16.
Dezember 1999 zurückgezogen wurde.
Das Compilerbauer mal wieder nicht mit der Implementierung
hinterherkommen ist nichts neues. Das war schon beim ersten Standard von
1989 und beim C++ Standard so.
crazy horse wrote:
> tja, dann muss man aber von Anfang an genau drauf achten. Meine Frage> war ja auch nicht, ob es geht (ja, dass geht), sondern ob es schon mal> jemand gebraucht/gemacht hat?
Ja, teilweise. Man braucht das ziemlich schnell (bzw. es wird mit
den <stdint.h>-Typen nun endlich genormt), wenn man bestimmte Software
beispielsweise auf AVR und ARM (oder AVR32) einsetzen will. Da ist
dann auch noch ein wenig mehr Nachdenken angesagt: uint8_t ist dort
keineswegs überall sinnvoll, sondern in der Regel wird man besser
einen uint_fast8_t benutzen, d. h. der am schnellsten zu verarbeitende
Datentyp, der mindestens 8 bits breit ist. uint8_t dagegen ist dann
angebracht, wenn darin beispielsweise Daten eines externen Protokolls
unterzubringen sind. Falls das dann irgendjemand mal vorhaben sollte
auf einen TI 32-bit-DSP zu portieren, wird ihm der Compiler sofort
mitteilen, dass das nicht geht. Hätte der Programmierer statt uint8_t
dagegen "unsigned char" benutzt, wäre er stillschweigend auf die Nase
gefallen, obwohl sich alles compilieren lässt... (Wer's nicht kennt:
diese DSPs kennen keine 8-bit-Datentypen, sondern nur 32-bittige.
Damit ist auch ein "unsigned char" 32 bit breit.)
crazy horse schrob:
> tja, dann muss man aber von Anfang an genau drauf achten. Meine Frage> war ja auch nicht, ob es geht (ja, dass geht), sondern ob es schon mal> jemand gebraucht/gemacht hat?
Ja, allerdings "nur" um Grafik-Routinen, die für AVR gedacht waren, auf
einem PC zu testen. Dabei ging es nicht um ein komplettes Programm,
sondern nur um die fraglichen Module. Mit ein paar Makros hat man die
Hardwareabhängigkeit rausparametriesiert (falls man im Ansatz schon
drauf geachtet hat)
Beitrag "Vektor-Font in C"
Johann L. wrote:
> crazy horse schrob:>> tja, dann muss man aber von Anfang an genau drauf achten. Meine Frage>> war ja auch nicht, ob es geht (ja, dass geht), sondern ob es schon mal>> jemand gebraucht/gemacht hat?>> Ja, allerdings "nur" um Grafik-Routinen, die für AVR gedacht waren, auf> einem PC zu testen. Dabei ging es nicht um ein komplettes Programm,> sondern nur um die fraglichen Module. Mit ein paar Makros hat man die> Hardwareabhängigkeit rausparametriesiert (falls man im Ansatz schon> drauf geachtet hat)>> Beitrag "Vektor-Font in C"
Was vergleichbares habe ich auch mal gemacht für mein uFS-Filesystem
damals. Da konnte ich die Header/Sources auf dem PC schreiben/debuggen
und nachher problemlos mit dem AVR-GCC kompilieren.