Hallo! Also ich bin gerade dabei, mir langsam aber sicher C-Kenntnisse im Selbststudium beizubringen.. Möchte auch einige kleine Programme für einen AVR Controller schreiben. Nur komme ich als Anfänger einfach nicht klar mit all den Datentypen und deren bezeichnung im WinAVR. Wie z.B.: uint8_t Habe die include Datei durchforstet, welche mir am Ehesten Infos liefern könnte und zwar die "inttypes.h". Darin fand ich z.B.: das: \code #include <inttypes.h> uint8_t smallval; int32_t longval; ... printf("The hexadecimal value of smallval is " PRIx8 ", the decimal value of longval is " PRId32 ".\n", smallval, longval); \endcode , was mir jedoch nicht wirklich weiter hilft. Wenn ich z.B.: ein paar Bytes in ein array speichern möchte, wobei ja jedes Byte ein Zeichen repräsentiert, welchen Datentyp nehme ich dazu? Nehmen wir an, ich will das Wort "TEST" irgendwo hin schicken (egal, ob per UART oder an irgendeinen Speicher, ....) Erstelle ich dann ein Array so? uint8_t array[3]; array[0] = "T"; array[1] = "E"; array[2] = "S"; array[3] = "T"; oder vielleicht so : unsigned char array[3]; array[0] = "T"; array[1] = "E"; array[2] = "S"; array[3] = "T"; Also die Frage ist, ist das egal, in welchem Datentyp ich so etwas speichere? Wenn ich "unsigned char" wähle, speicher ich tatsächlich den Buchstaben "T", richtig? Und wenn ich int wähle, wird wohl der Wert von "T" als dezimales "84" gespeichert, was binär wohl "10000100" bedeutet. Doch zurück zum eigentlichen Thema: Was bedeutet nun "uint8_t"? Einen int mit 8Bit Größe? Ach und gibt es irgendwo eine komplette Übersicht über die datentypen, die man häufig bei der AVR Programmierung mit dem avr-GCC verwendet/benötigt? Danke! Mit freundlichem Gruß... Roland
Schau doch hier mal nach: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Standardisierte_Integer.28Ganzzahl.29-Typen Ansonsten erlaubt C übrigens auch das: char text[] = "Test"; text ist dann 5 Bytes groß, da das Stringendezeichen \0 angehängt wird (Wie es sich gehört). Und: Wenn du ein array mit nur 3 Elementen definierst, darfst du nicht auf das vierte (array[3]) zugreifen! Das gibt in der Regel keine Fehlermeldung, du zerstörst aber ungewollt andere Daten. Es ist eher unwahrscheinlich, dass dein Programm dann das tut, was du willst. Gruß, Detlev
UINT8_t == unsigned char U -> unsigned ohne Vorzeichen INT -> Integer 8 -> Bit länge _t -> Kennung das ein Typ ist INT32 == signed long In der Datei "inttypes.h" sollte die Zuordnung drin stehen (typedef). Texte werden meist als signed verarbeitet. In deinem Fall geht es aber auch so. Variablen wie "int" sollte man nicht verwenden da sie vom Prozessor abhänig sind (16-64bit länge).
> Wenn ich "unsigned char" wähle, speicher ich tatsächlich den > Buchstaben "T", richtig? > > Und wenn ich int wähle, wird wohl der Wert von "T" als dezimales > "84" gespeichert, was binär wohl "10000100" bedeutet. Überraschung: in beiden Fällen wird der Zahlenwert 84 abgelegt. In einem Computer ist alles einfach nur eine Zahl. Es ist nur so, dass der Datentyp 'char' bei Ein/Ausgabe anders behandelt wird. Wird ein char ausgegeben, dann sorgt die Ausgabefunktion dafür, dass die 84 am Display für das aufleuchten der Pixel sorgen, die ein 'T' ergeben. Wird ein int ausgegeben, dann werden 2 Zeichen ausgegeben. Das Zeichen '8' gefolgt vom Zeichen '4'. Dein Gehirn macht daraus wieder 84. > Doch zurück zum eigentlichen Thema: Was bedeutet nun "uint8_t"? > Einen int mit 8Bit Größe? Yep. u unsigned (also nur positive Zahlen, keine negativen) uint unsigned int (also nur ganze Zahlen) uint8 mit 8 Bit (also: 0 bis 255) uint8_t das _t steht für: das ist ein Datentyp, um Verwechslungen mit Variablennamen zu vermeiden. > unsigned char array[3]; > array[0] = "T"; > array[1] = "E"; > array[2] = "S"; > array[3] = "T"; So ganz sicher nicht. Zaehl mal die Zuweisungen. Das sind 4 und nicht 3! In der Deklaration eines Arrays wird aber die Anzahl der benötigten Elemente angegeben und nicht der höchste zu erwartende Index. Wenn schon dann unsigned char array[4]; (Du solltest auch noch mal über den Unterschied von " und ' nach- denken. " benutzt man für einen kompletten String, ' benutzt man für ein einzelnes Zeichen). Aber das macht man eigentlich auch nicht. Denn mit so einem Array (das ja als string herhalten muss), kann man eher wenig anfangen (zumindest ist es lästig). In C gibt es die Konvention, dass ein String immer mit einem '\0' Zeichen aufhört. Alle Funktionen die mit Strings arbeiten, wissen das, zb auch die UART-String-Ausgabe Funktion. d.h. der String "TEST" besteht eigentlich aus 5 (!) Zeichen und nicht 4, da ja der abschliessende '\0' auch irgendwo gespeichert werden muss. unsigned char array[5]; array[0] = 'T'; array[1] = 'E'; array[2] = 'S'; array[3] = 'T'; array[4] = '\0'; Das ist aber noch mächtig umständlich. Viel einfacher ist: unsigned char array[5] = "TEST"; (geht aber nur bei Strings. Der Compiler sorgt dafür, dass im Prinzip genau die obigen 5 Zuweisungen gemacht werden. Das einzige, was jetzt noch lästig ist, ist dass ich den String "TEST" abzählen muss um zu wissen, wie gross das Array sein muss. unsigned char array[] = "TEST"; Jetzt übernimmt der Compiler das abzaehlen. Das hat den Vorteil, wenn sich der String "TEST" ändert, zb. auf "NOCH EIN TEST", dann muss nicht ich die Array-Größe abzählen, sondern das erledigt der Compiler für mich. > Also ich bin gerade dabei, mir langsam aber sicher C-Kenntnisse im > Selbststudium beizubringen.. Ich hoffe, du hast Literatur dafür. Online-Seiten und Web-Tutorials sind kein Ersatz für ein vernünftiges Buch.
Danke für all die Antworten! Ist echt ein super Forum hier!! Ja, ich bin dabei, mir ein Buch über ANSI - C zuzulegen. Also ich hab das ganze nun einigermaßen durchblickt , bis auf: 1.) unsigned char bezeichnet ja wohl ein Zeichen Ein Zeichen kann aber nicht "negativ" sein, oder? Aber wozu gibt es dann "signed char"? 2.) zu Dirks Aussage: " Variablen wie "int" sollte man nicht verwenden da sie vom Prozessor abhänig sind (16-64bit länge). " Ein Integer Wert aht also MINDESTENS 16 Bit? Hat uint8_t denn nicht nur 8 Bit? Ich meine, klar, ein unsigned int geht von "0" bis "65536", also muss er 16 Bit "breit" sein.. Dann ist allerdings diese Aussage (scheinbar) wieder Mist: "uint8 mit 8 Bit (also: 0 bis 255)" Grüße... Roland
> Aber wozu gibt es dann "signed char"? Das 'Problem' ist: In Deiner Vorstellung ist 'char' unweigerlich mit 'Zeichen' assoziert. Nun, ja. So falsch ist das auch wieder nicht, wenn man den Gedanken nicht zu ernst nimmt. In Wirklichkeit wäre für 'char' eine ganz andere Beschreibung angebracht: Ein 'char' nimmt kleine Zahlen auf, und wird bei Ein-/Ausgabe anders behandelt als die Datentypen für Zahlen. Aber: Ein 'char' ist auch nur ein Datentyp in dem Zahlen, eben kleine Zahlen, gespeichert sind. Man kann mit einem 'char' genauso rechnen wie mit einem int, long oder double. zu 2. Das Problem ist, dass nichts und niemand einem Compiler exakt vorschreibt, wieviele Bits ein char, int oder long den haben muss. In C ist das alles der Implementierung überlassen. Es existieren lediglich ein paar grundlegende Regeln. zb. das ein int mindestens soviele Bits haben muss wie ein char. Oder das ein long mindestens soviele Bits haben muss wie ein int. Noch nicht mal die Bitbreite eines char (normalerweise 8) ist festgelegt. Theoretisch kann ein char auch aus 9 oder 11 Bits bestehen. > Dann ist allerdings diese Aussage (scheinbar) wieder Mist: > "uint8 mit 8 Bit (also: 0 bis 255)" Wieso soll das Mist sein. Mit 8 Bit kann man bis 255 zählen. uint8 ist auf den meisten Maschinen ein Synonym für unsigned char. erst ein uint16 ist das was auf den meisten Maschinen ein unsigned int ist. Im Ur-C gab es nur die Datentypen char, int, long, float, double Wie gesagt: Für diese Datentypen gibt es zwar ein paar Regeln aber nichts verbindliches darüber, wieviele Bits da jeweils drinn sind. Das ist bei der normalen Programmierung tatsächlich eher irrelevant, wird aber bei der Programmierung von µC so richtig interessant. Da es aber im Ur-C dafür nichts Vernünftiges gab, hat man dann später zusätzliche Bezeichner eingeführt, aus deren Namen auch hervorgeht, über wieviele Bits der Datentyp eigentlich besteht. Damit hat man den Programmierer auch davon entbunden darüber nachzudenken, welchen Datentyp er tatsächlich braucht, wenn er einen unsigned mit 16 Bits haben will. Er schreibt einfach uint16_t, und gut ists. Das ein uint16_t auf manchen Maschinen einem 'unsigner long' entspricht, auf anderen wieder einem 'unsigned int', während es auf einer 3. Maschine ev. ein 'unsigned short int' ist, braucht in nicht mehr zu kümmern.
Wichtig ist noch: Ein uint8_t oder uint16_t oder wie sie alle heissen, sind keine eigenen Datentypen. Das sind lediglich typedef's für die Grunddatentypen. Im Grunde hätte man die auch 'SchnurDiBur' oder 'ASDF' nennen können. Nur ist es halt naheliegender, das Zeugs uint8_t oder uint16_t zu nennen.
Es wär doch irgendwie nett, wenn Programmer´s Notepad diese "typedef-Datentypen" trotzdem hervorheben bzw. blau schreiben würde.. Kann man das irgendwie veranlassen? Sonst wirds schnell mal unübersichtlich, wenn eine Funktion mehrere Parameter übergibt... Grüße...
Oh, tschuldigung, habs bereits gefunden unter Style--> Schemes-->Keywords ;-) Sry...
Bemerkung zu "char": ja, es soll ein Zeichen aufnehmen können. Anders als bei "int" (das immer ein Alias für "signed int" ist) ist aber bei char die Vorzeichenhaftigkeit/-losigkeit nicht im Standard vorgeschrieben, sodass eine Implementierung den Typ "char" wahlweise wie "signed char" oder wie "unsigned char" implementieren darf. Damit soll sie in die Lage versetzt werden, den Datentyp so zu wählen, wie es ihr auf Grund anderer Randbedingungen (Rechengeschwindigkeit, historische Nutzung von nicht-C-Implementierungen auf gleichem System) am besten gefällt. Die Randbedingung für die Größen von Datentypen sind übrigens (mal davon ausgehend, dass wir nur Maschinen mit Zweierkomplement- Darstellung für Integers betrachten): . char >= 8 bits . int >= 16 bits . short >= 16 bits . long >= 32 bits . long long >= 64 bits Sieht auf den ersten Blick einleuchtend aus, hat aber auch ein paar Pferdefüße, die man nicht auf den ersten Blick sieht. Insbesondere ist es halt durch den Standard nicht garantiert, dass es überhaupt einen Datentyp mit 8 Bit Breite geben muss. Gerüchtehalber soll es zumindest einige DSPs geben, die gar keine 8-bit-Zahlen verarbeiten können, bei denen ist dann sizeof(char) == sizeof(short) == sizeof(int) = 32. Der Vorteil der Benutzung der exact width integer types (wie uint8_t) ist es in diesem Falle, dass das Programm nicht wundersame Dinge zur Laufzeit macht, weil der Programmierer annahm, dass sein "unsigned char" von 255 auf 0 überrollt, sondern dass das Programm sich bereits mit einem compile time error verabschiedet, weil eine solche Maschine eben keinen uint8_t kennt.
Hallo Zusammen, ich habe ebenfalls den Datentyp uint8_t. Ist folgende Zuweisung richtig: uint8_t var=1; Nun möchte ich mir gerne den Inhalt über printf() ausgeben lassen. Wenn ich schreibe printf("variablenwert %d", &var); erscheint eine Warnung auf Grund des Datentyps. Was nehme ich denn anstelle von d um mir den Wert von var ausgeben zu lassen? Gruß Ange
1 | printf("variablenwert %d", var); |
Und bitte mache zukünftig für deine Fragen einen neuen Thread auf, und hänge dich nicht an einen anderen uralten Thread ran, schon gar nicht, wenn deine Frage praktisch nichts mit diesem alten Thread zu tun hat.
Stefan Ernst schrieb: > wenn deine Frage praktisch nichts mit diesem alten Thread zu tun hat. Selbst dann: Wenn ein Thread einmal älter als, sagen wir mal, 6 Monate ist, macht es in den wenigsten Fällen Sinn den Thread wieder hervorzukramen. Einzige Ausnahme: wenn man sich gezielt auf ein Vorgängerposting in diesem Thread bezieht, weil man dazu noch etwas zu sagen hat (Ergänzungen, neue Entwicklungen, etc.)
Ange schrieb: > Hallo Zusammen, > > ich habe ebenfalls den Datentyp uint8_t. Ist folgende Zuweisung richtig: > > uint8_t var=1; Ja, richtig. > > Nun möchte ich mir gerne den Inhalt über printf() ausgeben lassen. Wenn > ich schreibe printf("variablenwert %d", &var); erscheint eine Warnung > auf Grund des Datentyps. Was nehme ich denn anstelle von d um mir den > Wert von var ausgeben zu lassen? > > > Gruß Ange Legale Versionen wären:
1 | #include <stdint.h> |
2 | #include <inttypes.h> |
3 | |
4 | |
5 | int main( int nargs, char **args ) |
6 | {
|
7 | uint8_t var = 1; |
8 | printf( "var ist %d\n", (int)var ); // mäßig empfehlenswert |
9 | printf( "var ist %u\n", (unsigned int)var ); // schon besser |
10 | printf( "var ist %"PRIu8"\n", var ); // perfekt, benötigt inttypes.h |
11 | |
12 | return 0; |
13 | }
|
Jörg Wunsch schrieb: > . char >= 8 bits > . int >= 16 bits > . short >= 16 bits > . long >= 32 bits > . long long >= 64 bits Dazu bleibt anzumerken, dass das mit hoher Wahrscheinlichkeit so ist und eine gute Annahme für die reale Welt ist, es aber nicht so verbindlich standardisiert ist. sizeof(char) == 1 und sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long) ist dort die einzige Wahrheit. Beachte die "=". Gruß – Peter
Peter schrieb: > Dazu bleibt anzumerken, dass das mit hoher Wahrscheinlichkeit so ist und > eine gute Annahme für die reale Welt ist, es aber nicht so verbindlich > standardisiert ist. Doch, ist es. Siehe dazu z.B. C99-Standard 5.2.4.2.1 Peter schrieb: > sizeof(char) == 1 und sizeof(char) <= sizeof(short) <= sizeof(int) <= > sizeof(long) <= sizeof(long long) ist dort die einzige Wahrheit. > Beachte die "=". Und? Die "=" eröffnen lediglich die Option, dass auch alle Typen die gleiche Größe haben könnten.
Roland schrieb: > Ich meine, klar, ein unsigned int geht von "0" bis "65536", also > muss er 16 Bit "breit" sein.. Leichen fleddern macht ja soooo viel Spaß. Fledder ich doch mit: Es geht von 0 bis 65.535, was 65.536 verschiedene Werte ergibt.
Beitrag #5847292 wurde von einem Moderator gelöscht.
Beitrag #5847373 wurde von einem Moderator gelöscht.
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.