Multiple Methodendefinition - Wie Lösung in ANSI C?
-
Hallo zusammen,
ich habe folgende Signaturen, welche ich brauchen würde:
void add_num(uint8_t** data, uint8_t* pos, uint8_t* value, uint8_t cnt); void add_num(uint8_t** data, uint16_t* pos, uint16_t* value, uint16_t cnt); void add_num(uint8_t** data, uint32_t* pos, uint32_t* value, uint32_t cnt); void add_num(uint8_t** data, uint64_t* pos, uint64_t* value, uint64_t cnt);
Wie macht man soetwas in C? Da dies so ja der Compiler nicht mag. Void Pointer??
Danke für Tips.
uwe
-
Gib jeder Funktion einen anderen Namen add_num8(), add_num16() etc. Etwas besseres kann ich leider nicht bieten.
-
Man kann das schon generischer machen, indem man schummelt.
Ich denke daran, den Präprozessor zu benutzen, und den Datentyp der letzen drei Parameter als Makro einzutragen. Oder man lässt, wie du vorgeschlagen hast, void-Zeiger übergeben und castet sie dann entsprechend, bevor man dereferenziert.Das ist auf Wikipedia eigentlich recht einfach beschrieben.
-
...oder einen zusätzlichen parameter anfügen (länge des typs oder so).
bestimmt kann man auch was mit makros tricksen.
-
Hallo zusammen,
erst mal dank für die vielen, schnellen Antworten. Super. Die Wikiseite hat mich erlich gesagt nicht weitergebracht. Da:
- Templates kann ich aus Plattformgründen nicht verwenden,
- die Makromethode definiert immer ein spezifischen Datentyp für den generischen Algorithmus
- für jeden Type eine neue Funktion will ich eigentlich nicht, da ich sehr beschränkt in der Codegröße bin und die Zeilen abgesehen vom Typ identisch wärenDaher: Wie ist es mit der Makromethode gemeint? Mit Makros kenne ich mich nicht so aus (bin eher aus der Java Ecke
). Bei der void* Methode wie mache ich dann da das Casting, ohne das es letztlich wieder in dreimal dem selben Code nur mit anderem Typ wird?
Die Funktionen schreiben letzlich nur Daten in data, dies ist
**data == *data[];
heißt es wird an eine bestimmte bitposition innerhalb des data bit stream geschrieben, halt mal ein uint16 wert, dann wieder ein uint8 wert und so weiter.
der schreibvorgang an sich ist einfach nur bits von value in data rüberkopieren.
noch nen tip? danke.
uwe
-
uwerothfeld schrieb:
- für jeden Type eine neue Funktion will ich eigentlich nicht, da ich sehr beschränkt in der Codegröße bin und die Zeilen abgesehen vom Typ identisch wären
Du hast doch auch jetzt für jeden Typ eine neue Funktion (beim Überladen bekommst du n eigenständige Funktionen, die nur "zufällig" den selben Namen tragen).
[quote]Daher: Wie ist es mit der Makromethode gemeint?Vermutlich wird's auf sowas hinauslaufen:
#define add_num(data,pos,value,cnt) **data=...
-
hallo,
ja stimmt. das mit dem makro ändert dann ja auch nix an der codegröße, also doch die funktion verdoppeln oder mittels des void* und einer typeinfo casten.
mh, finde ich zwar doof, aber ok.was passiert denn wenn ich ein uint8* auf einen uint64* werfe? geht das überhaupt?
mfg
uwe
-
uwerothfeld schrieb:
was passiert denn wenn ich ein uint8* auf einen uint64* werfe? geht das überhaupt?
Sollte problemlos gehen, umgekehrt wird's schon problematischer. Da triffst du den Nagel auf den Kopf. Du könntest auch einen Datentyp verwenden, der sicher groß genug ist.
Brainstorming: das ganze geht auch mit nur einer Funktion, und ohne Makros; so wie vista/*-freak es oben angemerkt hat. Zur Not kann man ja die Typen "zu Fuß" zusammensetzen.
Beispiel in C89:
#include <stdio.h> /* vereinfachte Paratmeterliste size sollte stimmen */ void add_num(void *first, void *second, int size) { /* ein großer Typ, in den alles hineinpasst */ unsigned long huge1 = 0, huge2 = 0; int i; /* jetzt kommt, was ich "zu Fuß" genannt habe natürlich ginge das auch ohne den Pfusch, aber dafür müsste ich wiederum wissen, daß ich weiter unten mit *short aufrufen werde */ for (i = 0; i < size; i++) { huge1 += *(((unsigned char*) first) + i) << i*8; huge2 += *(((unsigned char*) second) + i) << i*8; } printf("%d %d\n", huge1, huge2); } int main (int ac, char **av) { unsigned short first = 500, second = 600; add_num(&first, &second, sizeof(unsigned short)); return 0; }
EDIT (Anmerkung):
Per Definition ist sizeof(unsigned char) gleich 1. (genau wie sizeof(char))
-
uwerothfeld schrieb:
was passiert denn wenn ich ein uint8* auf einen uint64* werfe? geht das überhaupt?
manche prozessoren mögen sowas nicht und werfen eine exception wegen eines bus- oder alignment errors.
zu dem 'werte aneinanderhängen'. so könnt's auch gehen:void *add (void *dest, void *what, size_t size) { memcpy (dest, what, size); return (char*)dest + size; } ... // der speicher char b[256]; char *p = b; // die variablen int iv = 1; char cv = 2; double dv = 3.0; // und hinein damit p = add (p, &iv, sizeof(iv)); p = add (p, &cv, sizeof(cv)); p = add (p, &dv, sizeof(dv)); ...
-
Wenn man die von CStoll beschriebene Variante mit Makros anstrebt, kann man sich sogar das size-Argument sparen, weil's dann zur Laufzeit bekannt ist.
Beispiel (diesmal ohne memcpy neu zu erfinden...
):
#include <stdio.h> #define add_num(dest, what) {\ memcpy(dest, what, sizeof(*what)); \ dest += sizeof(*what); \ } int main (int ac, char **av) { char b[256]; void *p = b; double dv = 3.14; add_num(p, &dv); printf("%f\n", *(double*)b); return 0; }
EDIT:
Aber scheinbar dürfte ich mich da auf GNU-Extensions verlassen: nämlich sollte es nicht möglich sein, mit p (typ void*) direkt Zeigerarithmetik zu machen. Da fehlt also noch ein char-Cast, denke ich.EDIT2:
#define Laufzeit Compilezeit
-
Hallo zusammen,
ich brauch nochmal eure hilfe. das mit dem memcpy finde ich super, tut nur leider nicht so wie ich es brauche. also nochmal mein problem. ich habe ein zielfeld in welches ich bits reinschreiben will. dann hab ich ein value, welcher vom typ uint8, uint16, uint32, ... ist, von diesen muß ich aber evtl. nur 3 oder 4 bit rüberkopieren. bsp:
uint8[3] ziel={0,0,0}; void* p_ziel = &ziel[0]; uint16 value = 3; p_ziel = add_num(p_ziel,value,2,sizeof(uint16)); //ziel[0]--> 192 add_num(p_ziel,value,2,sizeof(uint16)); //ziel[0] --> 240
probieren tu ich es in die richtung:
void* add_num (uint8_t* dest, void *what, size_t cnt, size_t size) { uint8_t byte_offset = (size/8)-1; uint8_t bit_offset = 8 - (cnt-(8*byte_offset)); void* what_pnt = what; uint8_t i=8-bit_offset; uint8_t resindex=7; printf("%i %i\n",byte_offset,bit_offset); for(;i>0;i--,resindex--){ if(*(uint8_t*)what_pnt & (1<<i-1)){ printf("1"); *dest |= (1 << resindex); printf(" %i \n",(1 << resindex)); } else{printf("0\n");} } printf("\n"); printf("dest %i dest+cnt %i\n",dest,dest+cnt); return dest + cnt; }//End add_num
tut aber leider überhaupt nicht das was es soll.
jemand einen tip? ich raffe es einfach nicht
gruß und dank
-
ja das problem hat sich neugestaltet, daher habe ich mal ein neues thema aufgemacht und mache hier schluß