Frage bzgl. Verarbeitung einer Konstantendeklaration

Gast #7309760
Lesenswert?

Moin,

ich habe dieser Tage ein einfaches Thermostat gebaut mit einem Atmega88 und nem DS18B20. Das Thermostat hat eine Hysterese damit das Aggregat nicht zu oft anspringen muss. Als Parameter habe ich eine Konstante deklariert und einen Wert zugewiesen:

1
const uint32_t hysterese = (15 * 60 * 1000);  //Hysterese in ms

Beim Trockentest ging noch alles, da habe ich den Wert auf 10000 gesetzt, aber bei Verwendung obiger Zeile kam offenbar ein Wert raus, der nicht 900000 Betrug, da nie geschalten wurde. Ich benutze als IDE Visual Studio Code mit Platformio und dem Arduino Framework. Für Konstanten habe ich sonst immer Makros bzw. einfache Präprozessoranweisungen genutzt, aber ich dachte mir wenn man eine Konstante deklariert, dann weiß man wenigstens genau, was die für einen Typ hat, das ist am Ende transparenter und sicherer.

Meine Frage ist jetzt, wieso hat die Zuweisung so nicht funktioniert? Ich würde das gerne verstehen.

Gast #7309792
Lesenswert?

Der Compiler rechnet mit /int/, wenn man ihm bei numerischen Konstanten nichts anderes mitteilt. Auf Deinem AVR-Arduino ist /int/ ein 16-Bit-Datentyp.

Ändere Deine Initialisierung mal zu

1
const uint32_t hysterese = (15 * 60 * 1000L);  //Hysterese in ms

(Das Suffix L weist den Compiler an, mit /long/ zu rechnen. Analog gibt es auch das Suffix UL, das hat /unsigned long/ zur Folge).

Gast #7309984
Lesenswert?

DerEinzigeBernd schrieb:

Der Compiler rechnet mit int, wenn man ihm bei numerischen Konstanten nichts anderes mitteilt. Auf Deinem AVR-Arduino ist int ein 16-Bit-Datentyp.

Ändere Deine Initialisierung mal zu const uint32_t hysterese = (15 * 60 * 1000L); //Hysterese in ms

(Das Suffix L weist den Compiler an, mit long zu rechnen. Analog gibt es auch das Suffix UL, das hat unsigned long zur Folge).

Ah, ok. Also damit hab ich nicht gerechnet. Klar dass ein int beim Atmega 16-bit hat, aber ich ging davon aus, dass der Compiler das ohnehin zur Compilezeit berechnet und dabei, entsprechend der CPU Architektur des PCs, mit 32-bit rechnet. Alles klar, wieder was gelernt.

Gast #7310163
Lesenswert?

Yves E. schrieb:

aber ich ging davon aus, dass der Compiler das ohnehin zur Compilezeit berechnet und dabei, entsprechend der CPU Architektur des PCs, mit 32-bit rechnet.

Warum sollte der Compiler die Architektur des PC (heute üblicherweise 64-bit) berücksichtigen, wenn doch für ein ganz anderes Target, hier AVR, compiliert wird? Wenn Du etwas von Sprache X nach Sprache Y übersetzen sollst, spielt es für Dich doch auch keine Rolle, in welchem Land du dich befindest.

#7310191
Lesenswert?

Yves E. schrieb:

Moin,

1
const uint32_t hysterese = (15 * 60 * 1000);  //Hysterese in ms

Ich benutze als IDE Visual Studio Code mit Platformio und dem Arduino Framework.

Weil Du Arduino benutzt, benutz Du also C++ ...

Für Konstanten habe ich sonst immer Makros bzw. einfache Präprozessoranweisungen genutzt, aber ich dachte mir wenn man eine Konstante deklariert, dann weiß man wenigstens genau, was die für einen Typ hat, das ist am Ende transparenter und sicherer.

CPP-Macros kannst Du bei C++ immer vermeiden (weil sie Mist sind).

Mache

1
constexpr uint32_t hysterese = (15 * 60 * 1000);  //Hysterese in ms

draus, und Du bekommst auch einen Fehler. Und schalte in Zukunft Deine Warnungen ein (mindestens -Wall -Wextra ...).

Meine Frage ist jetzt, wieso hat die Zuweisung so nicht funktioniert?

Es ist keine Zuweisung! Den Unterschied zwischen Zuweisung und Initialisierung ist etwas, was man ganz am Anfang des Lernens von C++ verstehen sollte / muss!

Gast #7310280
Lesenswert?

Alles klar, danke für die zahlreichen Antworten.

W.S. schrieb:

Yves E. schrieb:

//Hysterese in ms

Mal eine ganz andere Frage: Wie kommst du auf eine Hysterese in Zeiteinheiten? Das Ganze soll ja wohl ein Thermostat werden, also wäre da eine Hysterese in Temperatureinheiten angesagt.

W.S.

Weil sich diese Hysterese auf die Schalthäufigkeit bezieht und nicht auf die Temperatur. Das System, das gekühlt werden soll ist recht träge, da spielt es keine Rolle, wenn höchstens alle 15 Min. etwas am Schaltzustand geändert werden kann. Die Temperaturabweichungen sind überschaubar und das Aggregat wird so nicht sinnlos strapaziert.

Kaj schrieb:

Warum sollte der Compiler die Architektur des PC (heute üblicherweise 64-bit) berücksichtigen, wenn doch für ein ganz anderes Target, hier AVR, compiliert wird? Wenn Du etwas von Sprache X nach Sprache Y übersetzen sollst, spielt es für Dich doch auch keine Rolle, in welchem Land du dich befindest.

Schon klar, aber Compiler optimieren ja auch ne Menge Dinge weg, von daher ging ich davon aus, da es sich hier um eine Konstante handelt, würde der Compiler aus dieser Initialisierung einfach eine Zuweisung machen. So dass am Ende einfach:

1
const uint32_t hysterese = 900000;

daraus wird. Wie ja nun hinreichend geklärt wurde, war das eine falsche Annahme.

#7311033
Lesenswert?

Markus F. schrieb:

... und wenn Du die Compiler-Warnungen eingeschaltet hättest (etwas, was man immer machen sollte, -Wall, mindestens), hätte dir der Compiler hier eine Warnung bezüglich des Integer-Overflows ausgeworfen.

Es geht um Arduino. Das unterdrückt defaultmäßig alle Warnungen, weil sowas für die Arduino-Zielgruppe als zu kompliziert angesehen wird…

Yves E. schrieb:

Klar dass ein int beim Atmega 16-bit hat, aber ich ging davon aus, dass der Compiler das ohnehin zur Compilezeit berechnet und dabei, entsprechend der CPU Architektur des PCs, mit 32-bit rechnet.

Es wird zur Compilezeit berechnet, allerdings nach genau den selben Regeln wie eine Berechnung zur Laufzeit. Man will ja nicht, dass ein und die selbe Berechnung zur Compilezeit ein anderes Ergebnis hat als wenn sie zur Laufzeit durchgeführt worden wäre.

Gast #7311554
Lesenswert?

Yves E. schrieb:

Schon klar, aber Compiler optimieren ja auch ne Menge Dinge weg, von daher ging ich davon aus, da es sich hier um eine Konstante handelt, würde der Compiler aus dieser Initialisierung einfach eine Zuweisung machen. So dass am Ende einfach: const uint32_t hysterese = 900000;

daraus wird.

Das ist nach wie vor keine Zuweisung, sondern eine Initialisierung.

Korrekterweise solltest Du

1
const uint32_t hysterese = 900000UL;

schreiben, denn 900000 ist kein int, und Du willst eine unsigned-Variable damit initialisieren.

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