Wie kann man auf Member einer 'struct' entsprechend einer Variablen in C zugreifen?

8

Angenommen, ich habe struct (die übrigens Bitfelder enthalten, aber das sollte Ihnen egal sein):

%Vor%

und ich möchte auf bequeme Weise auf das i -Mitglied zugreifen. Lassen Sie uns eine Retrieval-Lösung untersuchen.
Ich habe diese Funktion entwickelt:

%Vor%

Aber ich vermute, dass es eine viel einfachere Lösung gibt. So etwas wie ein Array, das auf den Stil zugreift, vielleicht.

Ich habe versucht, so etwas zu tun:

%Vor%

Aber es wird erwartet, dass es nicht funktioniert.
Gibt es eine bessere Lösung?

    
Ori Popowski 20.05.2009, 13:20
quelle

12 Antworten

12

Wenn Sie keine spezifische Kenntnis der zugrunde liegenden Struktur der Struktur haben, gibt es keine Möglichkeit, eine solche Methode in C zu implementieren. Es gibt alle Arten von Problemen, einschließlich

  • Mitglieder verschiedener Größen
  • Verpackungsprobleme
  • Ausrichtungsprobleme
  • Tricks wie Bitfelder sind problematisch

Am besten implementieren Sie eine Methode von Hand für Ihre Struktur, die ein tiefes Verständnis der internen Mitglieder der Struktur hat.

    
JaredPar 20.05.2009, 13:24
quelle
6

Wenn jedes Feld in Ihrer Struktur ein int ist, sollten Sie grundsätzlich

sagen können %Vor%

Dadurch wird der Zeiger auf Ihre Struktur zu einem Zeiger auf ein Array konvertiert, wenn ganze Zahlen verwendet werden, und dann auf das n-te Element dieses Arrays zugegriffen. Da alles in Ihrer Struktur eine Ganzzahl zu sein scheint, ist dies absolut gültig. Beachten Sie, dass dies fürchterlich scheitern wird, wenn Sie jemals ein Nicht-Int-Mitglied haben.

Eine allgemeinere Lösung wäre, ein Array von Feldversätzen beizubehalten:

%Vor%

Dies funktioniert in dem Sinne, dass Sie getval für jedes der int-Felder Ihrer Struktur aufrufen können, selbst wenn Sie andere nicht-int-Felder in Ihrer Struktur haben, da die Offsets alle korrekt sind . Wenn Sie jedoch versucht haben, getval für eines der Nicht-Int-Felder aufzurufen, wird ein vollständig falscher Wert zurückgegeben.

Natürlich könnten Sie für jeden Datentyp eine andere Funktion schreiben, z. B.

%Vor%

und rufen Sie dann einfach die richtige Funktion für den gewünschten Datentyp auf. Übrigens, wenn Sie C ++ benutzten, könnten Sie etwas wie

sagen %Vor%

und dann würde es für jeden gewünschten Datentyp funktionieren.

    
Eli Courtwright 20.05.2009 13:34
quelle
6

Wenn Sie Ihre Struktur war nichts außer bitfields, könnten Sie nur Array-Zugriff verwenden, wenn ich mich richtig in Erinnerung, dass C garantiert, dass eine Reihe von Mitgliedern einer Struktur alle vom gleichen Typ, das gleiche Layout wie ein Array hat. Wenn Sie wissen, was in Bits, was Ihren Compiler speichert bitfields in Integer-Typen bestellt, dann könnten Sie Shift / Maske ops verwenden, aber das ist dann abhängig von der Implementierung.

Wenn Sie auf Bits mit variablem Index zugreifen möchten, ist es wahrscheinlich am besten, Ihre Bitfelder durch eine ganze Zahl mit Flag-Bits zu ersetzen. Der Zugriff durch Variable ist wirklich nicht das, wofür Bitfelder stehen: a1 ... an sind grundsätzlich unabhängige Mitglieder, nicht ein Array von Bits.

Sie könnten so etwas tun:

%Vor%

Und einige der Wiederholungen könnten durch den Trick vermieden werden, bei dem Sie den gleichen Header mehrmals einfügen, jedes Mal, wenn Sie ein Makro anders definiert haben. Der Header erweitert dieses Makro einmal für jede 1 ... N.

Aber ich bin nicht überzeugt, dass es das wert ist.

Es tut Deal mit JaredPar der Punkt, dass Sie in Schwierigkeiten sind, wenn Ihre Struktur verschiedene Arten vermischt - hier alle Mitglieder über einen bestimmten Sprungtabelle muss natürlich vom gleichen Typ sein zugegriffen, aber sie können alle alten Müll haben zwischendurch Sie. Das läßt noch den Rest JaredPar die Punkte, aber, und das ist eine Menge Code aufblasen für wirklich keinen Vorteil gegenüber dem Schalter.

    
Steve Jessop 20.05.2009 13:45
quelle
2

Nein, es gibt keinen einfachen Weg, das einfacher zu machen. Vor allem für Bitfelder, auf die indirekt über Zeiger kaum zugegriffen werden kann (die Adresse eines Bitfeldes kann man nicht annehmen).

Sie können diese Funktion natürlich auf folgende Weise vereinfachen:

%Vor%

Und es scheint offensichtlich, wie die Umsetzung kann durch die Verwendung eines Präprozessormakro vereinfacht werden, die auf das% erweitern co_de% -Linie, aber das ist nur Zucker .

    
unwind 20.05.2009 13:25
quelle
0

Wenn die Struktur wirklich so einfach ist wie beschrieben, können Sie eine Vereinigung mit einem Array (oder eine Umwandlung in ein Array) und etwas Bit-Access-Magie (wie in Wie setzen, löschen und schalten Sie ein einzelnes Bit in C? ).

Wie Jared sagt, ist der allgemeine Fall schwer .

    
dmckee 20.05.2009 13:37
quelle
0

Ich denke, Ihre wirkliche Lösung besteht darin, keine Bitfelder in Ihrer Struktur zu verwenden, sondern stattdessen einen Settyp oder ein Bit-Array zu definieren.

    
plinth 20.05.2009 13:50
quelle
0

Ich empfehle Code-Generierung. Wenn Ihre Strukturen keine große Anzahl von Feldern enthalten, können Sie Routinen für jedes Feld oder für eine Reihe von Feldern automatisch generieren und verwende sie wie:

%Vor%

oder

%Vor%     
Nick Dandoulakis 20.05.2009 14:08
quelle
0

Wenn Sie

haben
  1. Nur Bitfelder oder alle Bitfelder in Ihrer Struktur
  2. weniger als 32 (oder 64) Bitfelder

Dann ist diese Lösung für Sie.

%Vor%     
gnud 20.05.2009 14:32
quelle
0

Basierend auf Eli-Courtwright-Lösung, aber ohne Feldoffsets zu verwenden ...... Wenn Sie eine Struktur mit einem solchen Zeigerfeld haben, könnten Sie vielleicht schreiben:

%Vor%

Dann wissen Sie, dass jeder Zeiger einen 4-Byte-Offset von einem Zeiger auf die Struktur hat, so dass Sie schreiben können:

%Vor%

Dann können Sie beispielsweise für einen int-Wert schreiben:

%Vor%

Aufruf durch:

%Vor%

und so weiter für die anderen Strukturfeldwerte (Schreiben anderer spezifischer Funktionen und Verwenden des korrekten Byte-Offsetwerts (Vielfaches von 4)).

    
fabdan 15.01.2010 14:21
quelle
0

Obwohl das OP angibt, dass wir uns nicht um den Inhalt der Struktur kümmern sollten, da es nur Bitfelder sind, wäre es möglich, ein char oder int (oder einen anderen Datentyp mit der erforderlichen Größe) zu verwenden, um ein n- zu erzeugen. Bit "Array" in diesem Fall?

%Vor%

mit den Char-Typen ersetzt durch einen größeren Typ, wenn ein längeres "Array" benötigt wurde. Nicht sicher, dass dies eine definitive Lösung in anderen Strukturen ist, aber es sollte hier funktionieren, mit einer ähnlichen Readbit-Funktion.

    
aktungmak 29.12.2011 10:37
quelle
0

Wenn Sie mit beiden Elementindexen auf Ihre Struktur zugreifen wollen:

%Vor%

und namentlich:

%Vor%

Dann sind Sie mit einer schwer zu pflegenden switch-ähnlichen Methode fest, die jeder vorgeschlagen hat.

Wenn Sie jedoch nur nach Index und niemals nach Namen suchen möchten, können Sie etwas kreativer sein.

Definieren Sie zunächst einen Feldtyp:

%Vor%

und erstellen Sie dann eine Strukturdefinition:

%Vor%

Das Obige definiert eine Struktur mit fünf Elementen der Größe 1, 1, 1, 4 und 1 Bits. Das letzte {0} markiert das Ende der Definition.

Erstellen Sie jetzt einen Elementtyp:

%Vor%

So erstellen Sie eine Instanz von Element :

%Vor%

Und dann auf ein Element zugreifen:

%Vor%

Das Einstellen von Werten ähnelt dem Abrufen von Werten, nur der letzte Teil muss geändert werden.

Sie können das Obige erweitern, indem Sie die FieldType -Struktur erweitern, um Informationen über den Typ des gespeicherten Werts aufzunehmen: char, int, float usw. Anschließend schreiben Sie Accessoren für jeden Typ, der den erforderlichen Typ gegen den definierten Typ prüft.

    
Skizz 20.05.2009 14:31
quelle
0

Warum nicht getval() in die Struktur einbauen?

%Vor%

getIth() hätte Kenntnis von den Interna von Whang und könnte damit umgehen, was immer es enthielt.

    
Number8 20.05.2009 13:38
quelle

Tags und Links