Forum: Compiler & IDEs C Construct an unnamed object in-place?


von John (Gast)


Lesenswert?

Kann man ein struct anonym initialisieren und den Zeiger darauf erhalten 
(ähnlich zu string)?

    struct child {...}
    struct child * cp = &{...};

von Klaus W. (mfgkw)


Lesenswert?

Du willst vielleicht C++ nehmen?

In C gibt e keine Konstruktion von structs.
Du kannst dir Platz mit malloc() oder calloc() schaffen (letzteres 
initialisiert zu Nullen immerhin) oder sonstwie und bei Bedarf eine 
eigene Funktion danach aufrufen, die alles zurechtbiegt.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

In C gar nicht, aber in C++ schon::
1
child* cp = new child { 1, 2, 3};

Danach muss man die Instanz wieder mit "delete" löschen. Besser geht das 
mit std::unique_ptr:
1
auto cp = std::make_unique <child> (1, 2, 3);

Löscht die Instanz automatisch. Den Zeiger selbst bekommst du mit 
cp.get().

von Oliver S. (oliverso)


Lesenswert?

John schrieb:
> Kann man

irgendeine obskure Definition/Deklaration/etc. machen?

Die erste Autorität zu dem Thema ist dein Compiler. Der sagt dir schon, 
was er davon hält. Also frag den doch einfach.

Die Antwort lautet selbstverständlich nein. Aber du solltest mal nach 
rvalue reference googlen. Das ist im Prinzip das, was du willst, nur mit 
reference statt pointer.
1
    struct child {int foo;};
2
    struct child &&cp = {3};

Oliver

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Oliver S. schrieb:
> Die erste Autorität zu dem Thema ist dein Compiler.

Eher der C- oder eben C++ -Standard. Viele Compiler haben Erweiterungen, 
die nicht auf andere übertragbar sind. Daher ist es sinnvoll, sich nicht 
einfach nur auf ausprobieren zu verlassen, sondern eben den Standard 
oder eine verdaulichere Fassung davon, wie ein gutes Buch, zu 
konsultieren.

: Bearbeitet durch User
von John (Gast)


Lesenswert?

Ok danke.

von Oliver S. (oliverso)


Lesenswert?

Niklas G. schrieb:
> Viele Compiler haben Erweiterungen,
> die nicht auf andere übertragbar sind.

Nun ja, da hätte man zwei Möglichkeiten: man freut sich, daß es mit 
diesem einen Compiler funktioniert, oder man wählt per Compileroption 
diese Erweiterungen ab.

Oliver

: Bearbeitet durch User
von hä? (Gast)


Lesenswert?

John schrieb:
> struct child {...};
> struct child * cp = &{...};

natürlich geht es mit C.  Und im Prinzip genauso wie du es in der Frage 
formulierst.
1
   struct child {
2
      int a;
3
      int b;
4
      int c;
5
   };
6
7
   struct child* cp = &((struct child){ .a = 1, .b = 2, .c = 3 });
8
9
   printf ("%d\n", cp->c);


"compound literals" heißt das Ding.

von John (Gast)


Lesenswert?

Der Compiler meckert nicht!
1
#include <stdint.h>
2
3
struct inRAM{
4
    int16_t variable;
5
    const struct inFLASH __flash * ptr;
6
};
7
8
struct inFLASH{
9
    const int16_t constant;
10
    const char __flash * string;
11
};
12
13
struct inRAM array[] = {
14
    {-11, &(const struct inFLASH __flash){42, (const __flash char[]){"world"}}},
15
};

von John (Gast)


Lesenswert?

Mhh, da stimmt aber irgendwas noch nicht - ein Zeichen weniger im string 
spart zwei Bytes Flash!?

von Klaus W. (mfgkw)


Lesenswert?

Kann schon sein, wenn die Variable dahinter auf einer 2-Byte-Grenze 
liegen muß. Vor der Verkürzung des Strings gibt es ein ungenutztes 
Füllbyte deswegen, nach der Verkürzung braucht es das nicht und die 
Variable kann 2 vorrücken.

von John (Gast)


Lesenswert?

Tatsache, noch ein Zeichen weniger, Flash bleibt gleich (bezieht sich 
auf avr-libc und GCC).

Vielen Dank!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

hä? schrieb:
> natürlich geht es mit C

Der Zeiger ist dann aber nur bis zum Ende des umschließenden Blocks 
gültig. Da hätte man auch eine normale Variable nehmen können und halt & 
verwendet...

von mh (Gast)


Lesenswert?

Niklas G. schrieb:
> hä? schrieb:
>> natürlich geht es mit C
>
> Der Zeiger ist dann aber nur bis zum Ende des umschließenden Blocks
> gültig. Da hätte man auch eine normale Variable nehmen können und halt &
> verwendet...

Ich bin mir nicht sicher was du sagen willst, aber dieser compound 
literal hat static storage duration. Sieht aus wie nen cast, verhält 
sich aber in nahezu jeder hinsicht anders.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

mh schrieb:
> aber dieser compound literal hat static storage duration.

Laut Cppreference nur wenn es außerhalb von Funktionen steht:

https://en.cppreference.com/w/c/language/compound_literal

mh schrieb:
> Ich bin mir nicht sicher was du sagen willst

Der Gewinn gegenüber
1
struct child cp = { .a = 1, .b = 2, .c = 3 };
2
   printf ("%d\n", (&c)->c);
ist halt marginal. Ein Äquivalent zur "new" Expression gibt es nicht, 
außer vielleicht einer lustigen Konstruktion mit Makros...

von Klaus W. (mfgkw)


Lesenswert?

hä? schrieb:
> "compound literals" heißt das Ding.

Das ist aber mit Vorsicht zu genießen.
Ich glaube ab C99 geht das so, aber nur in C. In C++ wäre das nur ein 
temporäres Objekt, das am Ende der Anweisung stirbt. Der Zeiger darauf 
wird damit zu russischen Roulette in C++.

https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html

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.