Forum: PC-Programmierung [C++] Struktur "durchgehen" mit Pointer (ohne Elementnamen)


von Stefan (Gast)


Lesenswert?

Hallo Gemeinde.

Ich habe folgenden struct definiert, der Elemente unterschiedlicher 
Datentypen aufweist:

struct sExample
{
   float zahl1_float;
   float zahl2_float;
   int   zahl3;
   bool  test_1;
   float zahl4_float;
};


Meine main()-Routine legt eine Variable vom Type der Struktur an, 
initiliasiert diese mit Werten und übergibt die Adresse der Strukur an 
eine Unterfunktion func1( sExample *strukt ), die einen Pointer vom Typ 
sExample hat.

main()
{
    sExample struktur;
    struktur.zahl1_float = 1.2345f;
    struktur.zahl2_float = 2.3456f
    struktur.zahl3       = 18;
    struktur.test_1      = true;
    struktur.zahl4_float = 7.89f;

    func1( &struktur );
};


Jetzt meine Frage:
Die Unterfunktion func1( sExample *strukt ) soll nun die Aufgabe 
erfüllen, alle Werte der Struktur auf der Konsole auszugeben (via cout() 
).
Ich möchte nun aber eben nicht nochmal die Elemente mit ihren Namen 
ansprechen, sondern eleganter die Struktur durchlaufen.

Sprich explizites
cout << strukt->zahl1_float << endl;

soll nicht zur Anwendung kommen.
Kann ich die Elemente irgendwie mittels *strukt erreichen, sodass ich 
irgendwann eine allgemeine Code-Zeile realisieren kann etwa.

cout << (float)(*strukt) << endl;
// nächstes Element
strukt++
cout << (int)(*strukt) << endl;

Welche Möglichkeiten gibt es so etwas umzusetzen? Ich meine jedes 
Element hat doch im Speicher seine eigene Adresse. Hierüber sollte es 
doch erreichabr sein?

Vielen Dank schon einmal im Voraus.

von Stefan (Gast)


Lesenswert?

Ich betone:
Die Schwierigkeit liegt in der Existenz unterschiedlicher Datentypen 
innerhalb der Strukur.
Wären alle Elemente-Typen gleich z.B. Integer wäre es sehr sicher 
einfach die Elemente mittels Zeiger zu erreichen.

DANKE.

von Karl H. (kbuchegg)


Lesenswert?

Stefan schrieb:

> Die Unterfunktion func1( sExample *strukt ) soll nun die Aufgabe
> erfüllen, alle Werte der Struktur auf der Konsole auszugeben (via cout()
> ).
> Ich möchte nun aber eben nicht nochmal die Elemente mit ihren Namen
> ansprechen, sondern eleganter die Struktur durchlaufen.

Musst du aber.
Weder in C, noch in C++ gibt es das, was in Java oder C# 'Reflection' 
genannt wird.

Oder aber, du verwendest in erster Linie keine Struktur, sondern etwas 
intelligenteres.

von Mark B. (markbrandis)


Lesenswert?

Möglicherweise kann man da was mit einem void* Pointer, dem Makro 
offsetof() und "Zurechtgecaste" was machen.

http://www.cplusplus.com/reference/clibrary/cstddef/offsetof/

Oder man verwendet von vornherein eine andere Datenstruktur und umgeht 
das Problem :-)

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Oder aber, du verwendest in erster Linie keine Struktur, sondern etwas
> intelligenteres.


Zb einen Container, der polymorphe Typen aufnehmen kann, wobei die 
einzelnen Objekte dann selbst wissen, wie sie sich auf cout auszugeben 
haben.

von Stefan (Gast)


Lesenswert?

>> Welche Möglichkeiten gibt es so etwas umzusetzen? Ich meine jedes
>> Element hat doch im Speicher seine eigene Adresse. Hierüber sollte es
>> doch erreichabr sein?

char* struct = (char*) parameter;

cout << (float)(*((float*)strukt)) << endl;

// nächstes Element
strukt += sizeof (float)
cout << (int)(*((int*)strukt)) << endl;

// nächstes Element
strukt += sizeof (int)

...

aber warum sollte man so etwas tun ????????

Stefan

von Rolf Magnus (Gast)


Lesenswert?

Stefan schrieb:
> Welche Möglichkeiten gibt es so etwas umzusetzen? Ich meine jedes
> Element hat doch im Speicher seine eigene Adresse. Hierüber sollte es
> doch erreichabr sein?

Ja, eine Adresse hat es, aber wie willst du die ermitteln, ohne den 
Namen des Elements anzugeben? Und woher weißt du den Datentyp? Der ist 
in der Adresse nicht enthalten.

von Stefan (Gast)


Lesenswert?

Betrifft das MACRO offsetof (type, member):

Also wenn ich das Makro mit dem Parameter "member" als String aufrufen 
könnte, dann hätte ich wohl ne Lösung.

Speziell für mein Beispiel:

offsetof (sExample, "zahl4_float"):

Dieser Aufruf würde mir dann den Byte-Offset und damit die 
Speicheradresse des Elemntes liefern. Ich würde den Datentyp in einer 
Tabelle vorhalten die geparsed wird. Somit hätte ich Adresse und 
Datentyp und könnte damit wunderbar arbeiten...

Nur wie zwinge ich offsetof() als zweiten Parameter einen String 
anzuerkennen?

Vielen Dank für eure bisherige Unterstützung!

von Karl H. (kbuchegg)


Lesenswert?

Stefan schrieb:
> Betrifft das MACRO offsetof (type, member):
>
> Also wenn ich das Makro mit dem Parameter "member" als String aufrufen
> könnte, dann hätte ich wohl ne Lösung.
>
> Speziell für mein Beispiel:
>
> offsetof (sExample, "zahl4_float"):

Denk den Gedankengang mal zu Ende.

Was bringt es dir wenn du anstelle von

   cout << pointer->zahl4_float;

ein windiges Konstrukt mittels

   offsetof( sExample, "zahl4_float" );

in die Funktion hinschreiben musst?

> Dieser Aufruf würde mir dann den Byte-Offset und damit die
> Speicheradresse des Elemntes liefern.

Du musst nach wie vor den Namen des Elements, ALLER Elemente, kennen.
Und zwar IN der Funktion!

> Nur wie zwinge ich offsetof() als zweiten Parameter einen String
> anzuerkennen?

Gar nicht.

Wie die Amerikaner sagen: Du bellst den falschen Baum an.

von Rolf Magnus (Gast)


Lesenswert?

Stefan schrieb:
> Speziell für mein Beispiel:
>
> offsetof (sExample, "zahl4_float"):

Was bringt es dir denn, wenn du da statt zahl4_float jetzt "zahl4_float" 
schreiben mußt? Oder anders rum: Wo willst du die Namen der 
Struktur-Elemente herbekommen?

> Nur wie zwinge ich offsetof() als zweiten Parameter einen String
> anzuerkennen?

Das geht nicht. Zur Laufzeit gibt es die Element-Namen nicht mehr, daher 
kann man auch nicht über einen String mit dem Namen an ein Element 
drankommen.

von Stefan (Gast)


Lesenswert?

offsetof( sExample, "zahl4_float" )

schreibe Ich natürlich nicht in den QuellCode hinein.
Der 2. Parameter also der Elementenname wird dynamisch über ein 
Input-File gesetzt. Es geht jetzt darum, Wertzuordnungen aus dieser 
Datei auf eine C-Struktur "zu mappen".

von Karl H. (kbuchegg)


Lesenswert?

Stefan schrieb:
> offsetof( sExample, "zahl4_float" )
>
> schreibe Ich natürlich nicht in den QuellCode hinein.
> Der 2. Parameter also der Elementenname wird dynamisch über ein
> Input-File gesetzt.

Was willst du wirklich machen?
Das wird jetzt alles immer noch konfuser und immer noch 
fehleranfälliger. Du arbeitest momentan in eine Richtung zu der ich nur 
sagen kann: You ask for trouble!

Und das alles um ein Hinschreiben aller Strukturmember zu vermeiden, was 
im übrigen in einer OOP Welt nicht von einer eigenständigen Funktion 
gemacht wird, sondern von einer Memberfunktion der STruktur. Also in 
räumlicher Nähe zur Struktur bleibt, so dass man bei Änderungen diesen 
Teil nur schwer zu ändern vergessen kann.

von Rolf Magnus (Gast)


Lesenswert?

Stefan schrieb:
> Der 2. Parameter also der Elementenname wird dynamisch über ein
> Input-File gesetzt.

Dann mußt du dieses File anlegen und da die ganzen Elementnamen 
reinschreiben.

> Es geht jetzt darum, Wertzuordnungen aus dieser Datei auf eine C-
> Struktur "zu mappen".

Warum schreibst du in diese Datei dann nicht auch gleich noch Offset und 
Datentyp jedes Elements mit rein?

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus schrieb:
> Stefan schrieb:
>> Der 2. Parameter also der Elementenname wird dynamisch über ein
>> Input-File gesetzt.
>
> Dann mußt du dieses File anlegen und da die ganzen Elementnamen
> reinschreiben.

Theoretisch könnte er auch das Header File mit der Strukturdefinition 
parsen.
Hätte wenigstens den Vorteil, dass man nicht vergessen kann, bei 
Änderungen die Beschreibung zu ergänzen.

Nicht das ich diesen ganzen Ansatz mit externer Beschriebung generell 
für vernünftig halten würde. Ich finde ihn nach wie vor schlecht.

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.