Hallo, ich verwende ein Array von unsigned char und konvertiere dieses mittels atoi in eine uint_16. Das gibt erst einmal eine warning, weil atoi als Argument ja einen Zeiger auf ein char array erwartet. Wie kann ich denn nun möglichst elegant aus einem String ein uint16_t erzeugen? Ich möchte möglichst den gesamten Wertebereich ausnutzen und brauche nur positive Zahlen.
wenn du nur unsigned char werte 0-255 in uint_16 werte "wandeln" willst ist atoi der total falsche ansatz ich gehe mal davon aus das du weißt wozu atoi da ist ... ASCII to Integer wenn du komplette strings hast .. sollte der string eh in einem char xx[] liegen da sonst hier eh alle möglichen anderen funktinen meckern
Also ich würde das jetzt so aufrufen: strtoul(buffer,NULL,0); Allerdings gibt das immer noch eine Warnung: pointer targets in passing argument 1 of 'strtoul' differ in signedness Das liegt daran, dass buffer ein array of unsigned char ist. Aber wenn ich es einfach signed mache sollte es ja für meine Anwendung (ASCII) keinen Unterschied machen oder?
Da du weißt, das in deinem unsigned char Array im Grunde ein String vorliegt, es sich also um char handelt, kannst du den Pointer auf einen char* zurechtcasten. In dem Fall ist das zulässig und auch ok.
Oder ich deklariere buffer gleich als array of char, oder hat das irgendwelche Nachteile?
erklär mal kurz was du machen willst ... ich lese nur heraus das du eine warning bekommst wegen singed/unsigned oben schreibst du das du ein unsigned char array mit daten .. ( was für daten ?? ASCII ?? 0-255 ?? 0x00 - 0xFF ?? ( is das selbe ..ich weiß ) ) in ein anderes array mit uint_16 wandeln willst wenn du hier nichts wandeln willst sondern nur die werte in das uint_16 array schreiben möchtest .. dann tu das ..
Ich habe in einem array of unsigned char verschiedene Werte(ASCII). Dieses Array soll in eine uint_16 zahl gewandelt werden.
Lars schrieb: > Oder ich deklariere buffer gleich als array of char, oder hat das > irgendwelche Nachteile? Kommt drauf an. Die Frage ist an dieser Stelle: Warum hast du dann überhaupt uint8_t genommen? char für alles was mit Texten zu tun hat sint8_t kleiner Integer mit 8 Bit und Vorzeichen uint8_t kleiner Integer mit 8 Bit ohne Vorzeichen so werden die Datentypen eingesetzt. Wenn du deinen Buffer immer und überall immer nur im Sinne von "enthält einen Text" benutzt, gibt es keinen Grund warum der uint8_t sein muss.
zur not caste dir das array beim aufruf hin unsigned char buffer[x] atoi( (char*) buffer , .... );
Gut das weiß ich eben auch nicht mehr, warum der uint_8 ist. Ist schon eine Weile her. Also in dem Array steht nur Text. Also werde ich einfach char nehmen. Aber mal eine Frage am Rande. Wieso lässt Char negative Zahlen zu? ASCII ist doch positiv oder etwa nciht?
die frage ist wie man die daten interpretiert ... für mich ist sowas bis auf floatwerte immer 0x00 bis 0xff und ASCII zeichen "0" ist eben 0x30 ....
Lars schrieb: > Aber mal eine Frage am Rande. Wieso lässt Char negative Zahlen zu? Weil's der Referenzcompiler so implementierte. Und der tat es dies, weil die Referenzmaschine PDP-11 es in Hardware so tat. C liess das zwar stets offen, auch damals schon, aber viele Compiler schleppen das seit damals mit. > ASCII ist doch positiv oder etwa nciht? Undefiniert. Kann sein, kann nicht sein.
Lars schrieb: > Aber mal eine Frage am Rande. Wieso lässt Char negative Zahlen zu? wer sagt das? Ob char ein Vorzeichen hat oder nicht, entscheidet der, der den Compiler schreibt. Der C-Standard lässt ihm das frei und oftmals kann man dem Compiler beim Aufruf auch noch sagen wie man es gerne hätte. Daher auch: Will ich einen char im Sinne von 'eine Variable die einen kleinen Integer speichern kann' benutzen, dann nehme ich niemals char, sondern immer die Varianten, bei der ich explizit ein Vorzeichen anfordere oder eben nicht anfordere > ASCII > ist doch positiv oder etwa nciht? ASCII ist in seiner ursprünglichen Pracht ein 7-Bit Code.
A. K. schrieb: >> ASCII ist doch positiv oder etwa nciht? > > Undefiniert. Kann sein, kann nicht sein. PS: ASCII ist positiv, aber 'Ä' im ISO-Zeichensatz ist nicht Bestandteil von ASCII und kann je nach Compiler negativ sein, wenn im "char" gespeichert.
Gut also mache ich das Array jetzt char. Aber wenn ich uint16 erhalten will muss ich trotzdem strtoul(buffer,NULL,0); statt atoi(buffer); verwenden.
Lars schrieb: > Gut also mache ich das Array jetzt char. Aber wenn ich uint16 erhalten > will muss ich trotzdem > > strtoul(buffer,NULL,0); > > statt > > atoi(buffer); > > verwenden. Ja. es gibt kein atou und es gibt auch kein strtoui Allerdings wäre das keine schlechte Übung für dich, dir ein strtoui bzw. ein atou zu machen. Vermeidet den long zwischendurch.
Lars schrieb: > Gut das weiß ich eben auch nicht mehr, warum der uint_8 ist. Ist schon > eine Weile her. Also in dem Array steht nur Text. Also werde ich einfach > char nehmen. > > Aber mal eine Frage am Rande. Wieso lässt Char negative Zahlen zu? Die Frage stellt sich eigentlich nicht, denn mit Text rechnet man ja nicht. Der Compiler muß eben irgendeinen Integer-Typ als darunterliegenden Typ verwenden, um die Zeichen abzuspeichern. Welcher das ist, spielt aber eigentlich keine Rolle.
Rolf Magnus schrieb: > Die Frage stellt sich eigentlich nicht, denn mit Text rechnet man ja > nicht. Der Compiler muß eben irgendeinen Integer-Typ als > darunterliegenden Typ verwenden, um die Zeichen abzuspeichern. Welcher > das ist, spielt aber eigentlich keine Rolle. So die Theorie. Allein die Praxis... 'Ä' sei bei "char" mit Vorzeichen beispielsweise -60. EOF ist aber gewohnheitsmässig -1. Die Standardfunktion getchar() gibt "int" zurück, um chars und EOF auseinander halten zu können. Damit getchar() aber nicht schon bei 0xFF Schluss macht, gibt es vor EOF nur positive Werte zurück, bei Ä also nicht -60, sondern 195. Folglich wird int c = getchar(); if (c == 'Ä') printf("AE"); nicht funktionieren und man muss Hand anlegen: if (c == ('Ä' & 0xFF)) printf("AE"); oder if ((char)c == 'Ä') printf("AE");
Lars schrieb: > Aber mal eine Frage am Rande. Wieso lässt Char negative Zahlen zu? ASCII > ist doch positiv oder etwa nciht? Wer sagt denn, dass überhaupt ASCII verwendet werden muss? Richtig, niemand. ANSI C sagt dazu nur, dass eine Sammlung von bestimmten Zeichen in jedem Fall unterstützt werden muss, und dass diese Zeichen in einem char dargestellt werden können. Wie der Compiler das macht, bleibt ihm überlassen, deshalb kann man sich (wenn man portabel bleiben will) nicht darauf verlassen, dass '0' gleich 0x30 ist. Landest du z.B. mal auf einem IBM-Grossrechner (EBCDIC), dann ist dort '0' gleich 0xF0, und das kann dann je nach Compiler auch durchaus einen negativen char-Wert ergeben. Andreas
A. K. schrieb: > 'Ä' sei bei "char" mit Vorzeichen beispielsweise -60. EOF ist aber > gewohnheitsmässig -1. Die Standardfunktion getchar() gibt "int" zurück, > um chars und EOF auseinander halten zu können. Damit getchar() aber > nicht schon bei 0xFF Schluss macht, gibt es vor EOF nur positive Werte > zurück, bei Ä also nicht -60, sondern 195. Nein, das ist zumindest durch den Standard so nicht erlaubt. Bei folgendem Code muss AFAIK der Vergleich am Ende wahr sein, wenn 'Ä' ein "printing character" ist und kein IO-Error auftritt:
1 | FILE *f = fopen("test", "w+"); |
2 | long int pos = ftell(f); |
3 | fputc('Ä', f); |
4 | fseek(f, pos, SEEK_SET); |
5 | int c = fgetc(f); |
6 | if (c == 'Ä') |
7 | printf("OK\n"); |
Andreas
Andreas Ferber schrieb: > Wer sagt denn, dass überhaupt ASCII verwendet werden muss? Richtig, > niemand. ANSI C sagt dazu nur, dass eine Sammlung von bestimmten Zeichen > in jedem Fall unterstützt werden muss, und dass diese Zeichen in einem > char dargestellt werden können. Im Prinzip richtig. Die Frage nach ASCII oder nicht ASCII ist mitlerweile mehr oder weniger eine rein akademsiche Frage geworden. Auch wenn natürlich niemand vorschreibt, dass dem so ist. > Landest du z.B. mal auf einem IBM-Grossrechner > (EBCDIC), Wenn er je auf einem IBM Mainframe kommt, dann stellt sich die Frage so gar nicht mehr. Mit der Betonung auf 'wenn'. Und dann ist EBCDIC sein geringstes Problem :-)
Andreas Ferber schrieb: > Nein, das ist zumindest durch den Standard so nicht erlaubt. Ausprobiert?
1 | #include <stdio.h> |
2 | |
3 | int main(int argc, char **argv) |
4 | {
|
5 | FILE *f; |
6 | int c; |
7 | long pos; |
8 | |
9 | f = fopen("test", "w+"); |
10 | pos = ftell(f); |
11 | fputc('Ä', f); |
12 | fseek(f, pos, SEEK_SET); |
13 | c = fgetc(f); |
14 | printf("AE=%d c=%d\n", 'Ä', c); |
15 | if (c == 'Ä') |
16 | printf("OK\n"); |
17 | else
|
18 | printf("Nicht OK\n"); |
19 | }
|
Microsoft: AE=-60 c=196 Nicht OK Digital Mars: AE=-60 c=196 Nicht OK Linux GCC: AE=-60 c=196 Nicht OK
A. K. schrieb: > Ausprobiert? Nein. Trotzdem lag' ich nicht ganz falsch, der Hund liegt hier begraben: [c] #include <stdio.h> #include <ctype.h> int main(void) { printf("isprint('AE')=%d\n", isprint('Ä')); } [c] => isprint('AE')=0 (GCC, x86, Linux) Andreas
Der Hund liegt in der Definition von fgetc begraben: "... the fgetc() function shall obtain the next byte as an unsigned char converted to an int ...". http://www.opengroup.org/onlinepubs/000095399/functions/fgetc.html Es geht auch garnicht nicht anders, aufgrund des Konflikts mit 0xFF und der mindestens faktischen Festlegung von EOF auf -1. Das ist auch kein sprachtheoretisches Problem sondern eine nicht zu Ende gedachte Definition ebendieser fget[c|char] Funktionen.
Das wiederspricht aber IMO in bestimmten Konstellationen dann dem C-Standard selbst (oder der Standard ist an der Stelle lückenhaft). Wenn man vor dem ganzen noch ein setlocale(LC_ALL, "de_DE"); macht (soweit das System diese Locale unterstützt natürlich), dann wird 'Ä' je nach System auf einmal zum Printing Character (7.4.1.8 Absatz 2): The isprint function tests for any printing character including space (' '). Unter GCC/Linux gibt isprint('Ä') dann in der Tat einen wahren Wert zurück. Nach der Definition von Text Streams müsste dann beim Zurücklesen etwas "equal" vergleichendes rauskommen (7.19.2 Absatz 2): [...] Data read in from a text stream will necessarily compare equal to the data that were earlier written out to that stream only if: the data consist only of printing characters and [...] Allerdings (und das ist der Punkt, wo man den Standard als lückenhaft bezeichnen kann) steht AFAIK nirgendwo explizit, dass die stdio-Funktionen die Locale berücksichtigen, man kann das höchstens indirekt schliessen, da in der Beschreibung auf Locale-behaftete Begriffe wie "printing character" zurückgegriffen wird. Andreas
Es ist völlig schnurz ob das Ä printable ist und wie die locales eingestellt sind, denn wenn getc() nicht unabhängig von der Vorzeicheneigenschaft 0..255 zurück gibt, dann lassen sich Binärfiles damit bei vorzeichenbehaftetem "char" nicht verarbeiten. Und sie werden damit verarbeitet. Diese Funktionen sind (mit "w+b") nicht nur auf druckbare Zeichen definiert. Ja, das ist inkonsistent. fgetc/EOF ist defekt, ein Konstruktionsfehler. Das steht nur nicht dabei. Wäre EOF beispielsweise als (CHAR_MIN-1) definiert worden, wäre das Problem vom Tisch und fgetc() dürfte für Ä -60 zurück geben.
A. K. schrieb: > Der Hund liegt in der Definition von fgetc begraben: "... the fgetc() > function shall obtain the next byte as an unsigned char converted to an > int ...". Richtig. Deshalb wäre das folgende auch falsch: Andreas Ferber schrieb: > FILE *f = fopen("test", "w+"); > long int pos = ftell(f); > fputc('Ä', f); > fseek(f, pos, SEEK_SET); > int c = fgetc(f); > if (c == 'Ä') > printf("OK\n"); Die letzte if-Abfrage müßte heißen:
1 | if ((char)(unsigned char)c == 'Ä') |
Bei mir klappt das mit default-Einstellungen aber sowieso nicht, weil ich dann UTF-8 habe und 'Ä' deshalb aus mehreren Zeichen besteht.
Rolf Magnus schrieb: > Die letzte if-Abfrage müßte heißen: So geht's auch (wie ich oben schon schrieb), der andere cast ist erstens redundant und zweitens in der besagten Definition von fgetc schon drin:
1 | if ((char)c == 'Ä') |
> Bei mir klappt das mit default-Einstellungen aber sowieso nicht, weil > ich dann UTF-8 habe und 'Ä' deshalb aus mehreren Zeichen besteht. Du darfst auch '\xC4' schreiben.
A. K. schrieb: > Es geht auch garnicht nicht anders, aufgrund des Konflikts mit 0xFF und > der mindestens faktischen Festlegung von EOF auf -1. EOF braucht man eigentlich gar nicht. Das ist eh nur eine Optimierung, um nicht jedesmal feof() aufrufen zu müssen. EOF kann (zumindest theoretisch) sowieso nicht eindeutig sein, da es ja auch eine Plattform geben kann, wo char und int gleich groß sind. Da gäbe es gar keinen Wert für EOF, der nicht auch ein gültiger char-Wert sein könnte. A. K. schrieb: > der andere cast ist in der besagten Definition schon drin Der ist eigentlich gerade nicht drin. Der Compiler liest das Byte in einen unsigned char und konvertiert den nach int. Mein Cast macht jetzt erst wieder den unsigned char draus und konvertiert den dann nach char. Du hast aber recht damit, daß man diesen Cast weglassen kann.
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.