Struct: gleiche Daten in verschiedenen Variablen

OP #7312831

Ich habe folgendes Struct:

Ich möchte in R G B die gleichen Variablen stehen haben wie in URGB. Wie stelle ich das am dümmsten an? Kann ich einen Teil des Speicherbereichs von URGB auf R mappen? Oder muss ich dies durch eine Funktion laufen lassen?

Sprache ist C.

1
typedef struct
2
 {
3
   uint8_t R;
4
   uint8_t G;
5
   uint8_t B;
6
   uint32_t URGB;   
7
 }  RGBVal;

Liebe Grüße René

Gast

Naja, das geht, ab c11, zwar in der regel schon:

1
typedef struct {
2
  union {
3
    struct {
4
       uint8_t U;
5
       uint8_t R;
6
       uint8_t G;
7
       uint8_t B;
8
     };
9
     uint32_t URGB;
10
  };
11
} RGBVal;

Ist aber eigentlich UB. In clang und gcc sollte es gehen. Der Wert in URGB ist dann aber von der endianness abhängig.

Oliver S. schrieb:

Rene K. schrieb:

Oder muss ich dies durch eine Funktion laufen lassen?

Das wäre das sauberste.

Wie gesagt: in C ist der Ansatz mit der union absolut legal und explizit für type-punning vorgesehen. Deswegen nicht "unsauber" (was auch immer das heißen mag), solange man die Endianness außer Acht lassen kann (keine Serialisierung).

Der Ansatz mit (inline) Funktion und shifts löst auch das Problem.

Und memcpy geht auch noch, verkapselt in einer (inline) Funktion.

Wilhelm M. schrieb:

Oliver S. schrieb:

Rene K. schrieb:

Oder muss ich dies durch eine Funktion laufen lassen?

Das wäre das sauberste.

Wie gesagt: in C ist der Ansatz mit der union absolut legal und explizit für type-punning vorgesehen.

Nein, vorgesehen war er dafür eigentlich nicht. Und die Erklärung, dass man sie dafür verwenden könnte, steht nur in einer nicht normativen Fußnote. Dafür steht im normativen Teil aber das mit der common initial sequence von zwei Strukturen (wie in C++) als "one special guarantee" drin.

Gast

Rene K. schrieb:

Ich möchte in R G B die gleichen Variablen stehen haben wie in URGB.

Was möchtest Du erreichen?

In den meisten Fällen ist es straight, ein Format zu nehmen und das andere per Funktionen bei Bedarf zu konvertieren. Kostet heute auch 0 Overhead.

Für Zuweisungen in einer Anweisung reicht das rgb-struct. Eine Verwendung als Skalar ist für das u32 ja kaum sinnvoll (+x oder *2). Einzig der Vergleich ist damit einfacher. Wenn das nicht oft vorkommt, nimm das RGB struct und sage, was Du mit dem u32 machen möchtest.

Rolf M. schrieb:

Wilhelm M. schrieb:

Oliver S. schrieb:

Rene K. schrieb:

Oder muss ich dies durch eine Funktion laufen lassen?

Das wäre das sauberste.

Wie gesagt: in C ist der Ansatz mit der union absolut legal und explizit für type-punning vorgesehen.

Nein, vorgesehen war er dafür eigentlich nicht. Und die Erklärung, dass man sie dafür verwenden könnte, steht nur in einer nicht normativen Fußnote.

Der normative Text ist:

"A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member,107) and is an lvalue if the first expression is an lvalue. If the first expression has qualified type, the result has the so-qualified version of the type of the designated member."

Die nicht-normative Fußnote erläutert den nicht-normativen Begriff "type-punning".

Also: "type-punning" ist also explizit erlaubt, auch wenn der Begriff nur in der Fußnote fällt.

Dafür steht im normativen Teil aber das mit der common initial sequence von zwei Strukturen (wie in C++) als "one special guarantee" drin.

Aber darum geht es doch hier gar nicht.

Wilhelm M. schrieb:

Der normative Text ist:

"A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member,107) and is an lvalue if the first expression is an lvalue. If the first expression has qualified type, the result has the so-qualified version of the type of the designated member."

Dort sehe ich nirgends eine explizite Erlaubnis, ein anderes Element als das zuletzt geschriebene zu lesen.

Die nicht-normative Fußnote erläutert den nicht-normativen Begriff "type-punning".

Die Fußnote beschreibt es komplett und gibt in Klammern an, dass man das "type punning" nennt.

Das ist für mich kein Zeichen dafür, dass unions wie du sagst explizit dafür vorgesehen wären, sondern eher, dass es auf Grund häufiger Nutzung eben akzeptiert wird.

Dafür steht im normativen Teil aber das mit der common initial sequence von zwei Strukturen (wie in C++) als "one special guarantee" drin.

Aber darum geht es doch hier gar nicht.

Warum ist das eine "special guarantee", wenn type punning doch sowieso der angedachte Zweck sein soll?

Rolf M. schrieb:

Wilhelm M. schrieb:

Der normative Text ist:

"A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member,107) and is an lvalue if the first expression is an lvalue. If the first expression has qualified type, the result has the so-qualified version of the type of the designated member."

Dort sehe ich nirgends eine explizite Erlaubnis, ein anderes Element als das zuletzt geschriebene zu lesen.

Weil das Konzept des active-members in C nicht gibt im Gegensatz zu C++. Deswegen reicht es hier aus, einfach zu schreiben, dass der Wert der union dem Wert das benutzen Elementes entspricht (Achtung: es kann auch hier trap-representations geben).

Die Fußnote beschreibt es komplett und gibt in Klammern an, dass man das "type punning" nennt.

Das ist für mich kein Zeichen dafür, dass unions wie du sagst explizit dafür vorgesehen wären, sondern eher, dass es auf Grund häufiger Nutzung eben akzeptiert wird.

Natürlich war es ganz ursprünglich da, um Speicher zu sparen. Die Formulierung ist eine Klarifizierung gegenüber C89.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 3 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.