Forum: Mikrocontroller und Digitale Elektronik Pointer Übergabeparameter eine Funktion übergeben


von Max (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem in C. Ich möchte quasi einer Init Funktion 
den Pointer von der List übergeben. Wie müsste der Übergabeparameter 
lauten?

[test.h]
extern sElement List[10];

void Test_Init(....); <= ?????

[main.c]
sElement List[10];

//Aufruf Init Funktion
Test_Init(...);

von Oliver S. (oliverso)


Lesenswert?

sElement

Oliver

von Nop (Gast)


Lesenswert?

Max schrieb:

> ich habe folgendes Problem in C. Ich möchte quasi einer Init Funktion
> den Pointer von der List übergeben. Wie müsste der Übergabeparameter
> lauten?

sElement *

>
> [test.h]
> extern sElement List[10];

Das kann weg, wenn Du das sowieso sauber als Parameter übergibst.

> void Test_Init(....); <= ?????

void Test_Init(Element *list_ptr, size_t len);

> [main.c]
> sElement List[10];

Das kann dann auch static sein.

> //Aufruf Init Funktion
> Test_Init(List, sizeof(List) / sizeof(List[0]));

List muß dabei als Array-Deklaration sichtbar sein, was hier aber der 
Fall ist.

von Nop (Gast)


Lesenswert?

Nop schrieb:

> void Test_Init(Element *list_ptr, size_t len);

void Test_Init(sElement *list_ptr, size_t len);

von Da Baby (Gast)


Lesenswert?

Oliver S. schrieb:
> sElement
>
> Oliver

void Test_Init(sElement* List);

Test_Init(List) oder Test_Init(&List[0])

In der Funktion kannst du dann sowas machen:

//i-tes Element aus Liste Array
sElement t = *(List+i);

oder:
sElement t = List[i]

von Oliver S. (oliverso)


Lesenswert?

Da Baby schrieb:
> Oliver S. schrieb:
>> sElement
>>
>> Oliver
>
> void Test_Init(sElement* List);

Jep, war 'ne freudsche Fehlleistung von mir.

Oliver

von Max (Gast)


Lesenswert?

typedef struct Element
{
  uint8_t* Name;
  eTimerType Type;
  eTimerState State;
  uint32_t ValueMillSec;
}sElement;

von Nop (Gast)


Lesenswert?

Da Baby schrieb:

> void Test_Init(sElement* List);

Geht, sollte man aber nicht so machen, weil die Funktion dann nicht 
weiß, wie groß das Array ist. Idiomatisches C wäre wie in meinem 
Vorschlag ein Pointer auf das erste Element und als zweiten Parameter 
die Anzahl der Elemente.

von Émile (Gast)


Lesenswert?

Nop schrieb:
> Geht, sollte man aber nicht so machen, weil die Funktion dann nicht
> weiß, wie groß das Array ist.

Geht schon, wenn vereinbart wird, daß das Array nullterminiert ist, d.h. 
mit einem Element endet, in dem alle Elemente Null sind.

Diese Vorgehensweise ist bei Strings in C sehr verbreitet, da ist ein 
Element halt keine Struktur, sondern nur ein char, aber funktional 
läuft das aufs gleiche raus.

von Nop (Gast)


Lesenswert?

Émile schrieb:

> Geht schon, wenn vereinbart wird, daß das Array nullterminiert ist, d.h.
> mit einem Element endet, in dem alle Elemente Null sind.

Zum Lesen geht das - aber beim Schreiben, was eine Init-Funktion ja tun 
soll, müßte man dann vor dem Aufruf alle Elemente bis auf das letzte mit 
einem ungültigen Wert ungleich null vorinitialisieren. Das ist recht 
umständlich.

von Max (Gast)


Lesenswert?

Vielen Dank für eure Hilfe.

Ich bin etwas unschlüssig wie das alles umsetzen soll. Ich habe quasi 
eine Instanz in der 5 Elemente enthalten sind. Es stellt sich die Frage 
soll ich eine Init Funktion erstellen die die Elemente initiallieren 
soll, ja oder nein?

von DerEinzigeBernd (Gast)


Lesenswert?

Max schrieb:
> Ich habe quasi
> eine Instanz in der 5 Elemente enthalten sind. Es stellt sich die Frage
> soll ich eine Init Funktion erstellen die die Elemente initiallieren
> soll, ja oder nein?

Womit werden die Elemente initialisiert? Mit konstanten Werten? Dann 
brauchst Du keine Init-Funktion, sondern kannst Dein Array gleich beim 
Definiteren auch initialisieren:
1
typedef struct Element
2
{
3
  uint8_t* Name;
4
  eTimerType Type;
5
  eTimerState State;
6
  uint32_t ValueMillSec;
7
}sElement;
8
9
10
sElement Array[] =
11
{
12
  { "Horst", type1, state1, 34 },
13
  { "Detlef", type0, state7, 123 },
14
 ... etc.
15
};

(angenommen, daß "type1" etc. zu den vermutlich-enums passen).

von A. S. (Gast)


Lesenswert?

Max schrieb:
> Es stellt sich die Frage soll ich eine Init Funktion erstellen die die
> Elemente initiallieren soll, ja oder nein?

Das hängt von mehreren fragen ab:

Was weiß die initfunktion, was du zur compilezeit nicht weißt? Woher 
kommt der Speicher? Wer macht welche Annahmen über die Liste? Wer 
garantiert, dass init vor Verwendung aufgerufen wird bzw. alle mit "0" 
klarkommen.

Die Fragen sind vermutlich schwierig, dann beschreib lieber, was Du 
machen willst.

von Max (Gast)


Lesenswert?

Da es sich um einen Mikrocontroller handelt werde ich nichts dynam7sch 
machen. Ich möchte die hardwarenahen Timerfunktionen in eine eigene 
TimerLib verwenden. Diese TimerLib stellt dan die Funktionen nach außen 
dar. Es sollen zunächst 6 Instanzen (6 Timer) erzeugt werden. Mir stellt 
sich die Frage wie man sowas richtig umsetzen kann und wie die 
Initialisierung aussehen könnte. Die Instanzen sollen auch wo anders 
verwendet werden wie zum Beispiel in der uart, watchdog usw.

von A. S. (Gast)


Lesenswert?

Max schrieb:
> nichts dynam7sch machen

Max schrieb:
> Es sollen zunächst 6 Instanzen (6 Timer) erzeugt werden.

Wenn es eben geht, ist es einfacher/flexibler, wenn der Nutzer 
(aufrufer) den Speicherplatz bereitstellt.

Aber ohne Beispiel-Pseudocode oder ein wenig mehr Erklärung ist kaum 
erkennbar, was Du genau möchtest.

von A. S. (Gast)


Lesenswert?

A. S. schrieb:
> wenn der Nutzer (aufrufer) den Speicherplatz bereitstellt

... dann reicht meist ein Pointer in der Struktur für eine einfach 
verkettete, 0-terminierte Liste, falls eine Liste notwendig ist.

Schleifen zerfallen dann zu
1
for(p=startPtr;p;p=p->next) {...}

Es ist dann gleich, ob 3 oder 300 Timer genutzt werden.

Und Spar Dir gerne den Aufwand der doppelt-verketteten Liste, bis Du die 
einfache beherrschst. Der Performancegewinn ist in diesem Stadium 
vernachlässigbar.

von Peter D. (peda)


Lesenswert?

Max schrieb:
> Es sollen zunächst 6 Instanzen (6 Timer) erzeugt werden.

Dazu nimmt man typisch einen Scheduler, der von einem Timertick 
ausgeführt wird, d.h. man braucht nur einen Hardwaretimer.
Der Vorteil ist, die Liste muß nur so groß sein, wie maximal Timer 
gleichzeitig ausgeführt werden.

: Bearbeitet durch User
von Max (Gast)


Lesenswert?

Guten Morgen,

das mit einer verketten Liste habe ich mir auch überlegt. Ich brauche 
einen Timer für die UART, Watchdog usw. und auch für eventuell sonstige 
Aufgaben in der Applikation. Wenn ich das mit einer verketten Liste 
mache, dann muss ich zum Beispiel für die UART immer die Liste nach dem 
Timer für die UART suchen. Ich werde manuell die Liste erzeugen und dann 
jeweils zum Beispiel für die UARTT als Übergabeparameter einen Pointer 
auf das jeweilige Elment von der List übergeben.

von Max (Gast)


Lesenswert?

1
typedef struct List
2
{
3
  TimerElement  timerElement[MAX];
4
  TimerElement* z;                             
5
  int   entries;                
6
}List;
1
void Uart_Init(List* pList, eBaudrate baudrate);

Wenn ich dies so tue, woher weis die Uart welchen Timer in der Liste für 
ihn bestimmt ist? Da muss ich ja wieder in der Liste suchen.

von Klaus (feelfree)


Lesenswert?

Max schrieb:
> woher weis die Uart welchen Timer in der Liste für
> ihn bestimmt ist?

Warum sollte eine Funktion (hier Uart_Init) eine Liste mit Timern 
bekommen, wenn sie doch nur einen ganz bestimmten aus dieser Liste 
benötigt?
Das macht keinen Sinn.

von Max (Gast)


Lesenswert?

Ja stimmt eigentlich, Wie würdest du das lösen?

von Max (Gast)


Lesenswert?

Ich muss ja der UART den zuständige Timer als Übergabeparameter 
mitteilen.

von Klaus (feelfree)


Lesenswert?

Max schrieb:
> Ja stimmt eigentlich, Wie würdest du das lösen?

void Uart_Init(TimerElement *timer, eBaudrate baudrate);

von Max (Gast)


Lesenswert?

Ok. Und vorher muss ich aber trotzdem wissen welche EIntrag von der List 
für die Uart bestimmt ist.

von Klaus (feelfree)


Lesenswert?

Selbstverständlich.

von Peter D. (peda)


Lesenswert?

Max schrieb:
> Ich muss ja der UART den zuständige Timer als Übergabeparameter
> mitteilen.

Nö.
Du übergibst dem Scheduler nur die Ablaufzeit und den Callback. Der 
Scheduler legt dann beides auf einem freien Platz in der Liste ab.
Die Ablaufzeit wird dabei schon richtig in die belegten Einträge der 
Liste einsortiert. Der Timer muß also immer nur einen Eintrag 
runterzählen.

von A. S. (Gast)


Lesenswert?

Max schrieb:
> Ok. Und vorher muss ich aber trotzdem wissen welche EIntrag von der List
> für die Uart bestimmt ist.

Wofür brauchst Du denn eine Liste?

Im Uart legst Du den Timer
1
static struct sTimer TimerUart;

lokal an. Und arbeitest mit ihm. Init, Start, Stop, Test, ... was immer. 
Also z.B.
1
TimStart(&TimerUart);

WENN Du für irgendwas eine Liste brauchst (wofür auch immer), DANN 
mach die mit einer Pointer-verkettung
1
struct sTimer;
2
struct sTimer {
3
    struct sTimer *next;
4
    char *Name;
5
    ...
6
};
7
static FirstTimer = 0;
8
void TimerInit(struct sTimer *T, char *Name, ...)
9
{
10
    /* einketten des neuen Timers */
11
    T->next = FirstTimer;
12
    FirstTimer = T;
13
    ...
14
    T->Name = Name;
15
    ...
16
}

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.