Ich habe hier schon einen Beitrag zu itoa gefunden, der nach dem Zweck fragte, bin daraus jedoch nicht schlau geworden. [c]int b=6; char str[100]; printf("b binaer: %s\n", itoa(b, str, 2))[c] ich habe verstanden dass 2 bzw 16 angibt, ob die Zahl im binär bzw. hexadezimalsystem angegeben wird. b ist die zahl, die in binärschreibweise angegeben wird. Wozu brauch ich jetzt str(also einen char array?)
Gottaquest schrieb: > Ich habe hier schon einen Beitrag zu itoa gefunden, der nach dem Zweck > fragte, bin daraus jedoch nicht schlau geworden. > [c]int b=6; > char str[100]; > printf("b binaer: %s\n", itoa(b, str, 2))[c] > ich habe verstanden dass 2 bzw 16 angibt, ob die Zahl im binär bzw. > hexadezimalsystem angegeben wird. b ist die zahl, die in > binärschreibweise angegeben wird. Wozu brauch ich jetzt str(also einen > char array?) Irgendwohin muß itoa sein Ergebnis schreiben und printf möchte an der übergebenen Adresse einen String finden.
Der Parameter str, sagt der Funktion itoa, wo im Speicher es den von ihr erzeugten String von Ziffern ablegen soll. Das scheint auf den ersten Blick redundant, da ja itoa als Rückgabewert, genau diesen Zeiger zurückgibt. Es gibt dafür mehrere Argumente, von denen nicht alle zwingend sind. Nur ein Beispiel: Oft ist es so, dass Ausgabebuffer ohnehin mehrere verschiedene Daten aus verschiedenen Verarbeitungsschritten beinhalten. In dem man den Zeiger übergibt, erspart man sich z.B. das spätere Umkopieren des Ergebnisses und den zusätzlichen Speicher. Das trifft in Deiner Anwendung zwar nicht zu, aber die Funktion kann so auch für den anderen Fall verwendet werden.
Hex kann printf übrigens selbst per "%x", Oktal auch per "%o", nur binär geht nur per Klimmzug.
:
Bearbeitet durch User
Ich such bei solch Fragen das zugehörige File raus un versuch schlau draus zu werden.
1 | char * |
2 | itoa(char * buf, int val, int base) |
3 | {
|
4 | char * cp = buf; |
5 | |
6 | if(val < 0) { |
7 | *buf++ = '-'; |
8 | val = -val; |
9 | }
|
10 | utoa(buf, val, base); |
11 | return cp; |
12 | }
|
13 | char * |
14 | utoa(char * buf, unsigned val, int base) |
15 | {
|
16 | unsigned v; |
17 | char c; |
18 | |
19 | v = val; |
20 | do { |
21 | v /= base; |
22 | buf++; |
23 | } while(v != 0); |
24 | *buf-- = 0; |
25 | do { |
26 | c = val % base; |
27 | val /= base; |
28 | if(c >= 10) |
29 | c += 'A'-'0'-10; |
30 | c += '0'; |
31 | *buf-- = c; |
32 | } while(val != 0); |
33 | return ++buf; |
34 | }
|
Teo D. schrieb:
1 | if(val < 0) { |
2 | *buf++ = '-'; |
3 | val = -val; |
4 | }
|
Dazu wäre noch anzumerken, daß diese Routine scheitert für den Wert INT_MIN, der nämlich keinen positiven Gegenwert hat. Sofern man diesen Wert niemals hat, ist die Funktion OK, aber für eine generische Library-Funktion sollte da ein expliziter Check drinstehen.
Danke c.m. für den link(englischsprachige Ergebnisse sind halt wenn man noch am anfang ist teilweise schwer zu verstehen), Theor und den anderen für die Antworten.
Nop schrieb: > Dazu wäre noch anzumerken, daß diese Routine scheitert für den Wert > INT_MIN, der nämlich keinen positiven Gegenwert hat. ??? PS: Das ist der original Code von xc8 (gcc Clone).
Teo D. schrieb: > ??? Guck Dir mal die Wertebereiche von Integern an. Im Falle von z.B. 16 bit gehen die von -32768 bis 32767. +32768 ist nicht darstellbar. Also was passiert, wenn man der Routine -32768 übergibt und sie versucht, das Vorzeichen zu wechseln? > PS: Das ist der original Code von xc8 (gcc Clone). Der Code ist halt an der Stelle fehlerhaft.
Teo D. schrieb: > Nop schrieb: >> Dazu wäre noch anzumerken, daß diese Routine scheitert für den Wert >> INT_MIN, der nämlich keinen positiven Gegenwert hat. > > ??? > > > PS: Das ist der original Code von xc8 (gcc Clone). Das ist dann die mit xc8 mitgelieferte Libc.
Nop schrieb: > Guck Dir mal die Wertebereiche von Integern an Ja, bin Heute nich so fit. Klar hätte ich das sehen müssen, Danke. Nop schrieb: > Der Code ist halt an der Stelle fehlerhaft. Gut zu wissen, ein Hobby-Programmierer sucht da wohl zuletzt. :( (OK, der Fehler wäre schnell aufgefallen, wird aber sicher nicht der einzige sein)
Teo D. schrieb: > Nop schrieb: >> Guck Dir mal die Wertebereiche von Integern an > > Ja, bin Heute nich so fit. Klar hätte ich das sehen müssen, Danke. > > Nop schrieb: >> Der Code ist halt an der Stelle fehlerhaft. > > Gut zu wissen, ein Hobby-Programmierer sucht da wohl zuletzt. :( > (OK, der Fehler wäre schnell aufgefallen, wird aber sicher nicht der > einzige sein) Es gibt diverse Hinweise im Netz zu diesem Problem INT_MIN von itoa, was vielleicht auch der Grund ist, warum es nicht zum C-Standard gehört. Oder umgekehrt. https://en.m.wikibooks.org/wiki/C_Programming/stdlib.h/itoa
Carl D. schrieb: > Es gibt diverse Hinweise im Netz zu diesem Problem INT_MIN von itoa, was > vielleicht auch der Grund ist, warum es nicht zum C-Standard gehört. > Oder umgekehrt. Mir war ja nicht mal bewusst, das es nicht zum C-Standard gehört (Obwohl es klar ist, sonnt wäre es ja nicht im Manuel vom xc8 beschrieben). Obwohl mir langsam dämmert, da war doch was..? :) Nicht mal im Manual zum xc8 steht was dazu. Ist wohl Standard das dies Jeder weiß. :´(
Nop schrieb: > Guck Dir mal die Wertebereiche von Integern an. Im Falle von z.B. 16 bit > gehen die von -32768 bis 32767. +32768 ist nicht darstellbar. Also was > passiert, wenn man der Routine -32768 übergibt und sie versucht, das > Vorzeichen zu wechseln? Naja doch, eigentlich würde das gehen. Aus -32768 ($8000) wird wieder -32768($8000). Das wird in utoa auf ein unsigned int gecastet und wird damit zu 32768, welches korrekt im Wertebereich bis 65536 liegt. Dumm nur, wenn der Compiler das automatisch an den Wertebereich der CPU anpasst und aus dem $8000 bei Übergabe ein $FFFF8000 wird.
Gottaquest schrieb: > Danke c.m. für den link(englischsprachige Ergebnisse sind halt > wenn man > noch am anfang ist teilweise schwer zu verstehen), ... gute englischkenntnisse sind vorauszusetzen. 2018 und so.
Karl schrieb: > Naja doch, eigentlich würde das gehen. Oh man.... mir is doch schon schwindlig. Ich schau Morgen erst wieder hier rein. :)
Karl schrieb: > Nop schrieb: >> Guck Dir mal die Wertebereiche von Integern an. Im Falle von z.B. 16 bit >> gehen die von -32768 bis 32767. +32768 ist nicht darstellbar. Also was >> passiert, wenn man der Routine -32768 übergibt und sie versucht, das >> Vorzeichen zu wechseln? > > Naja doch, eigentlich würde das gehen. > > Aus -32768 ($8000) wird wieder -32768($8000). Das wird in utoa auf ein > unsigned int gecastet und wird damit zu 32768, welches korrekt im > Wertebereich bis 65536 liegt. > > Dumm nur, wenn der Compiler das automatisch an den Wertebereich der CPU > anpasst und aus dem $8000 bei Übergabe ein $FFFF8000 wird. Wenn [unsigned] int 32 Bit lang ist, dann existiert das Problem für -32768 gar nicht. Und ja, andere Sprachen haben solche Probleme nicht, Java z.B. verzichtet auf unsigned und braucht dann eben immer die nächstgrössere Integer-Variante. Ab 64-Bit wird's dann eng, denn long long trägt dann den Namen BigInt mit jeder Menge Overhead.
Nop schrieb: > Dazu wäre noch anzumerken, daß diese Routine scheitert für den Wert > INT_MIN, der nämlich keinen positiven Gegenwert hat. Das steht doch im Kontext zum utoa - Aufruf. Bei 2er-komplement-maschinen gibt's ja keinen Fehler. Bei den mit Vorzeichen auch nicht. Wo schlägt sowas in der Praxis fehl? Also auf welchen Architekturen?
Carl D. schrieb: > Java z.B. > verzichtet auf unsigned und braucht dann eben immer die nächstgrössere > Integer-Variante. Da wirds aber lustig, wenn ich einen 64bit-Integer durch 10 teilen will, um ihn in Dezimalstellen zu zerlegen. Sämtliche mir bekannten - ok, ich kenne sicher nicht alle - Ganzzahl-Divisionen erledigen signed Division dadurch, dass sie die negativen Zahlen negieren und dann eine unsigned Division durchführen.
Karl schrieb: > Aus -32768 ($8000) wird wieder -32768($8000). Das ist signed integer overflow und damit undefined behaviour. Carl D. schrieb: > Wenn [unsigned] int 32 Bit lang ist, dann existiert das Problem für > -32768 gar nicht. Dann existiert es in derselben Form aber für INT_MIN/32. Achim S. schrieb: > Wo schlägt sowas in der Praxis fehl? Also auf welchen Architekturen? Undefined behaviour kann einen nach jedem Compiler-Update beißen. Auf jeder Architektur. Das ist umso schlimmer, wenn es vorher lief und sich um eigentlich reifgetesteten Code handelt.
Nop schrieb: > Das ist signed integer overflow und damit undefined behaviour. Ja stimmt, aber andererseits: Für 99.999% der Fälle irrelevant. Denn wenn ich reale Werte speichere, wird ein Integer seltenst komplett ausgereizt. Dafür schleppe ich dann für den unwahrscheinlichen Fall, dass jemand wirklich mal mit einem Wert von -32,768m rechnet und den in ein unsigned Int packt immer die Prüfabfrage mit rum. Mein Compiler mahnt auch immer an: int16 = uint16 + int16 könnte den Wertebereich überschreiben. Da ich weiss, dass die Werte reinpassen juckt mich das nicht. Das ist bei Ada schön, da kann man festlegen: Die Zahl kommt nur zwischen -4000 und 12000 vor, und schon weiss der Compiler: Passt.
Nop schrieb: > Karl schrieb: > >> Aus -32768 ($8000) wird wieder -32768($8000). > > Das ist signed integer overflow und damit undefined behaviour. > > > Carl D. schrieb: >> Wenn [unsigned] int 32 Bit lang ist, dann existiert das Problem für >> -32768 gar nicht. > > Dann existiert es in derselben Form aber für INT_MIN/32. Hä? Ich dachte immer NOP braucht nur Zeit, aber rechnet zu mindest nichts falsch.
Carl D. schrieb: > Ich dachte immer NOP braucht nur Zeit, aber rechnet zu mindest nichts > falsch. Ist auch der Fall. INT_MIN/32 = -2147483648, und damit ist es doch dieselbe Konstellation wie -32768 für int/16. Karl schrieb: > Dafür schleppe ich dann für den unwahrscheinlichen Fall, dass jemand > wirklich mal mit einem Wert von -32,768m rechnet und den in ein unsigned > Int packt immer die Prüfabfrage mit rum. Die Prüfabfrage ist doch verschwindend gering. Aber wenn man eine Library macht, die nicht für eine konkrete Anwendung ist, in der man die Wertebereiche kennt, dann sollte man das halt auch richtig machen. Daß ausgerechnet das zum Flaschenhals in der Performance wird, halte ich für ausgeschlossen. Und wenn doch, dann ist die Applikation wahrscheinlich falsch entworfen und enthält tonnenweise Jojo-Code.
Bevor hier weiter über evtl. vorhandene Fehler in der Library und fiktive 32bit Integer geschrieben wird, sollte jemand nachschauen was die xc8 Dokumentation zu der itoa Funktion sagt. Ich konnte in den letzten 5 Minuten keine Informationen finden, war aber auch nicht bereit den xc8 zu installieren. Ich vermute, itoa wird nirgendwo beschrieben und ist damit nicht zur Benutzung vorgesehen. Damit wäre jede Diskussion über den geposteten Quelltext überflüssig.
Nop schrieb: > Carl D. schrieb: > >> Ich dachte immer NOP braucht nur Zeit, aber rechnet zu mindest nichts >> falsch. > > Ist auch der Fall. INT_MIN/32 = -2147483648, und damit ist es doch > dieselbe Konstellation wie -32768 für int/16. Auf einer 32-Bit-Maschine ist INT_Min/32 != INT_Min. Es sei denn wir Programmieren in "netmask". In C jedenfalls ist Arithmetik anders definiert.
Carl D. schrieb: > Auf einer 32-Bit-Maschine ist INT_Min/32 != INT_Min. Das war auch nicht als Arithmetik gedacht, sondern als "INT_MIN für den Fall eines vorzeichenbehafteten 32bit-Integers". Ich war so frei, dieses Ausmaß an eigenständigem Mitdenken einfach mal vorauszusetzen.
Nop schrieb: > Carl D. schrieb: > >> Auf einer 32-Bit-Maschine ist INT_Min/32 != INT_Min. > > Das war auch nicht als Arithmetik gedacht, sondern als "INT_MIN für den > Fall eines vorzeichenbehafteten 32bit-Integers". Ich war so frei, dieses > Ausmaß an eigenständigem Mitdenken einfach mal vorauszusetzen. Dann schreib halt auch INT32_MIN
Nop schrieb: > Die Prüfabfrage ist doch verschwindend gering. Aber wenn man eine > Library macht, die nicht für eine konkrete Anwendung ist, in der man die > Wertebereiche kennt, dann sollte man das halt auch richtig machen. Und was ist in dem Fall richtig? Ich hatte letztens den Fall: Division durch Null. Normalerweise liefert die Assembler-Division dann einfach den Eingangswert wieder zurück. Was mathematisch nicht korrekt ist, aber abgefangen werden kann. Nun hat der Compiler sich entschieden, da eine 32-bit-Division aus einer Lib einzubauen. Die liefert dann bei Division durch Null eine Exception. Was auch korrekt ist. Dummerweise lief das auf einem µC, der natürlich keine Exception ausgibt. Also wurde der µC in eine Endlosschleife geschickt. Das ist jetzt nicht das, was man auf einem µc möchte.
Karl schrieb: > Ja stimmt, aber andererseits: Für 99.999% der Fälle irrelevant. Denn > wenn ich reale Werte speichere, wird ein Integer seltenst komplett > ausgereizt. Das ist sehr gefährlich und verhindert auch nur einigermaßen professionellen Code. Ich habe nichts dagegen, wenn jemand ein int i mit i++ überlaufen lässt, solange er - das für seinen Compiler und Environment prüft, dass dies ohne WW3 starten nach INT_MIN überläuft - sich dessen bewusst ist - das angibt, falls andere es nutzen - exemplarisch entsprechende Asserts zur Compilezeit oder hier zur Laufzeit einbaut. Das Problem fängt ja bei free-running-counter als Timer an, die weder in signed noch in unsigned sinnvoll, einfach und sicher nutzbar sind, es sei denn, man verlässt sich auf das vorliegende 2-er-Komplement. Das Argument aber, dass es in 99.999% der Fälle gut geht, hat meist ein paar 9en zuviel. Sowohl das frei laufende i von oben, als auch der 16-bit-ADC oder der 32-Bit Speicherwert laufen viel schneller in ein 800xx als Du denkst.
Karl schrieb: > Und was ist in dem Fall richtig? Das Einfachste ist, man fragt hartcodiert auf INT_MIN ab und gibt für den Fall der Gleichheit ebenfalls hartcodiert den entsprechenden String zurück. Simpel, häßlich und zuverlässig. Man sollte dann noch ein Compile-Time-Assert davorsetzen, daß INT_MIN auch tatsächlich das ist, was man glaubt, das es ist. Ein einfaches #ifdef mit #error tut's. Wenn das von der Codegröße her bedenklich ist, dann ist es erst recht bedenklich, eine Libraryfunktion zu nutzen, die die Konvertierung zu diversen verschiedenen Basen beherrscht - denn das wird in diesem Umfang so gut wie nie gebraucht. > Normalerweise liefert die Assembler-Division dann einfach den > Eingangswert wieder zurück. Je nach Controller, manche mögen es so und andere so. Manchmal kommt auch ein Interrupt oder Hardfault oder sowas. Deswegen validiere ich vor einer Division erstmal die Werte, und wenn eine Division durch 0 anstünde, wird die Messung oder was auch immer dahintersteht als ungültig verworfen. Sowas kann insbesondere bei Zeitstempeln schnell mal passieren.
mh schrieb: > sollte jemand nachschauen was > die xc8 Dokumentation zu der itoa Funktion sagt. Ich konnte in den > letzten 5 Minuten keine Informationen finden, war aber auch nicht bereit > den xc8 zu installieren.
1 | ITOA
|
2 | Synopsis
|
3 | #include <stdlib.h> |
4 | char * itoa (char * buf, int val, int base) |
5 | Description
|
6 | The function itoa converts the contents of val into a string which is stored into buf. |
7 | The conversion is performed according to the radix specified in base. buf is assumed |
8 | to reference a buffer which has sufficient space allocated to it. |
9 | Example
|
10 | #include <stdlib.h> |
11 | #include <stdio.h> |
12 | void
|
13 | main (void) { |
14 | char buf[10]; |
15 | itoa(buf, 1234, 16); |
16 | printf("The buffer holds %s\n", buf); |
17 | }
|
18 | See Also |
19 | strtol(), utoa(), ltoa(), ultoa() |
20 | Return Value |
21 | This routine returns a copy of the buffer into which the result is written. |
https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwi93LXfmZfaAhUIXCwKHZnDC84QFggyMAE&url=http%3A%2F%2Fww1.microchip.com%2Fdownloads%2Fen%2FDeviceDoc%2F52053A.pdf&usg=AOvVaw1H4Iv0FWWapC8DB0TcCh7B
:
Bearbeitet durch User
Nop schrieb: > Das Einfachste ist, man fragt hartcodiert auf INT_MIN ab und gibt für > den Fall der Gleichheit ebenfalls hartcodiert den entsprechenden String > zurück. Simpel, häßlich und zuverlässig. Ja aber was will ich denn auf einem µC mit einem String. Bei itoa mag das noch angehen, aber bei einem div / Null nützt mir das gar nichts.
Karl schrieb: > Ja aber was will ich denn auf einem µC mit einem String. Meßwerte oder so in einen String umzuwandeln, um das auf einem angeschlossenen Display anzuzeigen, ist ja durchaus üblich. > aber bei einem div / Null nützt mir das gar nichts. Doch, denn bei einer Division durch Variablen kann man sich Gedanken machen, wie es zustandekommen kann, daß im Nenner eine 0 steht. Das kann man abfangen und im einfachsten Fall die Messung für ungültig erklären. Beispielsweise wenn man irgendeine zeitbezogene Größe berechnet und der Timertick sich nicht verändert hat, denn sowas kommt gerne vor, wenn ein Vorgang schneller als erwartet ist. Insbesondere, wenn der Vorgang selber auch noch parametriert ist und man daher nicht garantieren kann, daß er immer ausreichend lange dauert. Schlußfolgerung: Meßdauer zu kurz. Entweder Messung verwerfen oder mit längerer Dauer nochmal versuchen. Oder bei irgendwelchen Winkeln, wenn man z.B. einen Tangens braucht. Wenn der Winkel zu nahe an 90° ist, teilt man ebenfalls durch 0. Schlußfolgerung: Betrieb außerhalb des beabsichtigten Bereiches, und auch darauf kann man reagieren.
Nop schrieb: > Doch, denn bei einer Division durch Variablen kann man sich Gedanken > machen, wie es zustandekommen kann, daß im Nenner eine 0 steht. Eine Division bekommt zwei Integer-Werte und gibt einen Integer zurück. Wie und wohin willst Du da einen String mit einem Fehler schreiben? Sinnvoll wäre vielleicht, ein NaN zurückzugeben. Bei einem Projekt habe ich mal -32768 als Ganzzahl-NaN definiert, um damit ungültige Messwerte zu kennzeichnen. Das funktioniert aber schon nichtmehr, wenn man dann uint16 hat. Ist also auch nicht allgemein anwendbar.
Karl schrieb: > Eine Division bekommt zwei Integer-Werte und gibt einen Integer zurück. > Wie und wohin willst Du da einen String mit einem Fehler schreiben? Gar nicht, ebensowenig wie bei itoa mit -32768 ein String mit einem Fehler geschrieben würde, sondern "-32768" als korrekter Ergebnis-String zurückgegeben. Bei einer Division habe ich doch beschrieben, wie man das lösen kann. Grundsätzlich, indem man Eingabedaten bzw. Meßwerte vor der Verwendung in Berechnungen erstmal validiert. Denn das kann ja nur entweder an ungültigen Eingabedaten liegen, die man abfängt - oder alternativ natürlich an einem Fehler im Algorithmus, den man behebt.
Nop schrieb: > Das Einfachste ist, man fragt hartcodiert auf INT_MIN ab und gibt für > den Fall der Gleichheit ebenfalls hartcodiert den entsprechenden String > zurück. Simpel, häßlich und zuverlässig. Wieso hartcodiert? Zu welcher Basis? Du meinst sicher: Man ruft hartcodiert utoa mit -INT_MIN auf, oder? (wobei ich nicht wüsste, wie man das korrekt, portabel und defined macht)
Achim S. schrieb: > Wieso hartcodiert? Zu welcher Basis? Ich habe signed ints noch nie zu irgendwas anderen als Basis 10 in Strings konvertiert, und besonders nicht embedded. Aber Dein Vorschlag ... > Man ruft hartcodiert utoa mit -INT_MIN auf, oder? ... ist natürlich noch besser. > (wobei ich nicht wüsste, wie man das korrekt, portabel und defined > macht) Wieso nicht? -INT_MIN wird ja zur Compilezeit ausgewertet und steht als Konstante da.
Nop schrieb: >> (wobei ich nicht wüsste, wie man das korrekt, portabel und defined >> macht) > > Wieso nicht? -INT_MIN wird ja zur Compilezeit ausgewertet und steht als > Konstante da. -INT_MIN ist das gleiche wie INT_MIN!
Rolf M. schrieb: > -INT_MIN ist das gleiche wie INT_MIN! In einen signed int schon, zumindest bei Repräsentation im Zweierkomplement, aber doch nicht, wenn man das als Konstante zur Compilezeit an einen unsigned zuweist?!
Nop schrieb: > Rolf M. schrieb: > >> -INT_MIN ist das gleiche wie INT_MIN! > > In einen signed int schon, INT_MIN ist signed. > zumindest bei Repräsentation im Zweierkomplement, Ja, das hatte ich jetzt nicht extra dazu geschrieben. > aber doch nicht, wenn man das als Konstante zur Compilezeit an einen > unsigned zuweist?! Wohin du das Ergebnis nachher zuweist, spielt keine Rolle. Ob du INT_MIN oder -INT_MIN schreibst, macht keinerlei Unterschied auf einer Zweierkomplement-Maschine.
OK, gerade mal testhalber ausprobiert: also es geht, allerdings kommt beim Compilieren die GCC-Warnung "Ganzzahlüberlauf in Ausdruck":
1 | unsigned a = -INT_MIN; |
Selbes, wenn man das so macht:
1 | unsigned a = INT_MAX + 1; |
So herum geht das ohne Warnung, allerdings verläßt sich das aufs Zweierkomplement:
1 | unsigned a = INT_MIN; |
Das hier geht auch ohne Zweierkomplement:
1 | unsigned a = INT_MAX + 1U; |
Nop schrieb: > OK, gerade mal testhalber ausprobiert: also es geht, allerdings kommt > beim Compilieren die GCC-Warnung "Ganzzahlüberlauf in Ausdruck": > > unsigned a = -INT_MIN; Ja. Das Problem ist, dass in ISO C das Überlaufverhalten von vorzeichenbehafteten Integern nicht definiert ist. Es wird eben erst INT_MIN vorzeichenbehaftet negiert, und dann erst nach unsigned konvertiert. > Selbes, wenn man das so macht: > unsigned a = INT_MAX + 1; Ja, gleiches Problem. Man könnte (unsigned)INT_MAX + 1 draus machen, dann würde es passen. > So herum geht das ohne Warnung, allerdings verläßt sich das aufs > Zweierkomplement: > unsigned a = INT_MIN; Das ganze hat ja auch nur im Zweierkomplement überhaupt einen Sinn. In Einerkomplement oder Sign/Magnitude ist der postive und negative Wertebereich gleich groß, und andere Arten, vorzeichenbehaftete Werte zu repräsentieren, lässt C nicht zu. > Das hier geht auch ohne Zweierkomplement: > unsigned a = INT_MAX + 1U; Ja, damit wird die Addition unsigned durchgeführt, und dazu muss vorher INT_MAX ach unsigned konvertiert werden. Ist also im Prinzip äquivalent zu dem, was ich oben geschrieben hab.
Naja, wenn man -INT_MIN zur Compile-Zeit macht, ändert das sicher kaum was am UB. Und alles andere ist m.E. übler, als sich (begründet, gprüft) darauf zu verlassen, dass einer- oder zweier-Komplement verwendet und angewandt wird.
Achim S. schrieb: > Naja, wenn man -INT_MIN zur Compile-Zeit macht, ändert das sicher > kaum was am UB. Jepp, ich hatte nicht auf dem Schirm, daß auch der Compiler bei den statischen Ausdrücken keine Promotion macht. > Und alles andere ist m.E. übler, als sich (begründet, gprüft) > darauf zu verlassen, dass einer- oder zweier-Komplement verwendet und > angewandt wird. Prüfen kann man das ja leicht zur Compilezeit mit #ifs. Wenn Zweierkomplement, dann muß gelten -(INT_MIN + 1) == INT_MAX. Dann kann man beim hartcodierten Aufruf für den Fall INT_MIN einfach INT_MAX + 1U verwenden, ansonsten mit #error den denkbar unwahrscheinlichen Fall von Nicht-Zweierkomplement abfangen.
Nop schrieb: > Dann kann man beim hartcodierten Aufruf für den Fall INT_MIN einfach > INT_MAX + 1U verwenden, ansonsten mit #error den denkbar > unwahrscheinlichen Fall von Nicht-Zweierkomplement abfangen. Oder auch einfach nichts tun. Denn schließlich ergibt sich das Problem wie gesagt nur bei Zweierkomplement.
Rolf M. schrieb: > Oder auch einfach nichts tun. Denn schließlich ergibt sich das Problem > wie gesagt nur bei Zweierkomplement. Dann ist es aber wieder zur Laufzeit undefined behaviour, was man auch nicht gerne in einer Lib haben will.
Hä? Verstehe ich nicht. Das undefined behavior gibt es wie schon gesagt nur beim Zweierkomplement. Also muss ich nur dann was dagegen tun. Ob nun Zweierkomplement oder nicht, das ändert sich ja in der Regel während der Laufzeit nicht.
:
Bearbeitet durch User
Rolf M. schrieb: > Hä? Verstehe ich nicht. Das undefined behavior gibt es wie schon > gesagt nur beim Zweierkomplement. Also muss ich nur dann was dagegen tun. Ah, ich hatte Dein "einfach nichts tun" mißverstanden als "gar nichts tun", während es sich tatsächlich nur auf den "ansonsten"-Fall eines Postings bezog.
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.