Struct: gleiche Daten in verschiedenen Variablen

OP #7312831
Lesenswert?

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 #7312888
Lesenswert?

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.

#7313077
Lesenswert?

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.

#7314456
Lesenswert?

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 #7314599
Lesenswert?

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.

#7314782
Lesenswert?

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.

#7314913
Lesenswert?

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?

#7314943
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren