Forum: Mikrocontroller und Digitale Elektronik Was macht ein AVR bei einer Division durch Null?


von Wissenwollender (Gast)


Lesenswert?

Hallo,

was passiert, wenn man folgenden Fall bei einem AVR (GCC/AVR-Studio) 
hat?
1
uint16_t a = 0;
2
uint16_t b = 100;
3
4
uint16_t c = b / a;

Stürzt der Controller dann im Betrieb an dieser Stelle ab?

von Harry (Gast)


Lesenswert?

Es entsteht ein schwarzes Loch welches ALLES einsaugt

von der alte Hanns (Gast)


Lesenswert?

DER PROGRAMMIERER

Ein Programmierer sprach einmal
Im vollen Programmierungssaal

(er sagt es lächelnden Gesichts):
"Ich programmiere: Eins durch Nichts".

Jedoch was soll ich weiter schreiben:
Der Programmierer ließ es bleiben.


in memoriam KLEN

von Nobody (Gast)


Lesenswert?

In C führt eine Division durch 0 zu einem Programm Abbruch. Ein 
Controller stellt dann wohl seine Arbeit ein bis zu einem Neustart.

Du muss im Programm den Teiler selbst auf 0 prüfen und dann die 
gewünschten Massnahmen ergreifen.
1
uint16_t a = c = 0;
2
uint16_t b = 100;
3
4
if ( a > 0 )
5
{
6
   c = b / a;
7
}
8
else
9
{
10
   /* Diesen Missstand melden */
11
}

von Wissenwollender (Gast)


Lesenswert?

Nobody schrieb:
> In C führt eine Division durch 0 zu einem Programm Abbruch. Ein
> Controller stellt dann wohl seine Arbeit ein bis zu einem Neustart.

Wirklich??? Hätte gedacht, dass vielleicht ein Error-Flag gesetzt wird 
und das Programm ansonsten "normal" weitergeht...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ein AVR selbst kann gar nicht dividieren, da sein Befehlssatz keine 
Division kennt.

Insofern ist alles, was passiert, abhängig von der Umsetzung des 
Hochsprachendivisionsbefehls in den letzlich ausgeführten Maschinencode.

von Karl H. (kbuchegg)


Lesenswert?

Nobody schrieb:
> In C führt eine Division durch 0 zu einem Programm Abbruch. Ein
> Controller stellt dann wohl seine Arbeit ein bis zu einem Neustart.

Das kann man nicht so pauschal sagen.
Das Ergebnis ist nicht definiert. Alles mögliche kann passieren, 
inklusive einem Prozessorhalt. Aber sehr wahrscheinlich ist das nicht. 
Gerade auf einem µC werden die Dinge meistens so gelagert, dass das 
Programm zumindest weiter läuft. Je nach Situation hat man dann ein 
einmalig falsches Zwischenergebnis (was immer noch fatal ist, nicht 
missverstehen), im nächsten Durchlauf durch die Hauptschleife sind dann 
aber die Zahlenwerte möglicherweise schon andere, so dass das Programm 
ab dann korrekt weiterlaufen kann.
Gerade im Embedded-Bereich ist ein Prozessor-Halt der Super-Gau 
schlechthin.

> Du muss im Programm den Teiler selbst auf 0 prüfen
Das auf jeden Fall. Wenn durch 0 dividiert wird, dann deutet das sowieso 
meistens auf einen Sonderfall hin, der getrennt behandelt werden muss.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

C definiert eine Division durch 0 als "undefiniert". Compiler und 
Runtime können also machen was sie wollen, morgen anders als heute.

von Peter D. (peda)


Lesenswert?

Wissenwollender schrieb:
> Stürzt der Controller dann im Betrieb an dieser Stelle ab?

Wie sollte er?
Er hat keinerlei Absturzflags.

Er zieht ganz profan von jedem Bit 0 ab, da es ohne Unterlauf geht.
Das Ergebnis ist folglich 0b1111111111111111 bzw. 0xFFFF.

Wenn Du einen Absturz willst, mußt Du ihn schon selber programmieren:
1
uint16_t udiv16( uint16_t a, uint16_t b)
2
{
3
  if( b )
4
    return a / b:
5
  cli();
6
  for(;;);
7
}

von W.S. (Gast)


Lesenswert?

Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die 
ANSI-Vorgaben hält - als Ergebnis eine NAN. Und das ist die größte 
Sch*** die es gibt, denn aus einer NAN kommt man anschließend durch nix 
mehr heraus. Also auch kein nachträgliches Abfangen im Programm mehr 
möglich. Hab ich selber schon oft genug erlebt und mich darüber schwarz 
ärgern müssen.

W.S.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die
> ANSI-Vorgaben hält - als Ergebnis eine NAN. Und das ist die größte
> Sch*** die es gibt, denn aus einer NAN kommt man anschließend durch nix
> mehr heraus.

Was ein völlig korrektes Verhalten ist. Nicht nur gemäss ANSI, sondern 
auch gemäss einfacher Logik. Operationen auf undefinierte Werte können 
nur wiederum undefinierte Werte produzieren.

Allerdings bezieht sich der Thread auf Integer-Rechnung, du aber auf 
Fliesskomma-Rechnung.

: Bearbeitet durch User
von Cyblord -. (cyblord)


Lesenswert?

W.S. schrieb:
> Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die
> ANSI-Vorgaben hält - als Ergebnis eine NAN. Und das ist die größte
> Sch*** die es gibt, denn aus einer NAN kommt man anschließend durch nix
> mehr heraus.

Wie meinst du denn "kommt man nicht mehr heraus?". NAN ist doch nur ein 
spezieller Wert den eine Variable haben kann. Wieso muss man da irgendwo 
raus?

Meist ist es doch auch so, einen Fehler wie Division durch Null will man 
nicht wirklich abfangen. Denn was kann man hier denn Bitte noch 
ausrichten? Das weist auf einen schweren Fehler in der Programmlogik 
hin, meist fehlende Überprüfung von Eingaben, oder schlimmer 
irgendwelche Schleifen die zu tief laufen. Also da ist ein sauberes 
stehenbeleiben die beste Lösung. Ein "Weiter so", wie im guten alten 
Basic mit dem Befehl "On Error Goto Next" behindert nur die Fehlersuche.

von Wissenwollender (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Er zieht ganz profan von jedem Bit 0 ab, da es ohne Unterlauf geht.
> Das Ergebnis ist folglich 0b1111111111111111 bzw. 0xFFFF.

Der Controller schafft sich dann also in seinem Kosmos ein lokales 
Unendlich.

von Ralf G. (ralg)


Lesenswert?

cyblord ---- schrieb:
> Meist ist es doch auch so, einen Fehler wie Division durch Null will man
> nicht wirklich abfangen. Denn was kann man hier denn Bitte noch
> ausrichten?

Es gibt Funktionen, die gegen unendlich laufen. z.B., bei 'tan(90°)' 
muss es ja trotzdem weitergehen.

von Cyblord -. (cyblord)


Lesenswert?

Ralf G. schrieb:
> cyblord ---- schrieb:
>> Meist ist es doch auch so, einen Fehler wie Division durch Null will man
>> nicht wirklich abfangen. Denn was kann man hier denn Bitte noch
>> ausrichten?
>
> Es gibt Funktionen, die gegen unendlich laufen. z.B., bei 'tan(90°)'
> muss es ja trotzdem weitergehen.

Darum schrieb ich ja "meist".

von Tipp des Tages (Gast)


Lesenswert?

Warum soviele ironische Antworten?
Die Frage ist absolut berechtigt.  Zahlreiche Prozessoren kennen ein 
Exception-Handling, bei dem z.B. unterschiedliche Interrupts ausgelöst 
werden.
Bei den x86 kompatiblen gibt es einen eigenen Interrupt für Division 
durch Null. Weiterhin gibt es dort einen Interrupt für unbekannte 
OPcodes. Dieser wurde zu 286 und 386SX Zeiten verwendet, um per 
Softwareemulator den 287/387er Koprozessor zu emulieren, der für die 
Fliesskommaberechnungen zuständig ist.

Weiterhin gibt es Bibliotheken und Frameworks, die ähnliche Mechanismen 
bieten. Wie oben zurecht gesagt:
> Insofern ist alles, was passiert, abhängig von der Umsetzung des
> Hochsprachendivisionsbefehls in den letzlich ausgeführten Maschinencode.

Es fehlt jedoch die Aussage, ob in bestimmten Toolchains solche 
Mechanismen eingebaut sind.

Gerade als Anfänger in neuen Architekturen geht man von bekannten 
Mechanismen aus, und muss sich unterschiedliche Implementierungen und 
Herangehensweisen zunächst erarbeiten.

von (prx) A. K. (prx)


Lesenswert?

Wissenwollender schrieb:
> Der Controller schafft sich dann also in seinem Kosmos ein lokales
> Unendlich.

Das übliche Missverständnis. Unendlich ist als Ergebnis genauso richtig 
und falsch wie 65535 oder 42. Es kommt halt das raus, was der 
Algorithmus der Division erbringt, wenn man den Fall nicht eigens 
abfängt.

von (prx) A. K. (prx)


Lesenswert?

Tipp des Tages schrieb:
> Die Frage ist absolut berechtigt.  Zahlreiche Prozessoren kennen ein
> Exception-Handling, bei dem z.B. unterschiedliche Interrupts ausgelöst
> werden.

Nützt aber alles nix, weil hier nicht nach dem i.d.R. definierten 
Verhalten eines Prozessors gefragt wurde, sondern nach dem undefinierten 
(nicht: unspezifizierten!) Verhalten von Compiler bzw. dessen Rumtime.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tipp des Tages schrieb:
> Zahlreiche Prozessoren kennen ein Exception-Handling

Ein AVR hat sowas jedoch nicht.

W.S. schrieb:
> Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die
> ANSI-Vorgaben hält - als Ergebnis eine NAN.

Nein.  Man bekommt ein (vorzeichengerechtes) Inf, und das ist völlig
korrekt: wenn man eine von Null verschiedene Zahl durch Null teilt,
kommt nun einmal Unendlich dabei raus.  (Dass sich die originale
Frage jedoch auf Ganzzahlen bezog, wurde ja bereits erwähnt.)

Für den simplen (compilezeit-konstanten) Fall wie in obigem Beispiel
wird es sehr wahrscheinlich natürlich der Compiler schon bemerken.

: Bearbeitet durch Moderator
von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:
> Nein.  Man bekommt ein (vorzeichengerechtes) Inf, und das ist völlig
> korrekt: wenn man eine von Null verschiedene Zahl durch Null teilt,
> kommt nun einmal Unendlich dabei raus.

Man kann zwar das praktische Verhalten von Hardware oder Libs so 
definieren, mathematisch bleibt es jedoch undefiniert.
https://de.wikipedia.org/wiki/Division_(Mathematik)#Ist_.C2.B9.E2.81.84.E2.82.80_.3D_.E2.88.9E.3F

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Jörg Wunsch schrieb:
>> Nein.  Man bekommt ein (vorzeichengerechtes) Inf, und das ist völlig
>> korrekt: wenn man eine von Null verschiedene Zahl durch Null teilt,
>> kommt nun einmal Unendlich dabei raus.
>
> Man kann zwar das praktische Verhalten von Hardware oder Libs so
> definieren, mathematisch bleibt es jedoch undefiniert.
>

Letzen Endes ist es aber in der Praxis auch ziemlich egal.
Wenn bei einer Division die Möglichkeit besteht, durch 0 zu dividieren, 
dann muss dieser Fall gesondert behandelt werden. Und zwar bevor man 
dividiert.
Erleichtert wird dieses dadurch, dass eine versuchte Division durch 0 
sowieso meistens irgendeinen speziellen Sonderfall darstellt, den ich 
sowieso getrennt behandeln möchte. Und dann ist die vorlaufende 
Erkennung dieses Sonderfalls normalerweise bei weitem einfacher, als 
hinterher ein undefiniertes Divisionsergebnis zu erkennen und zu 
bearbeiten.

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Karl Heinz schrieb:
> als
> hinterher ein undefiniertes Divisionsergebnis zu erkennen

Undefiniert steht in der Compiler-Spezifikation, der Prozessor hat im 
konkreten Fall natürlich ein definiertes Ergebnis, wenn auch 
möglicherweise ein zufälliges. Es kommt aber nicht wirklich drauf an, ob 
man sich darauf versteift, dass das Ergebnis der Division undefiniert 
ist oder unendlich, weil man so oder so damit nicht weitermachen kann 
(der Prozessor kennt auch kein Unendlich). Genausowenig hilft die 
Darstellung NAN, die es bei real gibt, das bringt einen auch nicht 
weiter als eine Exception.

Da ist ganz einfach der Programmierer gefragt, was geschehen soll.

Georg

von Sean G. (atmega318)


Lesenswert?


von Paul Baumann (Gast)


Lesenswert?

Die Frage ist wirklich ernst gemeint:
Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext
gibt, der eine Division durch Null erzeugt?

(Ich kann es nicht probieren, weil ich hier keinen derartigen Kram
auf dem Rechner habe und ihn auch nicht installieren könnte bzw. dürfte)

MfG Paul

von Karl H. (kbuchegg)


Lesenswert?

Paul Baumann schrieb:
> Die Frage ist wirklich ernst gemeint:
> Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext
> gibt, der eine Division durch Null erzeugt?

Was ein ordentlicher Compiler ist, wird im Zuge der Constant-Folding 
Optimierung drauf kommen, dass hier durch 0 dividiert wird und eine 
entsprechende Warnung rausgeben.
Verpflichtet dazu ist er, wie bei allen Warnungen, allerdings nicht.
Im C-Standard gibt es keine Warnungen. Im C Standard steht nur, was ein 
Error ist und was nicht. Warnungen sind freiwillige Serviceleistungen 
des Compilers.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Paul Baumann schrieb:
> Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext
> gibt, der eine Division durch Null erzeugt?

GCC gibt eine Warnung. Wenn er es merkt.

von David .. (volatile)


Lesenswert?

main.c:163: warning: division by zero

von Georg (Gast)


Lesenswert?

Paul Baumann schrieb:
> Läßt sich das ein "C"-Kompiler gefallen

Naja, nehmen wirs mal ernst: was verstehst du unter "gefallen lassen"? 
Wenn er es merkt übersetzt er das Programm nicht oder gibt wenigstens 
eine Warnung aus - das kann man einstellen, man hat also in der Hand, 
was er sich gefallen lässt. Es macht aber wenig Sinn, alle Fehler und 
Warnungen abzustellen, da kommt keine brauchbare Software raus.

Georg

von Klaus W. (mfgkw)


Lesenswert?

Paul Baumann schrieb:
> Die Frage ist wirklich ernst gemeint:
> Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext
> gibt, der eine Division durch Null erzeugt?

Ja.
Wenn er schlau ist, kann er vieleicht eine Warnung ausgeben, aber 
prinzipiel geht es ihn nix an, wenn du so etwas machst.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Tipp des Tages schrieb:
> Die Frage ist absolut berechtigt.  Zahlreiche Prozessoren kennen ein
> Exception-Handling, bei dem z.B. unterschiedliche Interrupts ausgelöst
> werden.
> Bei den x86 kompatiblen gibt es einen eigenen Interrupt für Division
> durch Null.

Diese Prozessoren können dividieren. Ein AVR aber kann das nicht.

Verwechsle nicht Hochsprache mit den vom Prozessor ausgeführten 
Maschinenbefehlen - bei einem Prozessor, der keine Division kennt, ist 
eine Exception (oder ein Software-Interrupt) für einen Divisionsfehler 
ziemlich ... nutzlos.

von Axel S. (a-za-z0-9)


Lesenswert?

Georg schrieb:
> Karl Heinz schrieb:
>> als
>> hinterher ein undefiniertes Divisionsergebnis zu erkennen
>
> Undefiniert steht in der Compiler-Spezifikation, der Prozessor hat im
> konkreten Fall natürlich ein definiertes Ergebnis

Frage nicht gelesen? Ein AVR hat keinen Divisionsbefehl. Eine Division, 
ganz egal ob Ganzzahl oder Fließkomma wird immer von einer Biblio- 
theksfunktion ausgeführt. Und deren Verhalten ist zwar sicher für eine 
spezifische Toolchain vorhersagbar, im Allgemeinen jedoch undefiniert.

> wenn auch möglicherweise ein zufälliges.

Das nun ganz sicher nicht. Computer funktionieren deterministisch.

> Genausowenig hilft die
> Darstellung NAN, die es bei real gibt, das bringt einen auch nicht
> weiter als eine Exception.

Der Punkt ist, daß C für Arithmetik keine Exceptions vorsieht. Weder für 
Division durch Null noch (was sehr nützlich wäre) für einen Überlauf. 
Und weil es keine out of band Signalisierung gibt, hat man die NaN 
Pseudowerte eingeführt, um wenigstens in band signaling zu haben. Weil 
man dafür aber den Wertebereich des Ergebnisses einschränken muß hat man 
es nur für Fließkommazahlen gemacht, weil es da ohnehin schon ungültige 
interne Darstellungen gibt, von denen man einfach ein paar passend 
umdefiniert hat.

Langer Rede kurzer Sinn: das NaN Ergebnis ist die Exception.


XL

von Paul Baumann (Gast)


Lesenswert?

Danke für die Antworten auf meine Frage. Es stellt sich aber gleich
noch eine: Wenn ich den Text von Axel richtig verstanden habe, dann
gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander
multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch
in eine Bytevariable hineinwürgen will?

Wenn das so ist, will ich kein "C" haben.

MfG Paul

von Georg (Gast)


Lesenswert?

Axel Schwenke schrieb:
> Das nun ganz sicher nicht. Computer funktionieren deterministisch.

Wie würdest du denn den Inhalt nicht initialisierter Variablen 
bezeichnen? Klar arbeitet ein Prozessor deterministisch, aber für den 
Programmierer ist der Inhalt nicht vorhersehbar. Man kann ja auch 
behaupten, die Brownsche Molekularbewegung sei in Wirklichkeit 
deterministisch, bloss hilft das überhaupt nicht weiter.

Georg

von Karl H. (kbuchegg)


Lesenswert?

Paul Baumann schrieb:

> Wenn das so ist, will ich kein "C" haben.

C ist eben nichts für Leute, die die Tante brauchen um Lulu zu gehen.

Dein heiss geliebtes BASCOM hat auch so seine Probleme.

von Paul Baumann (Gast)


Lesenswert?

Karl Heinz schimpfte:
>C ist eben nichts für Leute, die die Tante brauchen um Lulu zu gehen.

War Dir das Mittagessen zu heiß?

>Dein heiss geliebtes BASCOM hat auch so seine Probleme.

Das habe ich mit keinem Wort behauptet. Was hier los ist....

:-(

Paul

von Amateur (Gast)


Lesenswert?

Irgendwie geht hier etwas durcheinander.
Nämlich das Verhalten eines Atmel und "C".
1. Soweit mir bekannt juckt es einen AVR kein bisschen, wenn der
   durch Nix teilen soll.
2. Vor längerer Zeit habe ich mal eine 16-Bit Division aus den AVR-
   Bibliotheken extrahiert. Da war keine explizite Abfrage auf null.
3. NaN kenne ich nur im Zusammenhang mit Fließkommazahlen bzw.
   -bibliotheken. Darum ging’s hier aber nicht. Das Verhalten hier
   hängt wohl vom Compiler bzw. davon ab, ob man C oder C++ verwendet.

von Karl H. (kbuchegg)


Lesenswert?

Paul Baumann schrieb:

>>Dein heiss geliebtes BASCOM hat auch so seine Probleme.
>
> Das habe ich mit keinem Wort behauptet. Was hier los ist....

Vielleicht kannst du dir vorstellen, das mit dieses dauernde C-Bashing 
mitlerweile schon ganz gehörig auf den Sack geht? Zumal viele derartige 
'Untergriffe' immer wieder von Leuten kommen, die C überhaupt nicht 
ausreichend beherrschen um sich hier ein Urteil erlauben zu können. 
Ausserdem behauptet auch niemand, dass C das Beste seit geschnittenem 
Brot wäre. Alle C Programmierer sind sich bewusst, dass die Sprache ihre 
Problemkreise hat (die meistens dann auch gar nicht in den Bereichen 
angesiedelt sind, die immer wieder gerne von "C-Laien" kritisiert 
werden)

von npn (Gast)


Lesenswert?

Amateur schrieb:
> 1. Soweit mir bekannt juckt es einen AVR kein bisschen, wenn der
>    durch Nix teilen soll.

Es kann ihn ja auch nicht jucken. Er hat schlicht keinen 
Divisionsbefehl. Also wird er niemals dividieren.
Die Division wird lediglich durch den Compiler nachgebildet, und genau 
darum dreht sich die Diskussion in letzter Zeit. Nicht um den AVR.

von Paul Baumann (Gast)


Lesenswert?

Karl Heinz schrie:
>Vielleicht kannst du dir vorstellen, das mit dieses dauernde C-Bashing
>mitlerweile schon ganz gehörig auf den Sack geht?

Ich habe mir nur erlaubt, 2 Fragen zu stellen -nicht mehr.

>Zumal viele derartige
>'Untergriffe' immer wieder von Leuten kommen, die C überhaupt nicht
>ausreichend beherrschen um sich hier ein Urteil erlauben zu können.

Ich beherrsche C nicht nur nicht ausreichend, sondern überhaupt nicht
Das war auch der Grund für meine Fragen, die ich anderenfalls gar nicht
hätte stellen müssen.

Im Übrigen ist auch nicht die Pflicht eines Moderators, auf jeden
Artikel zu antworten, dessen Inhalt nicht seinen Gefallen findet!

Paul

von David .. (volatile)


Lesenswert?

Paul Baumann schrieb:
> Ich habe mir nur erlaubt, 2 Fragen zu stellen -nicht mehr.

Nimms nicht persoenlich - Nein, du fragst nicht sachlich, sondern 
abwertend - das fiel auch mir auf.
Du musst ja kein C nutzen, aber in einem Thread wie diesem ist 
irrelevant, was du von C haeltst...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul Baumann schrieb:
> Ich habe mir nur erlaubt, 2 Fragen zu stellen -nicht mehr.

Nö, Paul:

Paul Baumann schrieb:
> Wenn das so ist, will ich kein "C" haben.

Das war das, was Karl Heinz „auf die Palme“ gebracht hat und was
er als „C-Bashing“ bezeichnet.

von (prx) A. K. (prx)


Lesenswert?

Axel Schwenke schrieb:
> Und weil es keine out of band Signalisierung gibt, hat man die NaN
> Pseudowerte eingeführt, um wenigstens in band signaling zu haben.

Die Entwicklung von IEEE 754 hat nichts mit C zu tun. In den 70ern gab 
es ein Sammelsurium verschiedener Fliesskommaformate, jeder Hersteller 
hatte eigene. C hingegen kannte damals kaum jemand. Dass man sich in 
diesem Rahmen auch um Grenzverhalten und unzulässige Operationen kümmert 
ist nur konsequent. Wobei IEEE 754 seinerseits abschaltbare Exceptions 
vorsieht.

Die Sprache C andererseits verlangt bis heute nicht die Konformität zu 
IEEE 754 bzw. IEC 60559 und definiert auch kein bestimmtes Verhalten bei 
sigalling NaNs. Das sind einfach zwei verschiedene Paar Stiefel, 
entspricht es doch dem Leitmotiv, möglichst wenig Plattformspezifika in 
die Sprache hinein zu definieren.

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

Georg schrieb:
> Axel Schwenke schrieb:
>> Das nun ganz sicher nicht. Computer funktionieren deterministisch.
>
> Wie würdest du denn den Inhalt nicht initialisierter Variablen
> bezeichnen? Klar arbeitet ein Prozessor deterministisch, aber für den
> Programmierer ist der Inhalt nicht vorhersehbar.

Und was läßt dich glauben, eine Divisionsroutine würde bei einer 
Division durch Null einfach den Inhalt einer nicht initialisierten 
Variablen zurückgeben?

Mal abgesehen davon, daß ein solches Verhalten vom Standard gedeckt 
wäre: ich würde eine solche Laufzeitbibliothek mit maximaler Skepsis 
betrachten.


XL

von Helge (Gast)


Lesenswert?

Wow, was für eine Diskussion.
1
void setup() {
2
  // initialize serial communications at 9600 bps:
3
  Serial.begin(9600);
4
}
5
6
void loop() {
7
8
  Serial.print("Was ist 1/0  ? Es ist ");
9
  int x=1;
10
  int y=0;
11
  Serial.println(x/y);
12
13
  delay(1000);
14
}

Mein Arduino sagt:

Was ist 1/0  ? Es ist -1
Was ist 1/0  ? Es ist -1
Was ist 1/0  ? Es ist -1
Was ist 1/0  ? Es ist -1
Was ist 1/0  ? Es ist -1

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Helge schrieb:
> Mein Arduino sagt:

...was auch immer der Compiler zur Übersetzungszeit da reinschreibt.

Viel interessanter ist der nicht konstante Fall, also was zur
Laufzeit wirklich dann ausgerechnet wird.

Aber da es sich um undefiniertes Verhalten handelt, kann das — selbst
wenn man heute ein bestimmtes, nachvollziehbares Verhalten
feststellen kann — schon übermorgen ganz anders aussehen.

Der einzig korrekte Weg kann also nur sein, dass man den Divisor vor
der Division gegen 0 testet und dann seine eigene Ausnahmebehandlung
implementiert.

: Bearbeitet durch Moderator
von Cyblord -. (cyblord)


Lesenswert?

Jörg Wunsch schrieb:
> Helge schrieb:
>> Mein Arduino sagt:
>
> ...was auch immer der Compiler zur Übersetzungszeit da reinschreibt.

Nur schade dass der normale Arduino User absolut keine Vorstellung 
dieser zusammenhänge hat. Compiler, Linker, Präprozessor, Laufzeit alles 
ein dichter Nebel an Worthülsen der die Insel der Verzweiflung umweht.

von Axel S. (a-za-z0-9)


Lesenswert?

Paul Baumann schrieb:
> Wenn ich den Text von Axel richtig verstanden habe, dann
> gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander
> multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch
> in eine Bytevariable hineinwürgen will?

So ist es. C abstrahiert Register und ALU einer CPU zu Variablen und 
arithmetischen/logischen Operatoren. Leider fällt bei dieser Abstraktion 
auch das Flagregister der ALU mit hinten runter. Es wäre in vielen 
Fällen enorm hilfreich, die Flags auch auf Hochsprachenebene zur 
Verfügung zu haben.

Die kanonische Lösung besteht darin, die Rechnung immer mit dem nächst- 
größeren Typ zu machen (bzw. allgemein einem Typ bei dem man sicher ist, 
daß er das Ergebnis in jedem Fall halten kann). Was natürlich immer dann 
zum Problem wird, wenn man Rechnungen mit dem längsten verfügbaren Typ 
macht.

> Wenn das so ist, will ich kein "C" haben.

Bei anderen Programmiersprachen bist du da auch nicht besser aufgehoben. 
Im Prinzip könnte man auch die C Laufzeitbibliothek so auslegen, daß sie 
in solchen Fällen einen Laufzeitfehler auslöst (wie es z.B. Turbopascal 
macht). Man macht es aber nicht, weil es den Code für den Normalfall 
(kein Überlauf) langsamer machen würde. Und auch weil nicht abfangbare 
Exceptions bäh sind. Gerade bei einem µC sollte das einleuchten.


XL

von (prx) A. K. (prx)


Lesenswert?

Axel Schwenke schrieb:
> Mal abgesehen davon, daß ein solches Verhalten vom Standard gedeckt
> wäre: ich würde eine solche Laufzeitbibliothek mit maximaler Skepsis
> betrachten.

In der PowerPC Spezifikation ist der Inhalt des Zielregisters bei einer 
ganzzahligen Division durch 0 undefiniert. Eine Exception ist damit 
nicht verbunden, jedenfalls nicht im Divisionsbefehl selbst.

Es kann also durchaus sein, dass das Zielregister in diesem Fall nicht 
verändert wird. Wenn in diesem Register vorher eine echte Zufallszahl 
drin stand, dann hast du deine Division durch 0 mit echt zufälligem 
Ergebnis.

Spass am Rande: Aus der Systematik der PowerPC Befehle ergeben sich 
Varianten von Divisionbefehlen, bei denen im Fall einer Division durch 0 
weder eine Exception noch irgendein anderes definiertes Ergebnis 
vorliegt, auch keine Flags. Also schlicht nichts definiert ist.

: Bearbeitet durch User
von Paul B. (paul_baumann)


Angehängte Dateien:

Lesenswert?

@Axel
Danke für Deine Antwort.

Karl-Heinz schrub:
>Dein heiss geliebtes BASCOM hat auch so seine Probleme.

Richtig. Als Beweis dafür hänge ich ein Bild an, aus dem hervorgeht,
daß eine Division durch Null zum Ergebnis 255 führt, wenn das Ergebnis
als Byte dimensioniert ist. Als Single kommt Null heraus. Auch der 
Bascom-
kompiler läßt sich also so einen Unfug gefallen.


>> Wenn das so ist, will ich kein "C" haben.
Jörg schrabte:
>Das war das, was Karl Heinz „auf die Palme“ gebracht hat und was
>er als „C-Bashing“ bezeichnet.


Gut, dann muß ich im Forum "Markt" eine Annonce aufgeben, daß ich nach
einer Goldwaage suche, auf die ich meine Worte legen kann...
;-)

MfG Paul

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul Baumann schrieb:
> Gut, dann muß ich im Forum "Markt" eine Annonce aufgeben, daß ich nach
> einer Goldwaage suche, auf die ich meine Worte legen kann...

Eine Laborwaage tut's auch.  Wenn du keine hast, bei mir im Keller
steht eine, schick die Worte einfach vorher zu mir, ich leg' sie
dann mal drauf. ;-)

von c-hater (Gast)


Lesenswert?

Paul Baumann schrieb:

> Danke für die Antworten auf meine Frage. Es stellt sich aber gleich
> noch eine: Wenn ich den Text von Axel richtig verstanden habe, dann
> gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander
> multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch
> in eine Bytevariable hineinwürgen will?

Nein, natürlich nicht. Könnte ja auch passen, Z.B. 1*1=1 paßt.

> Wenn das so ist, will ich kein "C" haben.

Das will man sowieso nicht. Allerdings hat das ganz andere Gründe.

Numerische Überläufe ggf. auch ignorieren zu können, ist jedenfalls eine 
Eigenschaft einer Programmiersprache, die sowohl extrem nützlich als 
auch hochgefährlich sein kann. Wenn du das noch nicht begriffen hast, 
bist du ein Lamer, der sich aus solchen Diskussionen einfach mal 
raushalten sollte.

So einfach ist das.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Was passieren kann wurde ja bereits gesagt, wobei sich das auf 
int-Division bezieht:

A. K. schrieb:
> C definiert eine Division durch 0 als "undefiniert".

Konkret:

>> C99 3.4.3 undefined behavior
>>
>> behavior, upon use of a nonportable or erroneous program
>> construct or of erroneous data, for which this International
>> Standard imposes no requirements.
>>
>> NOTE
>>
>> Possible undefined behavior ranges from ignoring the
>> situation completely with unpredictable results, to behaving
>> during translation or program execution in a documented
>> manner characteristic of the environment (with or without
>> the issuance of a diagnostic message), to terminating a
>> translation or execution (with the issuance of a diagnostic
>> message).

von Mike (Gast)


Lesenswert?

Helge schrieb:
> Mein Arduino sagt:
>
> Was ist 1/0  ? Es ist -1

Und wer hat da jetzt gerechnet?

War das der Compiler auf dem PC, der richtig erkannt hat, dass er die 
ganze Rechnung wegoptimieren kann und nur eine Konstante ausgeben muss, 
oder war das der AVR, der wirklich zwei Zahlen durch einen Algorithmus 
gejagt hat, den man im Quellcode mit "/" kennzeichnet?

Da sollte man erstmal in den lst-File gucken, was der AVR zu dem 
Ergebnis beigetragen hat.

von Helge (Gast)


Lesenswert?

>Und wer hat da jetzt gerechnet?

Das sollte Jörg beantworten können, er ist am nächsten drann beim 
Compilerbau.

von Paul B. (paul_baumann)


Lesenswert?

C-Hater erklärte großspurig:
>Numerische Überläufe ggf. auch ignorieren zu können, ist jedenfalls eine
>Eigenschaft einer Programmiersprache, die sowohl extrem nützlich als
>auch hochgefährlich sein kann. Wenn du das noch nicht begriffen hast,
>bist du ein Lamer, der sich aus solchen Diskussionen einfach mal
>raushalten sollte.

Nein, ich habe noch nicht begriffen, wozu das nützlich sein könnte.
Aber Du kannst es ja mal kurz und prägnant erklären. Schließlich
will ich ja kein Lamer sein, es reicht mir, mit verstauchtem Fuß
ein Lahmer zu sein.

SCNR
Paul

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Helge schrieb:
> Das sollte Jörg beantworten können, er ist am nächsten drann beim
> Compilerbau.

Nö, Johann.  Hat sich ja schon ausreichend zu Wort gemeldet hier.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Das "Ergebnis" kommt von den __[u]divmod{q,h,ps,s,d}i4 Routinen der 
libgcc, die im Falle von avr-gcc in Assembler implementiert sind.

AFAIR liefern diese bei einem Divisor von 0 einen Quotienten, bei dem 
alle Bits gesetzt sind.  Für den Rest kann es jeder bei Interesse selbst 
nachvollziehen:

http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs.S?content-type=text%2Fplain&view=co

Für die nicht zwingend saturierenden Fixed-Point Divisionen sind m.W. 
ebenfalls so, daß diese auf den Maximal- bzw. Minimal-Wert hin 
Saturieren.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Helge schrieb:
> Das sollte Jörg beantworten können, er ist am nächsten drann beim
> Compilerbau.

Dafür brauchts keinen Compilerbau. Testcode übersetzen und reinsehen 
reicht. Ich selber würde es allerdings auch nicht dem Compiler, sondern 
der Runtime überlassen, damit sich ein konsistentes Verhalten ergibt, 
auch wenn das von der Sprache selbst nicht gefordert wird.

von W.S. (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Der einzig korrekte Weg kann also nur sein, dass man den Divisor vor
> der Division gegen 0 testet und dann seine eigene Ausnahmebehandlung
> implementiert.

Jörg, manchmal regst du mich auf. Eine NAN kriegt man auch bei 
Überläufen - und die gibt's dann AUCH, wenn der Divisor ungleich Null 
ist. Das Ergebnis braucht bloß zu groß zu sein. Wenn du (wie ich) massiv 
mit Meßwerten zu tun hast, wo Kunden irgendwo ihre Anlagen falsch 
einjustieren und dann sowas wie 1.234E+30/1.234E-33 zuwege bringen, dann 
klemmt es OHNE daß man als Programmierer viel dagegen tun kann, außer 
sowas wie if (fabs(x)<1E-29)...

Weitaus besser wäre es, wenn bei all den saubescheuerten Gleitkomma-Libs 
genau SO verfahren worden wäre wie in der digitalen Signalverarbeitung, 
wo Übersteuerungen (die immer mal vorkommen) einfach durch sättigendes 
Verhalten abgefangen werden. Wenn dann mal 123/0 vorkommt, dann gibt das 
eben 7FFFFFFFh und fertig. Respektive -123/0 --> 80000000h

Man macht bei sowas keinen wirklich relevanten Fehler und spart sich ne 
Menge Telefonate.

W.S.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> Jörg, manchmal regst du mich auf. Eine NAN kriegt man auch bei
> Überläufen

Du uns auch: in diesem Thread geht es um ganzzahlige Divisionen,
und da brauchen wir über NaNs nicht weiter zu diskutieren.

Wenn du über Sinn und Unsinn von IEEE754 diskutieren willst, dann
öffne bitte einen eigenen Thread.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> Weitaus besser wäre es, wenn bei all den saubescheuerten Gleitkomma-Libs
> genau SO verfahren worden wäre wie in der digitalen Signalverarbeitung,

Du bringst hier ein Beispiel, in dem saturierende Arithmetik sinnvoll 
ist. Es gibt andere, wo es geradezu kriminell leichtsinnig wäre, 
sinnvolle Ergebnisse vorzutäuschen, wo doch zur Laufzeit bereits bekannt 
ist, dass sie kompletter Unsinn sind.

Leb damit, oder such dir eine Laufzeit oder Hardware, die deinen 
Wünschen entsprechend arbeitet. Wenn solches Verhalten bei DSPs wirklich 
bedeutend ist, dann sollte es welche geben, die sich entsprechend 
verhalten. Die Sprache C lässt das zu, sie verlangt nicht nach IEEE 754.

: Bearbeitet durch User
von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

@Paul

Mein C-Compiler(CVAVR) erkennt, wenn Multiplikationen oder Additionen 
möglicherweise zu Überläufen der Zielvarable führen ebenso erkennt er 
möglche Unterläufe und mögliche Nulldivisionen.

 Das alles meldet er während der Compilation. Ich habe dann die 
Möglichkeit dies zu ignorieren oder abzufangen.

 Meist habe ich die Varablen dann double oder long oder longlong 
definiert bzw. wenn der Definitonsbereich klar war und die 
Überschreitung nur theoretisch aber nicht real möglich war die Warnung 
ignoriert.
Bis jetzt hatte ich damit nie ein Problem.

von Simon S. (-schumi-)


Lesenswert?

Ich hatte das vor langem mal ausprobiert, es scheint so zu sein 
(tiny2313):
 irgendwas / 0 = alle Bits high
 0 / 0 = 0

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Simon S. schrieb:
> Ich hatte das vor langem mal ausprobiert

Trotzdem nochmal: das ist nicht garantiert, und kann und darf sich
bereits mit der nächsten Version von Compiler oder Bibliothek ändern.

von Axel S. (a-za-z0-9)


Lesenswert?

AMEN!

von Paul Baumann (Gast)


Lesenswert?

@Wilfried

Danke für Deine vernünftige Antwort. Das hat manch Einer hier nicht
drauf, einfach nur eine Frage zu beantworten, ohne eine Axt 
hinterherzuwerfen.

;-)

MfG Paul

von Route_66 H. (route_66)


Lesenswert?

Paul Baumann schrieb:
> @Wilfried

Er heißt Winfried!
Brille? - Wenigfrau!

von Paul Baumann (Gast)


Lesenswert?

Route66 schrub:
>Er heißt Winfried!
Das kommt davon, daß mein Kollege Wilfried heißt. Grmmlhmpf!
;-)

>Brille? - Wenigfrau!

Wenigfrau?
:-)))
Wunderbar!

Kannst Du mal meine Brille beschlagen? Ach, das wird mir jetzt ein 
bisschen
fiel, Mann!

MfG Paul

von (prx) A. K. (prx)


Lesenswert?

Paul Baumann schrieb:
> Wenigfrau?

Eigentlich müsste es "Venigfrau" heissen.

> Kannst Du mal meine Brille beschlagen?

Gestell kaputt? Hufeisen vorm Kopp sehen aber ziemlich doof aus.

: Bearbeitet durch User
von Ralf G. (ralg)


Lesenswert?

[NEBENBEI]
Paul Baumann schrieb:
> Wenn das so ist, will ich kein "C" haben.
Wer das nicht versteht, wenn's von Paul kommt, den verstehe ich nicht!
[/NEBENBEI]

@Paul
Vom Compiler zu verlangen, dass er sich um 'Division durch null' oder 
'tan(90°)' kümmert, ist einfach Unsinn (sag ich jetzt mal so).
Sicher ist das kein Problem, sowas zu integrieren, aber das schleppt man 
dann in jedem Programm mit rum! Jeden Sonderfall! Alles! Und das 
Ergebnis? Ist einfach falsch:
W.S. schrieb:
> Wenn dann mal 123/0 vorkommt, dann gibt das
> eben 7FFFFFFFh und fertig. Respektive -123/0 --> 80000000h
In vielen Fällen wird die Genauigkeit reichen. Aber mathematisch exakt 
ist das nicht. Wem das reicht, der setzt das in seinem Programm einfach 
selbst so um.
Denn es geht in der Hauptanwendung von 'C' nicht um ein paar 
LED-Basteleien ;-)

Paul Baumann schrieb:
> Wenn ich den Text von Axel richtig verstanden habe, dann
> gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander
> multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch
> in eine Bytevariable hineinwürgen will?
Genau aus dem gleichen Grund, wie oben. Vorher (kurz) überlegen, und 
dann nimmt man den richtigen Wertebereich.

von Paul Baumann (Gast)


Lesenswert?

Ralf schrub:
>Vorher (kurz) überlegen, und dann nimmt man den richtigen Wertebereich.

Ja, ist ja richtig. Nur: Wem das noch nicht passiert ist, das falsche
Format für seine Ausgabe zu erwischen, der werfe mit dem ersten Trafo!
;-)

MfG Paul

von Ralf G. (ralg)


Lesenswert?

Paul Baumann schrieb:
> Nur: Wem das noch nicht passiert ist, das falsche
> Format für seine Ausgabe zu erwischen,
Das kommt sicher vor! "C" ist eben nicht für uns Bastler gedacht. Wir 
verwenden es nur. Aber wer da ernsthaft damit arbeitet (auch 
hobbymäßig), der schätzt den daraus resultierenden schlanken Code.

(In jedem Beruf gibt's Stolperfallen!)

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
Noch kein Account? Hier anmelden.