was macht itoa

Gast #5372318
Lesenswert?

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?)
#5372336
Lesenswert?

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.
Gast #5372338
Lesenswert?

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.
#5372500
Lesenswert?

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
}
Gast #5372510
Lesenswert?

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.
Gast #5372590
Lesenswert?

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.
#5372621
Lesenswert?

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
#5372645
Lesenswert?

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ß. :´(
Gast #5372655
Lesenswert?

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.
#5372685
Lesenswert?

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.
Gast #5372689
Lesenswert?

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?
Gast #5372753
Lesenswert?

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.
Gast #5372760
Lesenswert?

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.
Gast #5372789
Lesenswert?

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.
#5372800
Lesenswert?

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.
Gast #5372812
Lesenswert?

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.
Gast #5372822
Lesenswert?

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.
#5372825
Lesenswert?

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.
Gast #5372826
Lesenswert?

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.
Gast #5372838
Lesenswert?

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.
Gast #5372859
Lesenswert?

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.
Gast #5372882
Lesenswert?

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.
#5372887
Lesenswert?

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
Gast #5372958
Lesenswert?

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.
Gast #5372976
Lesenswert?

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.
Gast #5373042
Lesenswert?

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.
Gast #5373083
Lesenswert?

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.
Gast #5373125
Lesenswert?

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)
Gast #5373143
Lesenswert?

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.
#5373426
Lesenswert?

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.
Gast #5373431
Lesenswert?

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;
#5373454
Lesenswert?

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.
Gast #5374482
Lesenswert?

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.
Gast #5374591
Lesenswert?

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.
Gast #5374975
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren