Rechnen mit unterschiedlichen Datentypen

Hallo,

ich habe ein Frage zum Rechnen mit verschiedenen Datentypen. Siehe folgenden Sketch

void setup() {
  Serial.begin(9600);
  long secSunriseOpen;
  int sunriseOpenmin = 20;
  int sunriseOpenh = 17;
  
  secSunriseOpen = (sunriseOpenmin * 60) + (sunriseOpenh * 3600);

    Serial.println(sunriseOpenmin);
    Serial.println(sunriseOpenh);
    Serial.println(secSunriseOpen);
}
void loop() {
}

Als Ausgabe erhalte ich :
20
17
-3136

Die Variable secSunriseOpen schein also überzulaufen obwohl sie als long definiert wurde. Wenn ich die anderen 2 Variablen auch als long definiere funktioniert die Berechnung.

Warum wird hier das secSunriseOpen als int interpretiert ?
Gibt es einen eleganten Weg um dies zu umgehen ohne die Eingangsvariablen auch als long zu definieren?

Gruß
Arduino Arti

ArduinoArti:
Warum wird hier das secSunriseOpen als int interpretiert ?
Gibt es einen eleganten Weg um dies zu umgehen ohne die Eingangsvariablen auch als long zu definieren?

https://www.arduinoforum.de/code-referenz
Das pdf runterladen.
Seite 29

Der Ziel-Datentyp ist erst mal egal. Gerechnet wird standardmäßig in int wenn nichts dabei steht. Außerdem hast du klar int * int. Was also wiederum int ist. Das Ergebnis wird dann dem Ziel zugewiesen

Korrekt:

  secSunriseOpen = (sunriseOpenmin * 60UL) + (sunriseOpenh * 3600UL);

Damit hast du int * unsigned long. Was unsigned long ist

Außerdem solltest du generell unsigned Typen verwenden wenn du keine negativen Ergebnisse erwartest

Serenifly:
Der Ziel-Datentyp ist erst mal egal. Gerechnet wird standardmäßig in int wenn nichts dabei steht. Außerdem hast du klar int * int. Was also wiederum int ist. Das Ergebnis wird dann dem Ziel zugewiesen

Korrekt:

  secSunriseOpen = (sunriseOpenmin * 60UL) + (sunriseOpenh * 3600UL);

Ist das zweite UL nicht IMHO overhead? Ich handhabe es bisher so, das nur der erste Wert als L/UL deklariert wird. Muss ich mir Sorgen machen? Ein weiteres = ist ja nicht drin..

Vielen Dank euch beiden.

my_xy_projekt:
Ist das zweite UL nicht IMHO overhead? Ich handhabe es bisher so, das nur der erste Wert als L/UL deklariert wird. Muss ich mir Sorgen machen? Ein weiteres = ist ja nicht drin..

In diesem Fall dürfte folgendes auf jeden Fall reichen

secSunriseOpen = (sunriseOpenmin * 60) + (sunriseOpenh * 3600UL);

Ja, könnte man sich wahrscheinlich sparen. Aber so extrem optimieren muss man hier auch nicht. Ich weiß dass wir hier gerne vorauseilend alles optimieren und "perfekt" machen wollen, aber wenn es nicht unbedingt nötig ist bringt das nicht viel

(deleted)

Am besten du sagst dem Kompilator mit welchen Datentypen er rechnen soll.

secSunriseOpen = ((long)sunriseOpenmin * 60) + ((long)sunriseOpenh * 3600);

Wobei hier mein "Anstand" sagt, dass ein impliziter Cast, welcher zu einer Erweiterung des Datentypes führt, bedenkenlos akzeptabel ist.
Hier ist kein expliziter nötig ist, es reicht die Literale, beide, mit einem L zu versehen.

Bei einer absichtlichen Datentype "Verkleinerung" würde das anders aussehen.
Dort fordere ich (von mir selber) einen Cast, alleine schon um den Fall im Code selber zu dokumentieren.

Auch kostet es wenig, wenn man statt eines int Literal ein long Literal verwendet.
Der Compiler kanns es ja noch optimieren, ......
So ist, aus meiner Sicht, die richtige Lösung:

(sunriseOpenh * 3600L) + (sunriseOpenmin * 60L);
oder eben so
(sunriseOpenmin * 60L) + (sunriseOpenh * 3600L);

Ok, ok, ich gebs zu!
Das ist eher eine Glaubensfrage, oder eine Sache der Prinzipienreiterei
(um nicht "Disziplin" sagen zu müssen)

Ich sehe, ich bin allein:

combie:

:wink:

Das ist eher eine Glaubensfrage, oder eine Sache der Prinzipienreiterei

Du bist doch sonst nicht so!

Du bist doch sonst nicht so!

Doch, genau so bin ich!

Fakt:
Der signed Überlauf ist ausdrücklich nicht definiert.
Der C++ Standard sagt, dass ein solcher Überlauf in ein "undefined Behavior" mündet.

Das wollen "WIR" nicht.
Von daher ist es erste Programmiererpflicht, dieses zu unterbinden.
Über die Art und Weise, das zu tun, kann man sich unterhalten, oder gar streiten.
Aber der Fakt, der steht da, in all seiner Unabwendbarkeit.

Hallo,

der TO benötigt aber kein signed. Hatte schon Serenifly festgestellt. Also UL Literal und gut ist.

Doc_Arduino:
Hallo,

der TO benötigt aber kein signed. Hatte schon Serenifly festgestellt. Also UL Literal und gut ist.

Nein, das reicht dann nicht.

Siehe:

  long secSunriseOpen;

int sunriseOpenmin = 20;
  int sunriseOpenh = 17;

Für mich ist das eindeutig alles signed.
Da macht es doch keinerlei Sinn, nur die Literale als unsigned zu definieren.

Ganz, oder gar nicht.
Oder, liege ich da so falsch?

Zudem weiß ich gar nicht, ob der TE nicht doch signed benötigt, um mit negativen Zeiten arbeiten zu können.
Du scheinst da mehr zu wissen....

combie:
Für mich ist das eindeutig alles signed.

Wie kommst Du darauf?

Ausgangslage ist der Sketch aus #0.

void setup() {
  Serial.begin(9600);
  long secSunriseOpen;
  int sunriseOpenmin = 20;
  int sunriseOpenh = 17;
 
  secSunriseOpen = (sunriseOpenmin * 60) + (sunriseOpenh * 3600);

    Serial.println(sunriseOpenmin);
    Serial.println(sunriseOpenh);
    Serial.println(secSunriseOpen);
}
void loop() {
}

Es gibt keine Konstellation, die an irgendeiner Stelle ins negative geht.

Unbestritten: Es können sich im Nachhinein die Bedingungen ändern. Dann(!) muss sich darum bemüht werden.

Wie kommst Du darauf?

Steht doch da!

Im eingangs gezeigten Programm sind alle gezeigten Variablen und Berechnungen signed.
Ohne jede Ausnahme.

Wenn du da was anderes siehst, dann siehst du Geister.

Bedenke:
Der Kompiler sieht deine Geister nicht, nur das, was notiert wurde.

Ob jetzt das signed, für alles, so beabsichtigt ist, kann ich natürlich nicht sagen.
Ist mir auch, ehrlich gesagt, erstmal vollkommen egal.

Merke:
Das Eingangsproblem war die Breite des Datentypes und nicht ob Vorzeichen behaftet, oder nicht.

combie:
Steht doch da!

Nein.
Du weisst es doch selbst, das der Compiler schlau sein will und aufgrund seiner eigenen Schlauheit optimiert.

Im eingangs gezeigten Programm sind alle gezeigten Variablen und Berechnungen signed.
Ohne jede Ausnahme.

Das bestreite ich nicht.
Aber jetzt kommt die Frage der Fragen:
Dem Compiler ist bekannt, das (in dieser Konstellation) niemals signed zum Einsatz kommen muss.
Warum will/soll/muß er das verhunzen?
Ein "undefined Behavior" ist in dieser Konstellation niemals gegeben.
Nach Deinem Einsatz in der Frage der Verarbeitung von signed Variablen, den ich mit großer Aufmerksamkeit verfolgt habe, ist das IMHO leider - und das mit höchstem Respekt vor deinem Sprung ins Haifischbecken - nicht 1:1 übertragbar.

Bedenke:
Der Kompiler sieht [] nur das, was notiert wurde.

Richtig!
Es wurde notiert, das keine Variable jemals ins negative gehen kann.

Gehst Du mit mir mit, wenn ich an dieser Stelle unterstelle, das in den Entwicklungsstufen von c++ versäumt wurde diese Konstellation in die "Optimierung" aufzunehmen?
[edit]
Möglicherweise gibt es dazu eine Umsetzung.
Dann wäre es KEIN Versäumnis in der Entwicklung, sondern in der Verwendung.
Das entzieht sich aber meiner Kenntnis...
[/quote]

Ein "undefined Behavior" ist in dieser Konstellation niemals gegeben.

Ach das ist doch einfach zu belegen, dass dieses eben doch auftritt!
Ich sach nur -3136 !
Der unschlagbare Beweis.

Du schwafelst!
Mach du mal.....

combie:
Nein, das reicht dann nicht.
...

Zur Vollständigkeit antworte ich. Ich betrachte immer soweit möglich den gesamten Thread. Daraus geht hervor das man für die Berechnung für Sonnenauf- und untergang kein signed benötigt. Negative Uhrzeiten habe ich noch keine gesehen. Wenn der TO den Thread verfolgt, sollte er daraufkommen alle seine Variablen auf unsigend long umzustellen und mit UL zu rechnen. Mehr gibts dazu nicht zu sagen.

Undefined behaviour heisst, dass der Compiler naturlich vorzeichenbehaftete Variable negativ werden lassen darf, wenn sie überlaufen, wie leicht zu beobachten, aber auch sonstwas anderes zulässig wäre.

int ist leicht zu tippen, jedesintsteht erstmal imVerdacht, dass der Verfasser sich nichts dabei gedacht hat.

Wir hatten doch letztens hier erst einen Thread, bei dem durch einen signed-Überlauf beim print völlig falsche Zahlen angezeigt wurden.

Gruß Tommy

michael_x:
Undefined behaviour heisst, dass der Compiler naturlich vorzeichenbehaftete Variable negativ werden lassen darf, wenn sie überlaufen, wie leicht zu beobachten, aber auch sonstwas anderes zulässig wäre.

Genau!
Er dürfte auch bei Trump anrufen oder/und Ostern und Weihnachten auf einen Tag legen.
Bei einem UB ist im Prinzip das ganze Programm defekt.

Wenn der TO den Thread verfolgt, sollte er daraufkommen alle seine Variablen auf unsigend long umzustellen und mit UL zu rechnen. Mehr gibts dazu nicht zu sagen.

Gerne!
Wenn unsigned das richtige, ist, dann gerne.
Ist nicht meine Entscheidung.....

Wir hatten doch letztens hier erst einen Thread, bei dem durch einen signed-Überlauf beim print völlig falsche Zahlen angezeigt wurden.

Ja!
Darum ist mir das ja auch noch so präsent.