www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik eventqueue in c schreiben


Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich wollte ienen fifo also eine Queue in c schreiben, damit ich 
eintreffende Events in der eingetroffenen reihenfolge bearbeiten kann, 
wenn ich dazu zeit habe. hierbei bekomme ich die queue einfach nicht 
hin. irgendwas stimmt da nicht mit den Pointern. meine getEvent und 
meine initialisierung funktionieren nicht richtig. der compiler meldet 
folgende fehler:
../EventQueue/evenQueue.c:48: error: expected expression before 'mainEventQueue'
../EventQueue/evenQueue.c: In function 'getEvent':
../EventQueue/evenQueue.c:65: error: 'event' undeclared (first use in this function)
../EventQueue/evenQueue.c:65: error: (Each undeclared identifier is reported only once
../EventQueue/evenQueue.c:65: error: for each function it appears in.)
../EventQueue/evenQueue.c:65: error: expected ';' before 'ret'
../EventQueue/evenQueue.c:66: error: 'eventQueue' undeclared (first use in this function)
../EventQueue/evenQueue.c:66: error: expected ';' before 'tmp'
../EventQueue/evenQueue.c:67: error: expected identifier or '(' before '=' token
../EventQueue/evenQueue.c:68: error: 'tmp' undeclared (first use in this function)
../EventQueue/evenQueue.c:69: error: 'ret' undeclared (first use in this function)

der code:
/**
 *
 *          Project:    Automatic WIFI Network
 *          Package:    EventQueue
 *
 *
 * File:          Test.c
 * Author:        Soenke Paschko
 * Maintainer:   Soenke Paschko
 *
 * Created on:   08. August 2009, 11:35
 *
 * Content:
 *
 *
 * Revision history:
 * 08.08.09 1. revision Paschko  -  First version
 */


  #include "../main.h"
  #include "events.h"
  #include "eventQueue.h"

   /**
   * Event struct
   */
  typedef struct event{
    char eventClass;
    char eventSource;
  };
  
  typedef struct eventQueue{
    struct event data;
    struct eventQueue *next;
  }mainEventQueue;

  int length;

  struct eventQueue * endOfQueue;


  /**
   * This function initializes the event queue
   */
  void initEventQueue(){
    length  = 0;
    endOfQueue = &mainEventQueue;
  }

  /**
   * This function adds an event to the event queue
   */
  void addEvent(struct event evt){
    length=length + 1;
    struct eventQueue  newElement = {evt, NULL};
    endOfQueue->next = &newElement;
  }

  /**
   * This function gets the event from the event queue
   */
  struct event getEvent(){
    length = length - 1;
    event ret = mainEventQueue->data;
    eventQueue tmp = mainEventQueue;
    mainEventQueue = mainEventQueue->next;
    free(tmp);  // free allocated memory
    return ret;
  }


Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach dir klar, dass mit
typedef struct eventQueue{
    struct event data;
    struct eventQueue *next;
  }mainEventQueue;
keine Variable vereinbart wird.

Autor: Naja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Typname wird hiermit
  typedef struct event{
    char eventClass;
    char eventSource;
  };

definiert?

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:
> Mach dir klar, dass mit
>
> typedef struct eventQueue{
>     struct event data;
>     struct eventQueue *next;
>   }mainEventQueue;
> 
> keine Variable vereinbart wird.

hm warum nicht? steht doch mainEventQueue dahinter. Iwe macht man das 
sonst?



Naja schrieb:
> Welcher Typname wird hiermit
>
>
>   typedef struct event{
>     char eventClass;
>     char eventSource;
>   };
> 
>
> definiert?

naja der typname ist event oder?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, eben nicht.

Mit
typedef struct eventQueue{
     struct event data;
     struct eventQueue *next;
}mainEventQueue;
definierst du:
1. ein Token: struct eventQueue und
2. einen Typen: mainEventQueue.

Du kannst damit dann Variablen deklarieren, etwa so:
1. struct eventQueue var1, var2, bla, blubb;
2. mainEventQueue varA, varB, x, y, z;

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Statt
 typedef struct event{
    char eventClass;
    char eventSource;
  };
  
  typedef struct eventQueue{
    struct event data;
    struct eventQueue *next;
  }mainEventQueue;

dies benutzen:
  struct event{
    char eventClass;
    char eventSource;
  };
  
  struct eventQueue{
    struct event data;
    struct eventQueue *next;
  };

  struct eventQueue mainEventQueue;

Dies
  void addEvent(struct event evt){
    length=length + 1;
    struct eventQueue  newElement = {evt, NULL};
    endOfQueue->next = &newElement;
  }

geht in die Hose. Nach Verlassen von addEvent ist newElement ungültig. 
Das einsame free() ohne passendes malloc() macht mich auch stutzig.

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum? ich verknüpfe es doch in meine liste??

das free gibt den speicherplatz wieder frei. alloziert wird der, wenn er 
der Funktion übergeben wird. aber du hast recht ich übergebe keinen 
pointer, nur eine kopie, deshalb geht das verlohren.

hier die neue Version:
/**
 *
 *          Project:    Automatic WIFI Network
 *          Package:    EventQueue
 *
 *
 * File:          Test.c
 * Author:        Soenke Paschko
 * Maintainer:   Soenke Paschko
 *
 * Created on:   08. August 2009, 11:35
 *
 * Content:
 *
 *
 * Revision history:
 * 08.08.09 1. revision Paschko  -  First version
 */

#ifndef EVENTQUEUE_H_
#define EVENTQUEUE_H_

   /**
   * Event structs
   */
  typedef struct{
    char eventClass;
    char eventSource;
  }event;

  typedef struct queue{
    event data;
    struct queue *next;
  }eventQueue;


  void initEventQueue();
  void addEvent(event * evt);
  event getEvent();

#endif /* EVENTQUEUE_H_ */

und der code:
/**
 *
 *          Project:    Automatic WIFI Network
 *          Package:    EventQueue
 *
 *
 * File:          Test.c
 * Author:        Soenke Paschko
 * Maintainer:   Soenke Paschko
 *
 * Created on:   08. August 2009, 11:35
 *
 * Content:
 *
 *
 * Revision history:
 * 08.08.09 1. revision Paschko  -  First version
 */


  #include "../main.h"
  #include "events.h"
  #include "eventQueue.h"




  int length;

  eventQueue * endOfQueue;     // Pointer to the end of the queue
  eventQueue * mainEventQueue;  // Pointer to the first Element of the queue


  /**
   * This function initializes the event queue
   */
  void initEventQueue(){
    length  = 0;
    endOfQueue = &mainEventQueue;
  }

  /**
   * This function adds an event to the event queue
   */
  void addEvent(event * evt){
    length=length + 1;
    eventQueue  newElement = {evt, NULL};
    endOfQueue->next = &newElement;
  }

  /**
   * This function gets the event from the event queue
   */
   event getEvent(){
    length = length - 1;
    event ret = mainEventQueue->data;
    eventQueue * tmp = mainEventQueue;
    mainEventQueue = mainEventQueue->next;
    free(tmp);  // free allocated memory
    return ret;
  }

Autor: Mark .. (mork)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem mit der ungültigen Variable besteht immer noch. In 'void 
addEvent' wird eine lokale Varible 'newElement' angelegt. Sobald die 
Funktion verlassen wird, existiert 'newElement' nicht mehr und der 
gespeicherte Pointer zeigt auf einen Speicherbereich mit zufälligem 
Inhalt. Damit die Variable auch dann gültig ist, wenn die Funktion 
verlassen wurde, muss sie auf dem Heap abgelegt werden. Und das macht 
macht man eben mit malloc. Siehe 
http://home.fhtw-berlin.de/~junghans/cref/FUNCTION...

Und noch was: 'endOfQueue = &mainEventQueue;' in 'void initEventQueue' 
ist sowohl semantisch als auch syntaktisch totaler Unsinn. 'endOfQueue' 
ist ebenso wie 'mainEventQueue' vom Typ 'eventQueue*' und deshalb kann 
man ihr auch keine Adresse von mainEventQueue zuweisen. Was Du machen 
willst, ist beide Zeiger auf NULL zu setzen, damit sie nicht auf einen 
zufälligen Bereich zeigen.

MfG Mark

Nachtrag: 'addEvent' hat noch einen kleinen Fehler, nämlich dass 
'endOfQueue' am Ende der Funktion nicht auf die Adresse des neuen 
Elements gesetzt wird. Zudem darf 'endOfQueue->next = &newElement;' so 
nicht stehen bleiben, sondern es muss zuerst geprüft werden, ob 
überhaupt ein letztes Element exisitiert (mit if(endOfQueue)). Erst dann 
kann man endOfQueue dereferenzieren.

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also muss ich das so machen?
  /**
   * This function adds an event to the event queue
   */
  void addEvent(event * evt){
    length=length + 1;
    eventQueue * newElement = (*char) malloc(3*8); 
    if(newElement != NULL){
      newElement = {evt, NULL};
      endOfQueue->next = &newElement;
    }
  }

nur da werden mir syntaxfehler gemeldet.

und das müsste dann so heisen?
  /**
   * This function initializes the event queue
   */
  void initEventQueue(){
    length  = 0;
    mainEventQueue = {NULL,NULL};
    endOfQueue = mainEventQueue;
  }


auch hier ist dann aber ein syntaxfehler bei mainEventQueue = 
{NULL,NULL};

was ist da falsch?

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

Bewertung
0 lesenswert
nicht lesenswert
Sönke Paschko schrieb:
> also muss ich das so machen?
>
>
>   /**
>    * This function adds an event to the event queue
>    */
>   void addEvent(event * evt){
>     length=length + 1;
>     eventQueue * newElement = (*char) malloc(3*8);
>     if(newElement != NULL){
>       newElement = {evt, NULL};
>       endOfQueue->next = &newElement;
>     }
>   }
> 
>
> nur da werden mir syntaxfehler gemeldet.

Welche?
Syntaxfehler haben einen Text. Manchmal ist der Text wenig hilfreich 
aber meistens führt er einen auf die Spur.

* benutze KEINEN cast in C um das Ergebnis von malloc zurechtzucasten!
  Wenn der C-Compiler einen Datentypfehler ankreidet, dann ist hier ein
  cast ausnahmsweise nicht das Mittel der Wahl.

* (*char) ist Kein Cast, sondern ein banaler Syntaxfehler. Es müsste
  (char*) heissen. Aber der Cast ist wie gesagt in C nicht notwendig
  und auch nicht gut.

* malloc(3*8)
  Benutze kein Wissen darüber, wie gross Datentypen sind, wenn du es
  nicht unbedingt musst. Lass den Compiler sich um die Details der
  Datentypgrößen kümmern! Auf anderen Maschinen als auf einem AVR
  wirst du nämlich dein blaues Wunder erleben, wenn du eine derartige
  struct so allokierst. Da kann es dann durchaus sein, dass ein
  Strukturelement 4 Bytes gross ist, obowhl du rechnerisch nur auf
  3 kommst -> der Compiler hat padding Bytes eingefügt.
  Lass den Compiler rechnen, der kann das besser und kennt die Details.

*   newElement = {evt, NULL};
  in welcher Sprache du hier auch immer programmierst, C ist es auf
  keinen Fall.


> was ist da falsch?

Grob gesagt: Falsch ist, dass du kein C-Buch benutzt um die Sprache zu 
lernen (und da spreche ich noch gar nicht über das halbe Dutzend 
logischer Fehler, die du in den 5 Zeilen Code eingebaut hast)

/**
  * This function adds an event to the event queue
  */
eventQueue * addEvent( event * evt )
{
  eventQueue * newElement = malloc( sizeof( eventQueue ) );
 
  if( newElement != NULL ) {
     newElement->data = evt;
     newElement->next = NULL;

     if( mainEventQueue == NULL )
       mainEventQueue = newElement;
     else
       endOfQueue->next = newElement;

     endOfQueue = newElement;

     length = length + 1;
  }

  return newElement;
}

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also laut einem onlinebuch kann man ein struct so initialisieren

struckttyp hallo = {1.eintrag,2.eintrag};

wie machst du das denn?

so?
  /**
   * This function initializes the event queue
   */
  void initEventQueue(){
    length  = 0;
    mainEventQueue->data = NULL;
    mainEventQueue->next = NULL;
    endOfQueue = mainEventQueue;
  }


gehts nämlich auch nicht.

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

Bewertung
0 lesenswert
nicht lesenswert
Sönke Paschko schrieb:
> also laut einem onlinebuch kann man ein struct so initialisieren
>
> struckttyp hallo = {1.eintrag,2.eintrag};
>

Eine Initialisierung ist keine Zuweisung (auch wenn sie so aussieht)
Initialisierung: Ein neues Objekt kommt zur Welt und bekommt Werte.
Aber die Zuweisung von Werten an ein bereits bestehendes Objekt ist 
keine Initialisierung!

Für Initialisierungen kann man in C Syntaxelemente benutzen, die für 
Zuweisungen nicht zur Verfügung stehen.

WIe ich schon sagte: Du brauchst ein Buch. Und zwar ein vernünftiges 
Buch (zb den K&R) und nicht irgendein windiges Online-Tutorial, in dem 
die Hälfte nicht drinnen steht.

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

Bewertung
0 lesenswert
nicht lesenswert
Sönke Paschko schrieb:

>
>
>   /**
>    * This function initializes the event queue
>    */
>   void initEventQueue(){
>     length  = 0;
>     mainEventQueue->data = NULL;
>     mainEventQueue->next = NULL;
>     endOfQueue = mainEventQueue;
>   }
> 
> 
>
> gehts nämlich auch nicht.

Logo geht das nicht (logisch gesehen). mainEventQueue ist ein Pointer! 
Worauf zeigt denn dieser Pointer ganz am Anfang?
Antwort: Irgendwo ins Nichts!
  /**
    * This function initializes the event queue
    */
  void initEventQueue(){
    length  = 0;
    mainEventQueue = NULL;
    endOfQueue = NULL;
 }

Zusammen mit der add Funktion, die ich dir oben geschrieben habe, 
funktioniert das dann perfekt. Bei ersten add wird das erste eventQueue 
Objekt erzeugt und mainEventQueue und endOfQueue darauf gesetzt.

Autor: Naja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste mal den Quelltext wie er jetzt aussieht.

"geht nicht" ist leider als Information nicht ausreichend. Woran siehst 
Du das es nicht geht?

Wenn man davon ausgeht das der Quellcode sich nicht wesentlich verändert 
hat, also immer noch
eventQueue * mainEventQueue;  // Pointer to the first Element of the queue

da steht, dann "geht" der Code deswegen nicht, weil noch kein Speicher 
für das worauf mainEventQueue zeigt, alloziiert ist. Ergo gibt es die 
Elemente data und next nicht.

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

Bewertung
0 lesenswert
nicht lesenswert
Und noch ein Tip:
starte deinen ersten Ausflug in die Welt der dynamischen Datenstrukturen 
NICHT auf einem AVR sondern auf einem PC. Du hast dort wesentlich 
bessere Debug-Möglichkeiten. Alleine die Tatsache, dass du dir deine 
Queue mittels
void print()
{
  eventQueue * pLoop = mainEventQueue;

  while( pLoop ) {
    printf( ....  was auch immer du für einen Event ausgeben kannst ... );
    pLoop = pLoop->next;
  }
}

eine simple View-Funktion machen kannst, die ziemlich zuverlässig Amok 
läuft, sobald auch nur der kleinste Hund in deiner Datenstruktur 
enthalten ist, ist die Vorarbeit auf einem PC wert. Nach jedem add 
oder delete die print Funktion aufrufen und nachsehen, ob das erwartete 
Ergebnis vorliegt.
Du wirst nämlich schnell merken, dass bei dynamischen Datenstrukturen 
jede Anweisung 100% korrekt sein muss, ansonsten geht etwas schief. Das 
gilt auch für die Reihenfolge von Anweisungen.
Das sieht zwar alles auf den ersten Blick korrekt aus, aber Fehler 
finden sich in dynamischen Strukturen immer erst >20 Schritte später. 
Das alte Prinzip, wonach ein Fehler im Debugger dort zu suchen ist, wo 
auch der Absturz passiert, gilt hier nicht mehr.

Wenn du deine Eventqueue auf dem PC korrekt laufen hast, lässt sich das 
alles 100% 1:1 auf den AVR übernehmen.

Und leg dir Papier und BLeistift bereit und zeichne die Operationen mit!
Für jeden Pointer malst du ein kleines Rechteck und wenn es sich dabei 
um eine benannte Variable handelt, dann schreibst du den Variablennamen 
darüber. Machst du einen malloc, dann malst du ein größeres Rechteck 
aufs Papier. Bei der Zuweisung des Pointers von malloc in eine Variable, 
malst du einen Pfeil von der 'Variablen' zum Rechteck. Genauso bei jeder 
anderen Zuweisung von Adressen an Pointer: Ein Pfeil wird eingezeichnet 
(Ausnahme: NULL wird einfach hineingeschrieben)


Das ist die Ausgangssituation:
Du hast 2 Variablen, beides Pointer
  mainEventQueue 
  +------------------+
  |                  |
  +------------------+

  endOfQueue
  +------------------+
  |                  |
  +------------------+

Jetzt gehen wir mal die add Funktion durch und zeichnen bei jedem 
Statement mit. Und zwar nur das, was auch tatsächlich im Quelltext 
steht!

Wir fangen bei der initFunktion an, die einfach nur die beiden Pointer 
Variablen auf NULL setzt
  mainEventQueue 
  +------------------+
  |   NULL           |
  +------------------+

  endOfQueue
  +------------------+
  |   NULL           |
  +------------------+

Die add-Funktion beginnt und bekommt einen Pointer auf einen Event in 
evt
  mainEventQueue 
  +------------------+
  |   NULL           |
  +------------------+

  endOfQueue
  +------------------+
  |   NULL           |
  +------------------+


  evt
  +-------------+        +-------------+
  |    o---------------->|             |
  +-------------+        |  Event      |
                         |             |
                         +-------------+
Die Funktion beginnt
  eventQueue * newElement = malloc( sizeof( eventQueue ) );

auf dem Papier bedeutet das, das ein neues Rechteck geboren wird, und es 
eine weitere Pointer Variable namens newElement gibt, die auf dieses 
Rechteck zeigt
  mainEventQueue 
  +------------------+
  |   NULL           |
  +------------------+

  endOfQueue
  +------------------+
  |   NULL           |
  +------------------+

  newElement
  +---------------+                   +------------+
  |       o-------------------------->| data:      |
  +---------------+                   | next:      |
                                      +------------+

  evt
  +-------------+        +-------------+
  |    o---------------->|             |
  +-------------+        |  Event      |
                         |             |
                         +-------------+
Beachte: Bei data bzw. next habe ich nichts eingetragen. Keinen Pfeil 
und auch nicht NULL. Denn genau das macht auch malloc, nämlich nichts. 
Was auch immer dort steht ist zufällig. Und zur Erinnerung: Du darfst 
auf dem Papier nur das machen, was auch dein Programm macht!

Weiter im Text
  if( newElement != NULL ) {

Such dir die Variable newElement in deiner Zeichnung. Steht da NULL 
drinnen oder nicht? Da geht ein Pfeil raus, newElement ist also nicht 
NULL. Also wird der then Teil vom if genommen
     newElement->data = evt;

rechte Seite der Zuweisung: evt. Von evt soll also der Wert genommen 
werden. Das läuft in der Zeichnung darauf hinaus, dass ein 2-ter Pfeil 
konstruiert wird, der dorthin zeigt, wo auch evt hinzeigt. Und wo soll 
dieser Pfeil beginnen? In newElement->data. Also: newElement aufsuchen. 
Dort muss ein Pfeil beginnen (daher im Quelltext auch ->). Dieser Pfeil 
endet in einem Rechteck und in diesem Rechteck muss es ein data Feld 
geben. Dort soll der neue Pfeil beginnen.
  mainEventQueue 
  +------------------+
  |   NULL           |
  +------------------+

  endOfQueue
  +------------------+
  |   NULL           |
  +------------------+

  newElement
  +---------------+                   +------------+
  |       o-------------------------->| data:  o--------+
  +---------------+                   | next:      |    |
                                      +------------+    |
                                                        |
                          +-----------------------------+
  evt                     v
  +-------------+        +-------------+
  |    o---------------->|             |
  +-------------+        |  Event      |
                         |             |
                         +-------------+
Überzeuge dich davon, dass der neu eingezeichnete Pfeil exakt dem 
entspricht, was durch
 newElement->data = evt;
gefordert war!

Weiter im Text
     newElement->next = NULL;
Das ist wieder einfach. newElement aufsuchen, dem Pfeil einmal folgen 
und im Rechteck bei next einen NULL Pointer eintragen
  mainEventQueue 
  +------------------+
  |   NULL           |
  +------------------+

  endOfQueue
  +------------------+
  |   NULL           |
  +------------------+

  newElement
  +---------------+                   +------------+
  |       o-------------------------->| data:  o--------+
  +---------------+                   | next: NULL |    |
                                      +------------+    |
                                                        |
                          +-----------------------------+
  evt                     v
  +-------------+        +-------------+
  |    o---------------->|             |
  +-------------+        |  Event      |
                         |             |
                         +-------------+
weiter
     if( mainEventQueue == NULL )
sieh dir meinEventQueue an. Steht da NULL drinnen?
Ja das tut es, also wird der then-Zweig genommen
   mainEventQueue = newElement;
Aha. Kennen wir schon. In mainEventQueue einen Pfeil installieren, der 
dorthin zeigt, wo auch newElement hinzeigt
  mainEventQueue 
  +------------------+
  |   o--------------------------------+
  +------------------+                 |
                                       |
  endOfQueue                           |
  +------------------+                 |
  |   NULL           |                 |
  +------------------+                 |
                                       |
  newElement                           v
  +---------------+                   +------------+
  |       o-------------------------->| data:  o--------+
  +---------------+                   | next: NULL |    |
                                      +------------+    |
                                                        |
                          +-----------------------------+
  evt                     v
  +-------------+        +-------------+
  |    o---------------->|             |
  +-------------+        |  Event      |
                         |             |
                         +-------------+
  endOfQueue = newElement;
Auch das ist wieder einfach
  mainEventQueue 
  +------------------+
  |   o--------------------------------+
  +------------------+                 |
                                       |
  endOfQueue                           |
  +------------------+                 |
  |   o-------------------------------+|
  +------------------+                ||
                                      ||
  newElement                          vv
  +---------------+                   +------------+
  |       o-------------------------->| data:  o--------+
  +---------------+                   | next: NULL |    |
                                      +------------+    |
                                                        |
                          +-----------------------------+
  evt                     v
  +-------------+        +-------------+
  |    o---------------->|             |
  +-------------+        |  Event      |
                         |             |
                         +-------------+
   length = length + 1;

OK. length habe ich bis jetzt ignoriert. Die Variable würde ich sowieso 
rauswerfen.

Damit ist die Funktion zu Ende und die Variablen evt und newElement als 
lokale Varibablen werden aufgelöst:
  mainEventQueue 
  +------------------+
  |   o--------------------------------+
  +------------------+                 |
                                       |
  endOfQueue                           |
  +------------------+                 |
  |   o-------------------------------+|
  +------------------+                ||
                                      ||
                                      vv
                                      +------------+
                                      | data:  o--------+
                                      | next: NULL |    |
                                      +------------+    |
                                                        |
                          +-----------------------------+
                          v
                         +-------------+
                         |             |
                         |  Event      |
                         |             |
                         +-------------+
Und? Das Ergebnis sieht richtig aus. Alle Pointer Variablen zeigen 
irgendwo hin oder sind NULL. Kein Pointer zeigt ins Nichts (Pfeil der an 
keinem Rechteck endet)

(Fortsetzung folgt)

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

Bewertung
0 lesenswert
nicht lesenswert
Jetzt machen wir einen weiteren Aufruf von add.

Wieder bekommt die Funktion einen Event in Form eines POinters in evt
  mainEventQueue
  +------------------+
  |   o--------------------------------+
  +------------------+                 |
                                       |
  endOfQueue                           |
  +------------------+                 |
  |   o-------------------------------+|
  +------------------+                ||
                                      ||
                                      vv
                                      +------------+
                                      | data:  o--------+
                                      | next: NULL |    |
                                      +------------+    |
                                                        |
                          +-----------------------------+
                          v
                         +-------------+
                         |             |
                         |  Event      |
                         |             |
                         +-------------+

  evt
  +-----------+                          +-----------+
  |   o--------------------------------->|           |
  +-----------+                          |  Event    |
                                         |           |
                                         +-----------+
Die Funktion beginnt
  eventQueue * newElement = malloc( sizeof( eventQueue )
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o--------------------------+|
  +------------------+           ||
                                 ||
                                 vv
                                 +------------+            +-----------+
                                 | data:  o--------+    +->| data:     |
                                 | next: NULL |    |    |  | next:     |
                                 +------------+    |    |  +-----------+
                                                   |    |
                          +------------------------+    |
                          v                             |
                         +-------------+                |
                         |             |                |
                         |  Event      |                |
                         |             |                |
                         +-------------+                |
                                                        |
                                                        |
  newElement                                            |
  +-------------+                                       |
  |   o-------------------------------------------------+
  +-------------+

  evt
  +-----------+                          +-----------+
  |   o--------------------------------->|           |
  +-----------+                          |  Event    |
                                         |           |
                                         +-----------+
  if( newElement != NULL ) {

newElement ist offensichtlich nut NULL (da geht ein Pfeil heraus)
    newElement->data = evt;
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o--------------------------+|
  +------------------+           ||
                                 ||
                                 vv
                                 +------------+            +-----------+
                                 | data:  o--------+    +->| data:  o----+
                                 | next: NULL |    |    |  | next:     | |
                                 +------------+    |    |  +-----------+ |
                                                   |    |                |
                          +------------------------+    |                |
                          v                             |                |
                         +-------------+                |                |
                         |             |                |                |
                         |  Event      |                |                |
                         |             |                |                |
                         +-------------+                |                |
                                                        |                |
                                                        |                |
  newElement                                            |                |
  +-------------+                                       |                |
  |   o-------------------------------------------------+                |
  +-------------+                                                        |
                                          +------------------------------+
  evt                                     v                              
  +-----------+                          +-----------+
  |   o--------------------------------->|           |
  +-----------+                          |  Event    |
                                         |           |
                                         +-----------+
  newElement->next = NULL;
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o--------------------------+|
  +------------------+           ||
                                 ||
                                 vv
                                 +------------+            +------------+
                                 | data:  o--------+    +->| data:  o----+
                                 | next: NULL |    |    |  | next: NULL ||
                                 +------------+    |    |  +------------+|
                                                   |    |                |
                          +------------------------+    |                |
                          v                             |                |
                         +-------------+                |                |
                         |             |                |                |
                         |  Event      |                |                |
                         |             |                |                |
                         +-------------+                |                |
                                                        |                |
                                                        |                |
  newElement                                            |                |
  +-------------+                                       |                |
  |   o-------------------------------------------------+                |
  +-------------+                                                        |
                                          +------------------------------+
  evt                                     v                              
  +-----------+                          +-----------+
  |   o--------------------------------->|           |
  +-----------+                          |  Event    |
                                         |           |
                                         +-----------+
   if( mainEventQueue == NULL )
Sieh dir die Variable mainEventQueue an. Ist sie NULL? Nein, da kommt 
ein Pfeil heraus. Also wird der else Zweig genommen
  endOfQueue->next = newElement;

Die Variable endOfQueue aufsuchen, dem Pfeil folgen (wegen dem -> im 
Quelltext) und im Rechteck an dem du landest bei next einen Pfeil 
eintragen, der dort endet, wo auch newElement endet:
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o--------------------------+|
  +------------------+           ||
                                 ||
                                 vv
                                 +------------+       +--->+------------+
                                 | data:  o--------+  | +->| data:  o----+
                                 | next:  o-----------+ |  | next: NULL ||
                                 +------------+    |    |  +------------+|
                                                   |    |                |
                          +------------------------+    |                |
                          v                             |                |
                         +-------------+                |                |
                         |             |                |                |
                         |  Event      |                |                |
                         |             |                |                |
                         +-------------+                |                |
                                                        |                |
                                                        |                |
  newElement                                            |                |
  +-------------+                                       |                |
  |   o-------------------------------------------------+                |
  +-------------+                                                        |
                                          +------------------------------+
  evt                                     v                              
  +-----------+                          +-----------+
  |   o--------------------------------->|           |
  +-----------+                          |  Event    |
                                         |           |
                                         +-----------+

Soweit so gut. Weiter:
   endOfQueue = newElement;

Das ist wieder einfach. Ein Pfeil der von endOfQueue ausgeht und dort 
endet wo auch der Pfeil in newElement endet:
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o---------------------------|------------------------+
  +------------------+            |                        |
                                  |                        |
                                  v                        v
                                 +------------+       +--->+------------+
                                 | data:  o--------+  | +->| data:  o----+
                                 | next:  o-----------+ |  | next: NULL ||
                                 +------------+    |    |  +------------+|
                                                   |    |                |
                          +------------------------+    |                |
                          v                             |                |
                         +-------------+                |                |
                         |             |                |                |
                         |  Event      |                |                |
                         |             |                |                |
                         +-------------+                |                |
                                                        |                |
                                                        |                |
  newElement                                            |                |
  +-------------+                                       |                |
  |   o-------------------------------------------------+                |
  +-------------+                                                        |
                                          +------------------------------+
  evt                                     v                              
  +-----------+                          +-----------+
  |   o--------------------------------->|           |
  +-----------+                          |  Event    |
                                         |           |
                                         +-----------+

Damit ist die Funktion wieder durch, die Argumente und lokalen Variablen 
werden eliminiert:
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o---------------------------|------------------------+
  +------------------+            |                        |
                                  |                        |
                                  v                        v
                                 +------------+       +--->+------------+
                                 | data:  o--------+  |    | data:  o----+
                                 | next:  o-----------+    | next: NULL ||
                                 +------------+    |       +------------+|
                                                   |                     |
                          +------------------------+                     |
                          v                                              |
                         +-------------+                                 |
                         |             |                                 |
                         |  Event      |                                 |
                         |             |                                 |
                         +-------------+                                 |
                                                                         |
                                                                         |
                                          +------------------------------+
                                          v                              
                                         +-----------+
                                         |           |
                                         |  Event    |
                                         |           |
                                         +-----------+

Zurücklehnen und die Datenstruktur studieren.
Sieht gut aus. Beginnend mit mainEventQueue startet eine Kette von 
EventQueue Objekten, die über den next-Pointer sauber miteinander 
verknüpft sind. Das letzte EventQueue Objekt hat ein NULL im next 
Pointer. Jedes EventQueue Objekt zeigt auch auf einen Event in seinem 
data Feld und endOfQueue zeigt auch tatsächlich auf das letzte 
EventQueue Objekt in der Kette.

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

Bewertung
0 lesenswert
nicht lesenswert
Bleibt nur noch darüber zu sprechen, was bei der Umkehrung (free) am 
Papier passieren soll.
Wenn dein Programm einen free ausführt, dann radierst du das Rechteck 
aus auf das der angegebene Pfeil zeigt, inklusive aller Pfeile die aus 
dem Rechteck herausführen. Und das wars dann schon. Insbesondere 
radierst du keinen Pfeil weg, der zu diesem Rechteck geführt hat! Nur 
weil man eine struct mittels free löscht, wird deswegen noch lange kein 
Pointer der dorthin zeigt umgesetzt. Der Pointer zeigt nach wie vor auf 
die gleiche Stelle im Speicher und die Tatsache, dass du dann am Papier 
einen Pfeil hast, der im Nichts endet, soll dich darauf aufmerksam 
machen, dass dann eine Operation wie Pointer->next einfach nicht mehr 
machbar ist. Der Pfeil zeigt ins Leere, dort gibt es kein next Feld!

Gehen wir als Beispiel deine etwas umgewandelte get Funktion durch
  struct event * getEvent(){
    length = length - 1;
    event * ret = mainEventQueue->data;
    eventQueue * tmp = mainEventQueue;
    mainEventQueue = mainEventQueue->next;
    free(tmp);  // free allocated memory
    return ret;
  }

Die Funktion beginnt mit dieser Datenstruktur
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o---------------------------|------------------------+
  +------------------+            |                        |
                                  |                        |
                                  v                        v
                                 +------------+       +--->+------------+
                                 | data:  o--------+  |    | data:  o----+
                                 | next:  o-----------+    | next: NULL ||
                                 +------------+    |       +------------+|
                                                   |                     |
                          +------------------------+                     |
                          v                                              |
                         +-------------+                                 |
                         |             |                                 |
                         |  Event      |                                 |
                         |             |                                 |
                         +-------------+                                 |
                                                                         |
                                                                         |
                                          +------------------------------+
                                          v                              
                                         +-----------+
                                         |           |
                                         |  Event    |
                                         |           |
                                         +-----------+

Erste Anweisung
      event * ret = mainEventQueue->data;

Also: neue Variable erzeugen und auf meinEventQueue->data zeigen lassen
(mainEventQueue aufsuchen, dem -> folgen, data Feld im Rechteck 
aufsuchen)
  mainEventQueue
  +------------------+
  |   o---------------------------+
  +------------------+            |
                                  |
  endOfQueue                      |
  +------------------+            |
  |   o---------------------------|------------------------+
  +------------------+            |                        |
                                  |                        |
                                  v                        v
                                 +------------+       +--->+------------+
                                 | data:  o--------+  |    | data:  o----+
                                 | next:  o-----------+    | next: NULL ||
                                 +------------+    |       +------------+|
                                                   |                     |
                          +------------------------+                     |
                          v                                              |
                         +-------------+                                 |
                         |             |                                 |
                         |  Event      |                                 |
                         |             |                                 |
                        >+-------------+                                 |
                        |                                                |
                        |                                                |
                        |                 +------------------------------+
                        |                 v                              
                        |                +-----------+
                        |                |           |
                        |                |  Event    |
                        |                |           |
                        |                +-----------+
                        |
   ret                  |
   +------+             |
   |  o-----------------+
   +------+
      eventQueue * tmp = mainEventQueue;
  mainEventQueue                        tmp
  +------------------+                  +----------+
  |   o---------------------------+ +--------o     |
  +------------------+            | |   +----------+
                                  | |
  endOfQueue                      | |
  +------------------+            | |
  |   o---------------------------|-|----------------------+
  +------------------+            | |                      |
                                  | |                      |
                                  v v                      v
                                 +------------+       +--->+------------+
                                 | data:  o--------+  |    | data:  o----+
                                 | next:  o-----------+    | next: NULL ||
                                 +------------+    |       +------------+|
                                                   |                     |
                          +------------------------+                     |
                          v                                              |
                         +-------------+                                 |
                         |             |                                 |
                         |  Event      |                                 |
                         |             |                                 |
                        >+-------------+                                 |
                        |                                                |
                        |                                                |
                        |                 +------------------------------+
                        |                 v                              
                        |                +-----------+
                        |                |           |
                        |                |  Event    |
                        |                |           |
                        |                +-----------+
                        |
   ret                  |
   +------+             |
   |  o-----------------+
   +------+
   mainEventQueue = mainEventQueue->next;
mainEventQueue soll dorthin zeigen, wo mainEventQueue->next bisher 
hingezeigt hat
  mainEventQueue                        tmp
  +------------------+                  +----------+
  |   o---------------------------+ +--------o     |
  +------------------+            | |   +----------+
                                  | |
  endOfQueue                      +-------------------------+
  +------------------+              |                       |
  |   o-----------------------------|----------------------+|
  +------------------+              |                      ||
                                    |                      ||
                                    v                      vv
                                 +------------+       +--->+------------+
                                 | data:  o--------+  |    | data:  o----+
                                 | next:  o-----------+    | next: NULL ||
                                 +------------+    |       +------------+|
                                                   |                     |
                          +------------------------+                     |
                          v                                              |
                         +-------------+                                 |
                         |             |                                 |
                         |  Event      |                                 |
                         |             |                                 |
                        >+-------------+                                 |
                        |                                                |
                        |                                                |
                        |                 +------------------------------+
                        |                 v                              
                        |                +-----------+
                        |                |           |
                        |                |  Event    |
                        |                |           |
                        |                +-----------+
                        |
   ret                  |
   +------+             |
   |  o-----------------+
   +------+
  free(tmp);  // free allocated memory
Das Rechteck, auf das tmp zeigt, wird ausradiert
  mainEventQueue                        tmp
  +------------------+                  +----------+
  |   o---------------------------+ +--------o     |
  +------------------+            | |   +----------+
                                  | |
  endOfQueue                      +-------------------------+
  +------------------+              |                       |
  |   o-----------------------------|----------------------+|
  +------------------+              |                      ||
                                    |                      ||
                                    v                      vv
                                                           +------------+
                                                           | data:  o----+
                                                           | next: NULL ||
                                                           +------------+|
                                                                         |
                         +-------------+                                 |
                         |             |                                 |
                         |  Event      |                                 |
                         |             |                                 |
                        >+-------------+                                 |
                        |                                                |
                        |                                                |
                        |                 +------------------------------+
                        |                 v                              
                        |                +-----------+
                        |                |           |
                        |                |  Event    |
                        |                |           |
                        |                +-----------+
                        |
   ret                  |
   +------+             |
   |  o-----------------+
   +------+
  return ret;
Der Aufrufer kriegt also einen Pointer zurück. ret zeigt tatsächlich 
noch auf etwas und dieses Etwas ist sogar sinnvoll, nämlich die 
Event-Beschreibung des ersten Events.

Damit ist die Funktion wieder zu Ende und die lokalen Variablen werden 
aufgelöst
  mainEventQueue                        
  +------------------+                   
  |   o---------------------------+  
  +------------------+            | 
                                  | 
  endOfQueue                      +-------------------------+
  +------------------+                                      |
  |   o----------------------------------------------------+|
  +------------------+                                     ||
                                                           ||
                                                           vv
                                                           +------------+
                                                           | data:  o----+
                                                           | next: NULL ||
                                                           +------------+|
                                                                         |
                         +-------------+                                 |
                         |             |                                 |
                         |  Event      |                                 |
                         |             |                                 |
                         +-------------+                                 |
                                                                         |
                                                                         |
                                          +------------------------------+
                                          v                              
                                         +-----------+
                                         |           |
                                         |  Event    |
                                         |           |
                                         +-----------+

Sieht nach wie vor gut aus. Der main Pointer zeigt auf den Anfang der 
verbleibenden EventQueue Objekte, auch endOfQueue ist noch gültig. Das 
einsame Event Objekt da mitten drinn, ist auch kein Problem, ein Pointer 
darauf wurde ja dem Aufrufer zurückgegeben, er ist auch dafür zuständig, 
dass es zerstört wird. Genauso wie er dafür zuständig war, dass es beim 
Aufruf von add schon erzeugt war.

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen dank für die lange erklährung, das war wirklich gut. ich hoffe 
ich hab alles verstanden. werde mich morgen mal an die Umsetzung machen.

Autor: Aahh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Debugger - nie gehoert ?
Simulation - Nie gehoert ?

So wird das eh nichts.

Autor: soeni- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was meinst du damit?

ich habe kein Emulator (VIEL ZU VIEL GELD)
Mit nem Simulator lassen sich nur sehr schwehr interrupts erzeugen, das 
ist zu kompliziert und warum?

Debugger (JTAG ICE) hab ich auch nicht.

Wozu auch, man kann doch über LEDs debuggen. oder man nimmt halt rs232 
und hat nen printfdebugging

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.