Forum: PC-Programmierung Design Frage


von frageer_10 (Gast)


Lesenswert?

Hallo zusammen,

ich habe eine Design Frage, ich habe in C eine Struktur, welche 
beinhaltet wieder mehrere Arrays mit anderen Strukturinstanzen und 
Funktionszeiger.

Beispiel:
1
typedef void (* ABCFuncType)(void);
2
typedef struct ConfigStruct ConfigStructType;
3
typedef struct MyExt1Struct MyExt1StructType;
4
typedef struct MyExt2Struct MyExt2StructType;
5
typedef struct MyExt3Struct MyExt3StructType;
6
7
struct MyExt1Struct
8
{
9
  int a;
10
  int b;
11
  ABCFuncType Routine;
12
};
13
14
struct MyExt2Struct
15
{
16
  int a;
17
  int b;
18
  int c;
19
  ABCFuncType Routine;
20
};
21
22
struct MyExt3Struct
23
{
24
  int a;
25
  int b;
26
  boolean xyz;
27
  boolean aaa;
28
  ABCFuncType Routine;
29
};
30
31
struct ConfigStruct
32
{
33
  const void * MyStructType;  
34
  int length;
35
};

Die Struktur ConfigStruct wird an eine Funktion z.B. 
MainFct(ConfigStructType config) übergeben, wo die Daten weiter 
verarbeitet werden. Die Funktion kann nur einen Parameter, nämlich diese 
Struktur annehmen.
Jetzt ist so, dass diese Funktion (d.h. MainFct) nicht weiß, ob 
MyStructType ist von Typ: MyExt1StructType, MyExt2StructType oder 
MyExt3StructType.
Meiner Meinung nach ich habe drei Möglichkeiten:
1) In ConfigStruct ein ENUM hinzufügen, damit man weiß wie man casten 
soll => Nachteil kostet Laufzeit, da ständig gecastet werden muss :/
2) Anstatt 3 Strukturen, alle mögliche attribute in nur einer Struktur 
packen => Nachteil kostet Speicher, was auch knapp ist.

Zur Info: deswegen 3 Strukturen, da die Attributen 
Konfigurationsabhängig sind. Von der Struktur: MyStructType werden ca. 
200-300 Instanzen angelegt ;)

Kennt Ihr vielleicht eine Lösung für solche Probleme?

Grüße

: Verschoben durch Moderator
von Bastler (Gast)


Lesenswert?

Union?
Die kann dann auch das Ziel eines Pointers sein.
Ein cast der Art "seh denn Speicherbereich an Adresse X mal als wie 
Struktur Y strukturiert an", kosten übrigens genau nix.

von frageer_10 (Gast)


Lesenswert?

@Bastler: union ist nicht möglich :(

von Bastler (Gast)


Lesenswert?

Es muß ja nicht jede Instanz eine union sein. Es reicht ja, wenn der 
*MyStructType auf eine solche zeigt. Wenn dann jede Struktur mit dem von 
dir schon angedachten enum STRUCT_TYPE beginnt, dann kann man einfach 
entscheiden welche "Sicht" auf die Daten die richtige ist.
Falls die "Routine" für die Verarbeitung der Daten zuständig ist, würde 
ich diese in allen structs an den Anfang stellen. Eine struct mit nur 
diesem Funktions-Pointer wäre dann das einzige, was über ein "Objekt" 
bekannt sein muß. Nennt man auch "interface".
Wenn du noch nichts mit objektorientierten Sprachen zu tun hattest, dann 
stehst du kurz davor diese Techniken selbst zu "erfinden". Bei mir war 
das sehr oft der Weg etwas zu lernen. Indem man selbst vom Problem 
ausgehend die Lösung erarbeitet. Thumbs Up!

von frageer_10 (Gast)


Lesenswert?

@Bastler: wie meinst Du es genau? castem muss ich sowieso. Könntest Du 
mir ein Beispiel skizzieren? ;)
Mit der Lösung zwei meinte ich folgendes:
1
typedef struct MyExt3Struct MyExt3StructType;
2
3
struct MyExt3Struct
4
{
5
  boolean xyz;
6
  boolean aaa;
7
  
8
};
9
10
struct MyExt1Struct
11
{
12
  int a;
13
  int b;
14
  const MyExt3StructType* MyExt3typ;
15
  ABCFuncType Routine;
16
};
MyExt3typ ist entweder NULL oder wenn die Attributen vorhanden sein 
sollten, dann wird eine Adresse zugewiesen. Wie schon gesagt, auch wenn 
NULL stehen sollte, dann kostet es auch viel Speicher....

Lösung 1 hat gewissen Charm ;) so eine Art von Polymorphismus...

BTW. Mit objektorientierten Sprachen hatte ich zu tun gehabt: Java und 
C#

von Bastler (Gast)


Lesenswert?

Ok, nur daß man in Java und C# wenig mit der technischen Implemantierung 
zu tun hat. Daß ein Objekt aus einem Pointer auf ein Array von 
Methoden-Pointern und nachfolgend, nach dem Pointer, den 
Member-Variablen besteht, erfährt man da nicht.

Nach deinem Beispiel gibt es 3 verschiedene Strukturen. Alle beinhalten 
einen Functions-Pointer. Wie diese benutzt werden sollen ist nicht 
bekannt. Kennt die Hauptfunktion den Aufbau der Strukturen oder reicht 
sie diese nur transparent an den enthaltenen Funktions-Pointer weiter?
Falls ersteres muß es zum Unterscheiden der Strukturen irgendein 
Kennzeichen geben. Getrixt könnte das natürlich auf der Pointer sein, 
falls für jede Struktur eine andere Funktion benutzt wird.

Leider ist aber der entscheidende Teil der Problemstellung nicht 
beschrieben, vermutlich weil "schon gelöst" und nun müssen nurmehr die 
Probleme dieser "Lösung" ausgeräumt werden. Erinnert mich an die Arbeit 
und die ruht bei mir bis Montag ;-)

von frageer_10 (Gast)


Lesenswert?

ups, mein Fehler, Funktionspointer beinhaltet nur die ConfigStruct. Die 
Hauptfunktion kennt die Strukturtypen, aber wie schon gesagt bei der 
Übergabe weiß nicht für welche hat sich der "Konfigurator" entschieden 
;) in der ConfigStruct stehen mehrere Funktionspointer, die aufgerufen 
werden und in dieser Funktionen werden Daten von MyStructType 
verarbeitet, d.h. diese Funktionen müssen auch den Typ von der Struktur 
kennen. Alle Funktionen müssen auch Reentrant sein.

Hmmmm....viellciht sollte ich doch eine große Struktur, mit allen 
Optionen/Attributen, zur Verfügung stellen? dann muss ich die NULL 
Pointer in kauf nehmen. Auch wegen Erweiterbarkeit, d.h. es kann sein, 
dass neue Attributen gebraucht werden, dann müsste ich x-Verschiedene 
Strukturtypen (alle Kombinationen) zur Verfügung stellen. pro Null 
Pointer und Struktur verliere ich 32 Bits. In jeder Funktion zuerst via 
Switch-Case den Typ zu ermitteln und dann noch zu casten würde 
vielleicht doch zu viel Laufzeit kosten......??

Mit OOD/OOR würde ich es mit Vererbung lösen.

Danke für Deine Antworten!!!

von Bastler (Gast)


Lesenswert?

Bei 32bit Pointer hat man doch eigentlich RAM satt, oder?

von frageer_10 (Gast)


Lesenswert?

na ja etwa 288kB RAM, wobei meine Module sind nicht alleine da ;) Wir 
haben ständig damit Probleme....

von Tom (Gast)


Lesenswert?

frageer_10 schrieb:
> In jeder Funktion zuerst via
> Switch-Case den Typ zu ermitteln und dann noch zu casten würde
> vielleicht doch zu viel Laufzeit kosten......??
Bauchgefühl funktioniert bei sowas nicht, Messen und Profiling schon.

> Mit OOD/OOR würde ich es mit Vererbung lösen.
C++ und als einziges Feature an dieser Stelle Polymorphie benutzen? Wenn 
man Polymorphie braucht und von Hand nachprogrammiert, ist der Overhead 
wahrscheinlich (mindestens) der gleiche wie wenn man den Compiler das 
erledigen lässt.

von frageer_10 (Gast)


Lesenswert?

@Tom: ich muss embedded C nutzen.

Meine letzte Frage ist,
Lösung 1) mit verschiedenen Structs, abhängig von der Konfiguration.
Oder doch Lösung 2) mit einer großen Struktur und bei zusätzlichen 
Attributes kommen Zeigern auf Extended-Strukturinstanzen, welche bei der 
nicht Benutzung auf NULL Zeiger zeigen?

Was meint Ihr?

von lalala (Gast)


Lesenswert?

frageer_10 schrieb:
> Nachteil kostet Laufzeit, da ständig gecastet werden muss :/

Mal das assembler-Listing ansehen. Casten sollte eigentlich gar keine 
Laufzeit kosten (wie sollte denn ein Cast im Assembler Deiner Meinung 
nach aussehen?)

von frageer_10 (Gast)


Lesenswert?

@lalala: ok, dann kostet 0, aber switch-case schon.
Na gut, aber welche Option 1 oder 2 ist eher optimal oder suboptimal?

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.