Unterschied bit schieben oder multiplizieren - UNO spinnt

Die folgenden Berechnungen sollten doch das gleiche Ergebnis liefern:

      unsigned long secsSince1900, secsSince1900_test;
      // convert four bytes starting at location 40 to a long integer

      secsSince1900_test =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900_test |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900_test |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900_test |= (unsigned long)packetBuffer[43];

      secsSince1900  = packetBuffer[40] * 256UL * 256UL * 256UL;
      secsSince1900 += packetBuffer[41] * 256UL * 256UL;
      secsSince1900 += packetBuffer[42] * 256UL;
      secsSince1900 += packetBuffer[43];
      Serial.print("secsSince1900 "); Serial.print(secsSince1900);
Serial.print("    secsSince1900-test "); Serial.print(secsSince1900_test);
Serial.print("    diff: "); Serial.println(secsSince1900_test-secsSince1900);

Mal stimmt es, mal nicht. Die secsSince1900 sin immer richtig, die secsSince1900_test hat manchmal eine Differenz von 519931648 zu secsSince1900. Hab schon mit einem anderen Uno getestet, gleicher Fehler.

Sketch kommt noch

Kann es sein, dass du Geister siehst.....

das kann schon sein. Also bist du auch der Meinung, dass das dasselbe Ergebnis bringen müsste?

Und ich weiss, der fehlerbehaftete Teil ist in dem nicht gezeigten Teil des Sketches.

hat manchmal eine Differenz von 519931648

immer genau die gleiche differenz?

ja, soweit ich gesehen habe, immer gleich. Ich bin aber der Sache auf der Spur.
In packetBuffer wird die Udp Antwort einer NTP Abfrage eingelesen. Die vier Bytes sind die relevanten für die Zeit (Sek. ab Jahr 1900). Ich habe im Sketch einen char buffer anstatt einen byte buffer verwendet.

Jetzt scheint es stabil in beiden Varianten zu funktionieren.

ElEspanol:
Und ich weiss, der fehlerbehaftete Teil ist in dem nicht gezeigten Teil des Sketches.

Hallo,

Du hattes es bereits selbst geahnt und Combie hätte mal wieder recht gehabt :wink:

Gruß Heinz

Daher war ja meine Frage, ob die beiden Routinen ABSOLUT gleichwertig sind. Sind sie also nicht, kommt auf den Datentyp an.

Hi

Ein signed sind immer noch 'eine Reihe Bits' - wenn Du Diese verschiebst, werden die Bits verschoben.
Wenn Du aber mit signed rechnest, dann werden die Vorzeichen-Bits eben zu den Vorzeichen - meine Erklärung zu dem Phänomen, Welches aus dem Snipped aber eben nicht ableitbar ist, da der Datentyp des Array dort nicht erwähnt wird.

So eben auch das von Dir ja selber schon angesprochene: Der Fehler (oder der Grund Dessen) liegt im geheimen Teil :slight_smile:
Schön, daß Das auch den Profis hier passiert!

MfG

ElEspanol:
Daher war ja meine Frage, ob die beiden Routinen ABSOLUT gleichwertig sind. Sind sie also nicht, kommt auf den Datentyp an.

Es kommt immer auf den Datentyp an.
Das ist mit das wichtigste Kapitel!
Ich rate zu angespannter Aufmerksamkeit, bei der Wahl der Datentypen.

Wenn du char genommen hast, kommt es sogar auf die konkrete Maschine an.
Denn char kann signed sein, oder auch unsigned.
Der C++ Standard legt das nicht fest.
Auch nicht, wie viel Bit ein char hat.
OK. mindestens 8 ... aber es dürfen auch mal 36 Bit pro char sein.

Welches aus dem Snipped aber eben nicht ableitbar ist, da der Datentyp des Array dort nicht erwähnt wird.

Och...

// convert four bytes starting at location 40 to a long integer

Das ist eine recht übliche Falle.
Kommentar und Code widersprechen sich.
Denn byte ist unsigned, dem ElEspanol sein char allerdings offensichtlich signed.
Da liegt der Klemmer.

Aber anderer Prozessor/Kompiler, neues Glück!

postmaster-ino:
Profis

Wie kommst du denn da drauf? Eher fortgeschrittener, interessierter Hobbyist mit analytischen Fähigkeiten trifft es eher :slight_smile: