Forum: Mikrocontroller und Digitale Elektronik Verkette Liste


von Rennreh (Gast)


Lesenswert?

Die lIsteenstruktur
1
struct LEDVEKTORENLISTE{
2
  struct LEDVEKTORENLISTE *next;
3
  struct LEDVEKTORENLISTE *ring_next;
4
  BYTE *vektor;
5
}*ledvektorenliste_start,*ledvektorenliste_ende;

Die Funtkion, an welcher das nächste Listenelement hinzugefügt wird.
1
void add_vektor(BYTE*vektor) {
2
  struct VEKTORENLISTE  *ptr = ledvektorenliste_ende;
3
  
4
  
5
  if(ptr==NULL) {
6
    ptr  = malloc(sizeof(struct VEKTORENLISTE));
7
    ptr->vektor      = vektor;
8
    vektorenliste_start  = ptr;
9
    ptr->next      = NULL;
10
    ptr->ring_next    = ptr;
11
  }else{
12
    ptr->next  = malloc(sizeof(struct VEKTORENLISTE));
13
    ptr->ring_next    = ptr->next;
14
    ptr          = ptr->next;
15
    ptr->vektor      = vektor;
16
    ptr->next      = NULL;
17
    ptr->ring_next    = ledvektorenliste_start;
18
  }
19
}

Der Compilier mag die erste Zeil emit dem Malloc nicht...
1
ptr  = malloc(sizeof(struct VEKTORENLISTE));
error: invalid application of 'sizeof' to incomplete type 'struct 
VEKTORENLISTE'


Ich bin mir da sehr sicher das der Quellcode so funktionieren sollte, 
ebenfalls sollte der Ausdruck
1
ptr  = malloc(sizeof(*ptr));
 Funktionieren. Ich hatte vorher mit MSVC programmiert nun nutze ich AVR 
Studio mit avrgcc. Liegt es am GCC compiler ?
Wieso kann der Compiler die Größe des Typs "struct LEDVEKTORENLISTE" 
erkennen ?

mfg

von Klaus W. (mfgkw)


Lesenswert?

was jetzt? VEKTORENLISTE oder LEDVEKTORENLIST?

Und wieso groß geschrieben?

Und vor malloc() fehlt der cast.

Und überhaupt!

von Karl H. (kbuchegg)


Lesenswert?

Rennreh schrieb:

> Der Compilier mag die erste Zeil emit dem Malloc nicht...
>
1
ptr  = malloc(sizeof(struct VEKTORENLISTE));
> error: invalid application of 'sizeof' to incomplete type 'struct
> VEKTORENLISTE'

Logo.
deine Struktur heißt LEDVEKTORENLISTE und nicht VEKTORENLISTE


PS: reserviere Namen mit nur Großbuchstaben ausschliesslich für Makros. 
Das ist die übliche Konvention.
Es spricht nichts dagegen, wenn du die Struktur LedVektorenListe nennst. 
Ist doch viel leichter zu lesen als so ein Schwall Grossbuchstaben, in 
dem man sich erst einmal die Wortanfänge optisch suchen muss.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:

> Und vor malloc() fehlt der cast.

Vorsicht.
In C ist der keine gute Idee.

Der cast ist nur dann angebracht, wenn derselbe Code sowohl in C als 
auch in C++ benutzbar sein soll.

von Karl H. (kbuchegg)


Lesenswert?

Noch ein Hinweis:

Wenn du in die Debug-Phase kommst (und das wirst du, du hast da ziemlich 
viele Fehler eingebaut :-), dann male dir die Datenstruktur am Papier 
auf und steppe im Papier deine Operation durch, indem du am Papier 
Pointer einzeichnest bzw. ausradierst.

von Rennreh (Gast)


Lesenswert?

Ja stimmt vielen dank :)

nach den vielen änderungen funktioniert es :)

mfg

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Tipp zu strukturen, ich machs immer mit typedef:
1
typedef struct foo_tt
2
{
3
  unsigned char c;
4
  unsigned int i;
5
  struct foo_tt *next;
6
  struct foo_tt *prev;
7
} foo_t;
8
9
foo_t foo;
10
11
foo_t *foo2 = (foo *) malloc (10 * sizeof(foo));

name_t kennzeichnet hier immer den typedef, und name_tt den namen der 
struktur, da man den ja in einer verketteten Liste in der struktur 
selbst braucht.

Da man häufig eine Variable benötigt, die sich aus der Struktur ableitet 
(also gleicher Name), kommt man hier nicht in komplikationen, man sieht 
sogar auf den ersten Blick die eindeutige Zuordnung.

Und,
GROSSBUCHSTABEN sind idR. für #defines "reserviert".
variablen schreibt man iR. klein,
Funktionen mit grossem Anfangsbuchstaben,

gemischteWoerterInVariablen und
GemischteWörterInFunktionsNamen schreibt man in camelCase bzw. 
CamelCase.


---
> }*ledvektorenliste_start,*ledvektorenliste_ende;


schöner ist es, die mit einem typedef dann "irgendwo" (an sinnvoller 
stelle) zu deklarieren als im struct. Ist auch besser lesbar.


VG,
/th.

von Daniel R. (zerrome)


Lesenswert?

Eben und sizeof() braucht ne Variable und keinen Typ...

von Random .. (thorstendb) Benutzerseite


Lesenswert?

whoops ...
1
foo_t *foo2 = (foo_t *) malloc (10 * sizeof(foo_t));

mal wieder zu schnell getippt und edit zeit vorbei :-)

Warum kann man hier eigentlich nur so kurz bearbeiten?

von (prx) A. K. (prx)


Lesenswert?

Daniel Platte schrieb:

> Eben und sizeof() braucht ne Variable und keinen Typ...

Geht beides.

von Stefan E. (sternst)


Lesenswert?

Daniel Platte schrieb:
> Eben und sizeof() braucht ne Variable und keinen Typ...

Sorry, aber das ist schlicht Unsinn.

von Karl H. (kbuchegg)


Lesenswert?

Die Idee, in das einzelne Strukturelement einen Ring-Pointer einzubauen 
würde ich mir noch einmal überlegen.
* Der Pointer muss bei allen weiteren Operationen korrekt
  nachgezogen werden
* Der Pointer braucht Platz. Wenn schon, dann würde ich diesen Speicher
  in eine doppelte Verkettung investieren. Das vereinfacht das Löschen
  aus der Liste enorm.
* Die Funktionalität 'Liste zu einem Ring' schliessen, ist mit einer
  kleinen Hilfsfunktion bei moderatem zusätzlichen Rechenaufwand unter
  Verwendung des Startzeigers leicht zu implementieren:
1
LedVektorenListe* NextLed( LedVektorenListe* pNow )
2
{
3
  if( !pNow )      // just to be sure
4
    return NULL;
5
6
  if( pNow->next == NULL )
7
    return ledvektorenliste_start;
8
9
  return pNow->Next;
10
}
11
12
13
void foo( LedVektorenListe* pLoop )
14
{
15
  LedVektorenListe* pStartedAt = pLoop;
16
17
  do {
18
    // mach was mit pLoop
19
20
    pLoop = NextLed( pLoop );
21
  } while( pLoop != pStartedAt )
22
}

* Es spricht auch nichts dagegen, die Liste grundsätzlich immer als
  Ring zu führen. Ob ich das Ende der Liste erkenne, indem ich den
  Next Pointer mit NULL vergleiche, oder ob ich ihn mit dem Start-
  Pointer vergleichen muss, ist gehupft wie gesprungen.

von Daniel R. (zerrome)


Lesenswert?

@ A. K. (prx)
@ Stefan Ernst (sternst)

Stimmt, geht beides bei sizeof. Ist ja ganz schön schlau das sizeof...

von Rennreh (Gast)


Lesenswert?

Vielen Danke für eure tips und Hilfe.

@ Karl heinz Buchegger
[ocde]
* Es spricht auch nichts dagegen, die Liste grundsätzlich immer als
  Ring zu führen. Ob ich das Ende der Liste erkenne, indem ich den
  Next Pointer mit NULL vergleiche, oder ob ich ihn mit dem Start-
  Pointer vergleichen muss, ist gehupft wie gesprungen.
[/code]
Ja das ist wahr, bei 1kb sram sollte ich nicht so herumschlampen ^^
1
Wenn du in die Debug-Phase kommst (und das wirst du, du hast da ziemlich
2
viele Fehler eingebaut :-), dann male dir die Datenstruktur am Papier
3
auf und steppe im Papier deine Operation durch, indem du am Papier
4
Pointer einzeichnest bzw. ausradierst.

Ist es im Kontroller eigentlich wirklich notwendig allokierten Speicher 
mit malloc wieder freizugeben ?
Die notwendigkeit würde doch nur dann bestehen wenn ein Betriebsystem 
die Speicherverwaltung betreibt. Da auf meinem Atmega8 kein 
Betriebsystem läuft aber malloc serwohl weis wo speicher frei ist, frage 
ich mich gerade wie malloc auf dem kontroller eigentlich arbeitet.

von Klaus W. (mfgkw)


Lesenswert?

Es ist nicht zwingend notwendig, weder mit noch ohne Betriebssystem.
Nur: wenn du nicht wieder freigibst, aber irgendwann wieder allokieren
willst, ist irgendwann natürlich der Speicher alle.

Deshalb:

- Speicher, der während der gesamten Laufzeit benötigt wird: einmal 
allokieren, allokiert lassen.

- Speicher, den man mal braucht und irgendwann nicht mehr: wieder 
freigeben.

Das hat mit einem Betrübsystem nichts zu tun.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.