Tag 14 – Letzte Farbe anzeigen

Foren Adventskalender Tag 14 – Letzte Farbe anzeigen

Ansicht von 5 Beiträgen - 1 bis 5 (von insgesamt 5)
  • Autor
    Beiträge
  • #865
    Klaus
    Teilnehmer

    Hallo zusammen,

    ich hab mal wieder etwas gebastelt und bis dabei gleich noch auf einen Fehler im Programm gestoßen.
    Meine Version zeigt nun die zuletzt gewählte Farbe im Colorpicker an.

    Dabei kamen immer wieder Zeichen zum Browser, die ich gar nicht im Quellcode habe. Dann habe ich festgestellt, dass im PROGMEM noch mehr Zeichen stehen, als man sieht. Deshalb darf die Schleife nicht
    for (int i = 0; i <= sizeof(site); i++)
    sondern
    for (int i = 0; i < sizeof(site)-1; i++)
    heißen, da 2 Zeichen zu viel aus dem Speicher gelesen werden. Eines wäre mir ja noch klar, wenn es nur das Nullbyte wäre. Aber warum 2? Kennt jemand den Grund dafür?

    #868
    Raabinator
    Mitglied

    Also, bei mir hängen drei Nullen dran (siehe Bild)

    • Die erste ist die Null im String, die mit /0 erzeugt wird (ist unnötig)
    • Die zweite Null ist die, die der Compiler automatisch an die Zeichenkette anhängt (site ist eins Größer als Zeichen angegeben sind)
    • Die dritte Null ist das was zufällig als nächstes im Programmspeicher kommt. Leider gibt die Arduino-IDE kein .map-File aus. Dort könnte man nachsehen, was als nächstes kommt.

    Um das komplette Array zu senden (inkl. der automatischen Ende-Null) sollte die Schleife so aussehen:
    for (int i = 0; i < sizeof(site); i++)

    Da wir aber eine Zeichenkette senden könnten wir auch die Null als Ende verwenden, dann so:

    int i = 0;
    while (meinArray[i] != '\0')
    {
      // ... mach was mit dem Zeichen ...
      i++;
    }
    

    Das wird aber unübersichtlich, da wir das Zeichen erst mit der Funktion pgm_read_byte_near aus dem Flash lesen müssen.

    Im Sketch des Autors wird der String durch das <= um ein Zeichen überlesen. Richtig wäre <. Damit wird auch die Ende-Null gesendet, die der Browser aber nicht braucht. Daher ganz richtig mit < sizeof(site)-1.

    • Diese Antwort wurde geändert vor 8 Jahren, 9 Monaten von Raabinator.
    Attachments:
    #872
    Klaus
    Teilnehmer

    OK, die ersten beiden leuchten mir ja jetzt ein. Aber warum sendet er dann noch ein drittes Byte zu viel?
    Das mit < sizeof(site) leuchtet ja auch ein, wenn man mal drüber nachdenkt. Man fängt bei 0 an. Die Größe fängt natürlich bei 1 an. Deshalb muss man ja 1 früher aufhören. Aber wie kommt es dann zustande, dass er trotzdem 1 übers Ende raus liest?
    Btw, bei mir liest er anscheinend nur 2 Bytes zu viel, was anhand der Erklärung automatisch \0 dran hängen und Größe fängt bei 0 an, auch logisch ist.
    Ich müsste mal den Sniffer anwerfen, um zu sehen, was er genau sendet. Oder ob das dritte Byte bei mir nur nicht zu sehen ist.

    #879
    Raabinator
    Mitglied

    Hallo Klaus

    Das kann man mit Wireshark gut beobachten (http://www.wireshark.org).

    sizeof() gibt die Größe des Array zurück. Die Indizierung des ersten Elementes beginnt bei 0, das letzte Element ist damit also sizeof()-1.
    Um alle Elemente zu indizieren müsste die Schleife bis <= sizeof()-1 oder gleichbedeutend < sizeof() laufen. Dies beinhaltet dann die 0 in der Zeichenkette und die automatische 0, die auch in die Größe mit eingerechnet ist.
    Mit <= sizeof() wird nochmal ein Byte mehr gelesen (durch das =), nämlich das array[sizeof(array)]-Byte. Da an dieser Stelle im Speicher zufällig eine 0 steht -> die dritte 0.

    • Diese Antwort wurde geändert vor 8 Jahren, 9 Monaten von Raabinator.
    • Diese Antwort wurde geändert vor 8 Jahren, 9 Monaten von Raabinator.
    • Diese Antwort wurde geändert vor 8 Jahren, 9 Monaten von Raabinator.
    #883
    Klaus
    Teilnehmer

    Das ist mir schon klar, hatte ich ja oben auch geschrieben. Aber bei meinen Versuchen hatte er noch ein drittes Byte zu viel. Allerdings gestern war das nicht so. Keine Ahnung, was da noch los war. Funktioniert aber inzwischen.

Ansicht von 5 Beiträgen - 1 bis 5 (von insgesamt 5)
  • Du musst angemeldet sein, um auf dieses Thema antworten zu können.