Forum: PC-Programmierung [C] universelle Funktion mit void Zeiger


von B. S. (bestucki)


Lesenswert?

Hallo zusammen

Ich programmiere zwar auf einem uC, aber da dies eher eine allgemeine 
Programmierfrage ist, habe ich dieses Unterforum gewählt. Wenn falsch, 
bitte verschieben.

Ich habe mehrere Integerarrays mit verschiedenen Datentypen, die aber 
alle auf die gleiche Weise verarbeitet werden müssen. Ist es nun 
sinvoll, eine allgemeine Funktion zu schreiben, der ein void Zeiger 
übergeben wird, anstatt für jeden Datentyp eine eigene Funktion zu 
schreiben? Wie wird dies allgemein gehandhabt?


Hier ein Beispiel, wie ich mir den Funktionsprototyp in etwa vorstelle:
1
void foo(
2
  void * result,
3
  int resulttype,
4
  void * source,
5
  int sourcetype,
6
  int sourcesize);


Dass die Sache funktioniert weiss ich, habs selbst versucht. Die Frage 
ist nur, wie fehleranflällig das Ganze ist und ob es evt. bessere 
Lösungen gibt.

Der Sinn dahinter ist es, Speicherplatz zu sparen und nicht für jeden 
Datentyp eine Funktion mit identischem Code schreiben zu müssen.

von Florian P. (db1pf)


Lesenswert?

Hallo,

naja, es kommt darauf an was du mit den Daten machen möchtest. Problem 
ist, dass du mit (void*) nicht rechnen kannst. Also z.B.
1
void foo(void *in, void *out, int n)
2
{
3
  int i;
4
  for (i=0; i<n; i++)
5
    *out++ = (*in++) * (*in++);
6
}
wird nicht gehen, da der Compiler nicht weiß wie er die Zahl 
interpretieren muss. Du müsstest jetzt abhängig von deinem Parameter 
resulttype die Ein- und Ausgangsvariable casten und dann damit rechnen.
Ob sich der Aufwand lohnt hängt vom Umfang der Funktion ab...

Grüße,
Florian

von Oliver (Gast)


Lesenswert?

be stucki schrieb:
> Ich habe mehrere Integerarrays mit verschiedenen Datentypen

Hm, was denn nun? Alles Integers, oder verschiedene Datentypen?

Und da nirgends etwas über die Programiersprache steht, würde ich in C++ 
einfach eine Template-Funktion dafür schreiben ;)

Oliver

von Peter II (Gast)


Lesenswert?

be stucki schrieb:
> Dass die Sache funktioniert weiss ich, habs selbst versucht. Die Frage
> ist nur, wie fehleranflällig das Ganze ist und ob es evt. bessere
> Lösungen gibt.

kann ich mir nicht vorstellen.

wenn dein array aus uint8_t besteht, dann kannst du keinen array zugriff 
machen.

uint8_t x[10];

foo( x );

void foo( void* a ) {
   a[9] = 1;
};

wird einfach nicht funktionieren.

von FelixW (Gast)


Lesenswert?

Der Aufruf ist Fehleranfällig, da deine Typnummer immer zum 
tatsächlichen Typ passen muss.
Wenn deine Funktion funktioniert überlade sie mit Funktionen, die einen 
definierten Typ haben, damit sinkt die Chance später Fehler zu machen 
und der Codebedarf bleibt gering.
1
void foo(
2
  void * result,
3
  int resulttype,
4
  void * source,
5
  int sourcetype,
6
  int sourcesize);
7
8
void foo(int *result, long *source, int sourcesize) {
9
 foo( result, NUM_TYPE_INT, source , NUM_TYPE_LONG, sourcesize);
10
}

von B. S. (bestucki)


Lesenswert?

Vielen Dank für die schnellen Antworten!

Programmiersprache ist C, steht im Titel.

Es sind alles Arrays mit Integer-Datentypen, also char, short, int, 
long, long long oder die aus stdint.h

Dass ich keine direkten Arrayzugriffe machen kann und casten muss, ist 
mir bewusst. Wie ich nun immer den richtigen Datentyp caste, hatte ich 
mir noch nicht überlegt. Nach kurzem Nachdenken hab ich jedoch keine 
sinnvolle Lösung gefunden, Ideen? Wahrscheinlich wird daran die Sache 
scheitern.

Dass die Sache fehleranfällig wird, hab ich schon vermutet. C kennt 
leider keine Überlagerungen.


So wie ich das sehe, hinkt mein Vorhaben gewaltig...

von Karl H. (kbuchegg)


Lesenswert?

be stucki schrieb:

> Dass ich keine direkten Arrayzugriffe machen kann und casten muss, ist
> mir bewusst. Wie ich nun immer den richtigen Datentyp caste, hatte ich
> mir noch nicht überlegt. Nach kurzem Nachdenken hab ich jedoch keine
> sinnvolle Lösung gefunden, Ideen? Wahrscheinlich wird daran die Sache
> scheitern.

In C geht da eigentlich nur:
zb ein uint8_t als Typkennung zusammen mit einer Handvoll #define oder 
einem enum, der die möglichen Werte dafür festlegt.

von Karl H. (kbuchegg)


Lesenswert?

Oder aber du fasst den Funktionspointer samt einem Pointer zu den 
Daten-Arrays in einer Struktur zusammen.


Aber eines ist klar:
Fehleranfällig ist das eine wie das andere. Du lieferst dich immer dem 
Programmierer aus, dass der keine Fehler macht.


Genau da beginnt ja auch eine der Geburtsstunden der OOP: Der 
Zusammenschluss von Daten samt Bearbeitungsfunktionen zu einer Einheit.

von B. S. (bestucki)


Lesenswert?

Karl Heinz Buchegger schrieb:
> In C geht da eigentlich nur:
> zb ein uint8_t als Typkennung zusammen mit einer Handvoll #define oder
> einem enum, der die möglichen Werte dafür festlegt.

Mein Problem dabei ist, dass ich dem Compiler nicht sagen kann, auf 
welchen Datentyp mein void Zeiger zeigt. Ich kann den void Zeiger in 
einen int Zeiger kopieren und es funktioniert auch alles wunderbar. Soll 
es aber, abhängig von einem Übergabewert, ein anderer sein, funktioniert 
die Sache schon nicht mehr. Ich müsste in einem switch den richtigen 
Datentyp auswählen. Weil dann die entsprechenden Zeiger einen anderen 
Namen haben müssen, muss ich somit auch für jeden Datentyp einen anderen 
Code schreiben, den dann den richtigen Zeiger verwendet. Dann schreibe 
ich besser gleich von Anfang an für jeden Datentyp eine eigene Funktion.

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.