Verkette Liste

Gast #1354727
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
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.
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.
Persönliche Seite
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.
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.
Gast
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.
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.