mikrocontroller.net

Forum: Compiler & IDEs Overflow bei pointer in structure


Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich will in einem Structure die letzten 7 Mittelwerte der jeweiligen 
Sensoren auslesen und den höchsten Wert erhalten. Jedoch liefert unten 
angeführtes Beispiel immer die falschen Werte. Wie muss ich den COde 
ändern, damit er funktioniert? Kann man ihn mittels Pointer auch etwas 
effizienter machen? (kenn mich da noch nicht so gut aus)

Grüße Hans

typedef struct {
        uint8_t param;
  uint16_t Mittelwerte[30];    //Minutenmittelwerte
}sensor;

sensor sensoren[12];
uint8_t index;

void Evaluation(void)
{
    uint8_t i,j, ptr*;
    uint8_t highVal;

    for(i = 0; i < 12; i++)
    {
        for(j=0;j<8;j++)
        {
             if(sensoren[i].Mittelwert[index-j]>highVal)
                  highVal=sensoren[i].Mittelwert[index-j];
        }
    }

  vPutnLCD(highval);
}

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
highval muss am Anfang auf den kleinstmöglichen Wert initialisiert
werden.

for(j=0;j<8;j++) berücksicht die letzten 8, nicht die letzten 7
Mittelwerte.

Wo kommt der Wert für index her?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> highval muss am Anfang auf den kleinstmöglichen Wert initialisiert
> werden.

... also 0, da die Mittelwerte unsigned sind.

Wenn die Mittelwerte 16 Bits breit sind, sollte dies auch highVal
sein.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe,

aber es hapert immer noch irgendwo. Mit Hilfe von "index" werden die 
alten Werte in einer anderen Funktion  überschrieben. Anschließend wird 
der index dort auch um 1 erhöht. So, hab mal ausgebessert:
typedef struct {
        uint8_t param;
        uint16_t Mittelwerte[30];    //Minutenmittelwerte
}sensor;

sensor sensoren[12];
uint8_t index;

void Evaluation(void)
{
    uint8_t i,j, ptr*;
    uint16_t highVal=0;

    for(i = 0; i < 12; i++)
    {
        for(j=0;j<7;j++)
        {
             if(sensoren[i].Mittelwert[index-j]>highVal)
                  highVal=sensoren[i].Mittelwert[index-j];
        }
    }

  vPutnLCD(highval);
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:
> Danke für die Hilfe,
>
> aber es hapert immer noch irgendwo.

Was heist das genau?

In deiner Funktion ist ansonsten so nichts mehr zu sehen.
Solange index einen Wert groesser/gleich 6 hat und
die Werte auch richtig im Array abgelegt sind, muss das
funktionieren.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch die Funktion zum Aktualisieren der Messwerte. (Wird jede Sek. 
aufgerufen)
void Refresh(void)
{
     uint16_t values[12]   
     getMeasurements(values);

     for(i = 0; i < 12; i++)
          sensoren[i].Mittelwert[index]=values[i];         
    
    if(index>=29)
       index=0;
    else
       index++;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:
>     if(index>=29)
>        index=0;


Ööhm.
Wenn index den Wert 0 hat, was ergibt dann index - j.
Dieser Ausdruck kommt in deiner Ermittlungsfunktion vor
und j nimmt innerhalb der Schleife Werte zwischen 0 und 6
an.
Wenn also index gleich 0 ist und j schon auf den Wert 6
vorgerückt ist, dann wird 0 - 6 zu -6. Und ein Array
Element mit dem Index -6 wirst du in keinem Array finden.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, danke!

Wenn ich einen Pointer auf die Mittelwerte setze und dann den Pointer 
andauernd inkrementiere, läuft dieser dann im Kreis (springt nach dem 
letzten wieder zum Ersten), oder zeigt er dann ins Nirvana?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:
> Ah, danke!
>
> Wenn ich einen Pointer auf die Mittelwerte setze und dann den Pointer
> andauernd inkrementiere, läuft dieser dann im Kreis (springt nach dem
> letzten wieder zum Ersten),

Nein.
Warum sollte er?

> oder zeigt er dann ins Nirvana?

Jep. Aber vergiss Pointer. Die bringen dich hier auch nicht
weiter.

Du musst deine Aufgabenstellung neu durchdenken. Vor allen
Dingen was du machen willst wenn weniger als 7 Mittelwerte
vorhanden sind und du aber den größten Mittelwert von 7
auf Biegen und Brechen bestimmen willst. Das kann dich
dann zur Lösung für dein jetziges Problem führen.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So? oder gehts noch einfacher?
void Evaluation(void)
{
    uint8_t i,j, ptr*;
    uint16_t highVal=0;

    for(i = 0; i < 12; i++)
    {
        for(j=0;j<7;j++)
        {
             if(index>j)
             {
                 if(sensoren[i].Mittelwert[index-j-1]>highVal)
                     highVal=sensoren[i].Mittelwert[index-j];
             }
             else
             {
                  if(sensoren[i].Mittelwert[29+index-j]>highVal)
                      highVal=sensoren[i].Mittelwert[index-j];
             }
        }
    }

  vPutnLCD(highval);
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:
> So? oder gehts noch einfacher?

Was heist einfacher.
Erst mal sollte es richtig sein :-)

Vergleichst du
>                  if(sensoren[i].Mittelwert[index-j-1]>highVal)
                                  hier:      *********
>                      highVal=sensoren[i].Mittelwert[index-j];
                                  mit:                *******
>              }
>              else
>              {
>                   if(sensoren[i].Mittelwert[29+index-j]>highVal)
            und nochmal                hier:  **********

>                       highVal=sensoren[i].Mittelwert[index-j];
                                       mit:            *******

Das wird wohl nichts werden, wenn du ein ganz anderes Element
zum vergleich benutzt, als das von dem dann die Zuweisung
ausgeht.

Was lernen wir daraus?
Kommt eine 'komplexe' Berechnung mehrmals in einem Codestück
vor, dann lohnt es sich immer, dafür eine Variable abzustellen
und die Berechnung zuerst mal nur einmal zu machen und das Ergebnis
in dieser Variablen zuwischenzuspeichern. In Folge wird dann anstelle
der Berechnung die Variable benutzt.

Was lernen wir noch daraus?
Das Code bei dem allesineinerWurschtgeschriebenwird nicht gerade
die Übersichtlichkeit fördert. Ein paar Leerzeichen an strategischen
Stellen positioniert können den Unterschied ausmachen zwischen
einem Code der fehlerhaft ist und einem Code bei dem einem
die Fehler nur so in die Augen springen. Ein paar Leerzeichen
hie und da dauern weder länger zum tippen noch bekommt man
Ausschlag davon.
void Evaluation()
{
    uint8_t  i, j;
    uint16_t highVal=0;
    uint8_t  testIndex;

    for( i = 0; i < 12; i++ )
    {
        for( j = 0; j < 7; j++ )
        {
            testIndex = index - j;
            if( index < j )
                testIndex += 30;
  
            if( sensoren[ i ].Mittelwert[ testIndex ] > highVal )
                highVal = sensoren[ i ].Mittelwert[ testIndex ];
        }
    }

    vPutnLCD( highval );
}

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke sehr für die Tipps und Ratschläge ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.