Forum: Compiler & IDEs Peinliche Frage zu C-Grundlagen


von Lars (Gast)


Lesenswert?

Hallo alle zusammen!

Habe eine etwas peinliche Frage zu C.
Habe programmieren mit C# gelernt. Da kann ich eine Klasse mit meinen 
Methoden definieren und diese beliebig oft initiieren.
Wenn ich also eine Klasse MyBuffer habe, mit den Mehtoden Add, Read, 
Remove, ... und diese als TX und RX brauche, dann lege ich einmal
1
MyBuffer rx = new MyBuffer();
2
und
3
MyBuffer tx = new MyBuffer();
 an.
Zugreifen kann ich dann z.B. mit
1
rx.Add(rx_byte)

Wie mache ich das jetzt in C, wenn ich einen TX und einen RX Buffer habe 
und ein C-File mit meinen Methoden?!?

Danke für die Hilfe.

Gruß
Lars

von Walter (Gast)


Lesenswert?

ich nehme an dass du wirklich C meinst und nicht C++

die Daten musst du als struct anlegen, die Methoden als Funktionen denen 
du eine  Zeiger auf diese structs übergibst

von mano_wee (Gast)


Lesenswert?

Ringpuffer könnte das sein was Du sucht: FIFO

von MaWin (Gast)


Lesenswert?

> Wenn ich also eine Klasse MyBuffer habe,
> mit den Mehtoden Add, Read, Remove

> Wie mache ich das jetzt in C

Na ja, wenn du in C eine Implementation eines
MyBuffer hast, mit add, read, remove,
dann machst du das praktisch genau so.

MyBuffer rx = newbuffer();
add(rx,rx_byte);

Aber du hast so eine Implementation nicht :-)

Du musst es halt so machen, wie es in deiner
Umgebung möglich ist, und falls du (weil es
ein mickriger uC ist) keine brauchbare
Implementaion eines MyBuffer findest,
musst du ihn dir selber schreiben.

#define BUFSIZ 512
char buffer[BUFSIZ];
int inpos=0;
int outpos=0;
void add(char ch) { buffer[inpos=(inpos+1)%BUFSIZ]; }
char read(void) { return buffer[outpos=(outpos+1)%BUFSIZ]; }
int full(void) { return (inpos+1)%BUFSIZ==outpos; }
int empty(void) { return inpos==outpos; }

Das täte aich vielen C+ Programmen gut, dann würden sie nicht
so viel Ballast durch eierlegende Wollmilchsäure rumtragen.

Allerdings wäre es dann anders als meinen obiger Code
wenigstens getestet :-)

von Lars (Gast)


Lesenswert?

Hallo!

Ok, jetzt stehe ich nur noch mit einem Bein auf dem Schlauch.

Wenn ich jetzt also einen RX und TX Buffer brauche muss ich den Code 
wirklich zweimal machen und in ein eigenes C File speichern. Bzw. zwei 
Puffer anlegen und den Methoden irgendwie den richtigen Puffer 
übergeben!?

Gruß
Lars

von Walter (Gast)


Lesenswert?

Walter schrieb:
> die Daten musst du als struct anlegen, die Methoden als Funktionen denen
> du einen Zeiger auf diese structs übergibst

von Lars (Gast)


Lesenswert?

Ja, mein ich doch!

Ich habe mein C-File mit den Funktion Add, Read, ....
Die Funktionen haben als Übergabeparameter z.B.
1
void Add(Buffer* buffer, char value)
Dann ein h-File, indem mein Puffer-Struct definiert und mit
1
extern
 auf meine Funktionen verwiesen ist.
Das h-File füge ich dann bei den c-Files ein, wo ich es brauche.
Lege dann dort meine Puffer mit der Struct an
1
Buffer rx = new Buffer();
 und wenn ich dann ein Byte hinzufügen will mache ich
1
Add(&rx, <wert>);
!?

Gruß
Lars

von 900ss (900ss)


Lesenswert?

Hab MaWins Code mal modifiziert: ist auch ungetestet :-)
1
#define BUFSIZ 512
2
typedef struct buff_s
3
{
4
  char buffer[BUFSIZ];
5
  int inpos=0;
6
  int outpos=0;
7
} buff_t;
8
9
// 3 Instanzen von buff_t (Daten)
10
buff_t buffer1, buffer2, buffer3;
11
12
// hier die Functionen
13
void add(buff_t *b, char ch) { b->buffer[b->inpos=(b->inpos+1)%BUFSIZ]; }
14
char read(buff_t *b) { return b->buffer[b->outpos=(b->outpos+1)%BUFSIZ]; }
15
int full(buff_t *b) { return (b->inpos+1)%BUFSIZ==b->outpos; }
16
int empty(buff_t *b) { return b->inpos==b->outpos; }
17
18
// Aufruf für einen Instanz z.B.:
19
20
add( &buffer1, 'a' );

Edit: ah du hast es ja scheinbar auch schon selber so ähnlich gemacht.

von Lars (Gast)


Lesenswert?

Und wo definiere ich jetzt am Besten was!?

Wenn ich zwei C-Files habe, indem die zwei Schnittstellen abgehandelt 
werden (Daten in RX-Puffer schreiben, TX-Puffer lesen), entsprechend 
zwei C-File, indem die jeweiligen Daten analysiert werden (Daten aus dem 
RX-Puffer lesen, TX-Puffer schreiben),  und ein C-File für den Buffer 
mit meinen Add-, Read- ... Funktionen!?

Denn es müssen sich ja immer einmal die Schnittstelle + Datenanalyse den 
gleichen Puffer verwenden.

von Karl H. (kbuchegg)


Lesenswert?

Lars schrieb:
> Und wo definiere ich jetzt am Besten was!?

Du hast es immer noch nicht.

Da du schreibst, dass du in Objektorientierter Programmierung firm bist:

Das hier

buff_t buffer1, buffer2, buffer3;

sind 3 'Objekte' vom Typ buff_t

Das hier
void add(buff_t *b, char ch) { b->buffer[b->inpos=(b->inpos+1)%BUFSIZ]; 
}
char read(buff_t *b) { return b->buffer[b->outpos=(b->outpos+1)%BUFSIZ]; 
}
int full(buff_t *b) { return (b->inpos+1)%BUFSIZ==b->outpos; }
int empty(buff_t *b) { return b->inpos==b->outpos; }

sind die 'Member-Funktionen' der 'Klasse'

Wenn du eine 'Member-Funktion' aufrufst, dann gibst du der Funktion 
einen Pointer auf 'das Objekt' mit, damit die 'Member-Funktion' auf 
diesem Objekt operieren kann.

> Wenn ich zwei C-Files habe, indem die zwei Schnittstellen abgehandelt
> werden (Daten in RX-Puffer schreiben, TX-Puffer lesen), entsprechend
> zwei C-File, indem die jeweiligen Daten analysiert werden (Daten aus dem
> RX-Puffer lesen, TX-Puffer schreiben),  und ein C-File für den Buffer
> mit meinen Add-, Read- ... Funktionen!?

Das kommt jetzt auf den genauen Aufbau an (ISR, nicht ISR).

Aber du kannst zb die beiden Buffer als globale Variablen machen und die 
einzelnen Funktionen (Schnittstelle + Datenanalyse) greifen auf den 
jeweils richtigen Buffer zu und benutzen die Funktionen aus der 
Buffer-Lib zur Manipulation der Buffer.

Übertreib aber nicht. Aufteilen von Funktionalitäten in Files nach 
Themenkreisen geordnet ist zwar gut. Wenn man es aber zu weit treibt, 
wird es nur unübersichtlich.
zb kann man eventuell Schnittstellencode + einen Teil der Datenanalyse 
durchaus in ein File zusammenfassen, dessen Aufgabe es ist irgendwelche 
"Datensätze" von einer Schnittstelle zu holen. "Datensätze' ist schon 
ein etwas höheres Konzept als einfach nur ein Bytestrom, wie er von der 
Schnittstelle kommt.
Die ganze Bufferverwaltung, die dazu notwendig ist, findet sich dann nur 
in dieser 1 Datei.

von Peter D. (peda)


Lesenswert?

Will man die FIFO mit den Interrupts verwenden, kommen noch verschiedene 
Probleme hinzu (Interruptfreigabe, volatile, Atomizität).

Hier ein fertiges Beispiel, was all dies beachtet:

Beitrag "AVR-GCC: UART mit FIFO"


Peter

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.