Forum: Mikrocontroller und Digitale Elektronik C++: MyFunc(struct val) -> Aufruf: MyFunc({1,2}); - Warum gehts nicht?


von Alexander I. (daedalus)


Lesenswert?

Hallo,

Warum kann ich einen struct nicht implizit mit "{ ... }" erzeugen und 
direkt als Parameter für eine Funktion verwenden? Ich erhalte immer 
"Syntaxfehler: '{'" als Fehler.

Kurzes Beispiel:
1
typedef struct
2
{
3
 int a;
4
 int b;
5
} summanden;
6
7
int Addiere(summanden param)
8
{
9
 return param.a+param.b;
10
}

Funktionsaufruf:
1
summanden test1 = {1,2};
2
Addiere(test1); // funktioniert
3
Addiere({4,5}); // funktioniert NICHT, warum?

Wo liegt für den Compiler das Problem? Er könnte doch ohne weiteres den 
Struct implizit erzeugen und auf den Stack schmeißen, damit die Funktion 
ihn nutzen kann... danach interessiert selbiger ja nicht mehr.

Der Hintergrund ist folgender:
Ich habe eine verkettete Liste (STL) der ich in einer 
Initialisierungfunktion ziemlich viele Elemente anfügen möchte, die z.B. 
Defines sind. also Beispiel:
1
Liste.push_back({"einwert", EINWERT});

Gibt's da eine elegante Lösung, die keine temporäre Erstellung einer 
Variable (test1, siehe oben) benötigt?

Vielen Dank vorab.

von der mechatroniker (Gast)


Lesenswert?

Eine zweite Funktion, die die Werte "einzeln" entgegennimmt. Für die 
eigentliche Funktionalität sollte eine von beiden dann die andere 
aufrufen, damit der Code nicht dupliziert wird.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ein Makro.
1
summanden s;
2
#define ADD(a,b) s.a = (a); s.b = (b); Addiere (s);
3
ADD (5, 3);
4
ADD (42, 4);

von Sven P. (Gast)


Lesenswert?

Niklas G. wrote:
> Ein Makro.
>
1
summanden s;
2
> #define ADD(a,b) s.a = (a); s.b = (b); Addiere (s);
3
> ADD (5, 3);
4
> ADD (42, 4);

Voll am Sinn vorbei, würd ich sagen...

Man kann sowas auch mit Templates lösen, so wie PAIR das macht.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Sven P. wrote:
> Voll am Sinn vorbei, würd ich sagen...
Würde ich nicht sagen. Was Alex suchte, war doch lediglich eine 
einfachere Schreibweise, 2 Werte in eine zu erzeugende struct auf dem 
Stack zu speichern. Die Schreibweise mit { ... } klappt ja nicht, und 
das Makro tut doch nichts anderes, als beide Werte in die struct im 
Stack zu speichern. Würde die {..}-Methode funktionieren, käme da 
wahrscheinlich genau der gleiche Asm-Code heraus wie mit dem Makro.

von Oliver (Gast)


Lesenswert?

>Addiere({4,5}); // funktioniert NICHT, warum?

Weil der Compiler nicht weiß, was {4,5} sein soll.
WEnn du ihm das sagst, geht es:
1
Addiere((summanden){4,5});

Oliver

von Alexander I. (daedalus)


Lesenswert?

Hallo Oliver:

Das war so auch mein erster Gedanke. VC++ 2005 akzeptiert den Code dann 
aber trotzdem nicht. Selber Fehler.

Die Idee mit dem Makro funktioniert, hätte ich auch selber draufkommen 
können.

von Karl H. (kbuchegg)


Lesenswert?

Da es sich ja um C++ handelt, würde ich das so machen

1
struct summanden
2
{
3
 int a;
4
 int b;
5
6
 summanden( int a_, int b_ ) : a( a_ ), b( b_ )  {}
7
};
8
9
int Addiere( const summanden & param )
10
{
11
 return param.a + param.b;
12
}
13
14
int main()
15
{
16
   Addiere( summanden( 5, 4 ) );
17
}

Noch besser allerdings wäre es, C++ nicht als verkapptes C zu benutzen
1
struct summanden
2
{
3
 int a;
4
 int b;
5
6
 summanden( int a_, int b_ ) : a( a_ ), b( b_ )  {}
7
 int Add() const { return a + b; }
8
};
9
10
int main()
11
{
12
  summanden test1( 1, 2 );
13
  int res1 = test1.Add();
14
  int res2 = summanden( 4, 5 ).Add();
15
}

von Karl H. (kbuchegg)


Lesenswert?

Alex Wurst wrote:
> Hallo Oliver:
>
> Das war so auch mein erster Gedanke. VC++ 2005 akzeptiert den Code dann
> aber trotzdem nicht. Selber Fehler.

Klar. Das ist nun mal von der C++ Syntax her so nicht vorgesehen.

> Die Idee mit dem Makro funktioniert, hätte ich auch selber draufkommen
> können.

Sie ist trotzdem schlecht.

von Karl H. (kbuchegg)


Lesenswert?

> Liste.push_back({"einwert", EINWERT});
>
> Gibt's da eine elegante Lösung, die keine temporäre Erstellung einer
> Variable (test1, siehe oben) benötigt?

Deine Liste besteht aus bestimmten Typen.
Verpass diesem Type einen Konstruktor und gut ists.

Mach dir keine Sorgen wegen temporärer Variablen. Wenn du die Funktionen 
inline machst, wird der Compiler sie wegoptimieren. Der ist als C++ 
Compiler darauf getrimmt, solche Fälle zu erkennen.
1
enum UnitTypes {
2
   EINWERT,
3
   ZWEIWERT,
4
   DREIWERT
5
};
6
7
stuct Units
8
{
9
  std::string  text;
10
  UnitTypes    type;
11
12
  Units( const std::string & text_, UnitTypes type_ )
13
  : text( text_ ),
14
    type( type_ )
15
  {
16
  }
17
}
18
19
int main()
20
{
21
  std::list< Units > Liste;
22
23
  Liste.push_back( Units( "einwert", EINWERT ) );
24
  Liste.push_back( Units( "zweiwert", ZWEIWERT ) );
25
  Liste.push_back( Units( "dreiwert", DREIWERT ) );
26
}

Wenn deine struct nicht mehr als aus 2 Werten besteht, ist auch der 
Hinweis auf std::pair (wie er weiter oben schon mal gebracht wurde) mehr 
als gerechtfertigt. Fang an C++ zu programmieren und nicht 'C mit 
Erweiterungen'

von Oliver (Gast)


Lesenswert?

>Klar. Das ist nun mal von der C++ Syntax her so nicht vorgesehen.

Das war so auch mein erster Gedanke, aber gcc schluckt es. Sowohl als C 
als auch als C++.

>VC++ 2005 akzeptiert den Code dann
>aber trotzdem nicht. Selber Fehler.

Grüße an Bill...


Oliver

von Karl H. (kbuchegg)


Lesenswert?

Oliver wrote:
>>Klar. Das ist nun mal von der C++ Syntax her so nicht vorgesehen.
>
> Das war so auch mein erster Gedanke, aber gcc schluckt es. Sowohl als C
> als auch als C++.

Für C gabs da eine Änderung im letzten Standard, die sich meines Wissens 
noch nicht bis C++ durchgerungen hat.

Das der gcc es schluckt wundert mich nicht wirklich.
Dazu muss man wissen, wie Änderungen im Standard durch die Gremien 
geboxt werden: Da gibt es jemanden der eine Änderung vorschlägt. Sein 
Problem: Er braucht eine kleine Lobby die ihn unterstützt, den das 
Gremium ist erst mal konservativ und versucht die Sprache so zu halten 
wie sie zur Zeit ist. Ein starkes Argument, welches das Gremium niemals 
ignorieren wird, ist allerdings, wenn man einen Compiler vorweisen kann, 
der diese Änderung bereits enthält und man so dokumentieren kann, dass 
diese Änderung erstens machbar ist und zweitens keine sonstigen 
weitreichenden Auswirkungen auf die Sprache hat. Und für diese 
Demo-Implementierung wird nun mal der gcc sehr gerne hergenommen. Daher 
sollte es nicht verwundern, dass der gcc oft schon Dinge beherrscht, die 
noch gar nicht durch die Normungs-Gremien als Sprachstandard abgesegnet 
wurden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:

> Ein starkes Argument, welches das Gremium niemals
> ignorieren wird, ist allerdings, wenn man einen Compiler vorweisen kann,
> der diese Änderung bereits enthält und man so dokumentieren kann, dass
> diese Änderung erstens machbar ist und zweitens keine sonstigen
> weitreichenden Auswirkungen auf die Sprache hat.

Genau darum habe ich ja am Ende die Binärkonstanten (die mit dem 0b)
bei GCC durchgeboxt.  Bei der Standardisierung von C99 ist dieses
Feature vorgeschlagen worden, aber die Rationale erklärt dazu nur
lapidar, dass der Vorschlag abgelehnt wurde ``due to lack of precedent
and application''.  Zumindest der erste Punkt (lack of precedent) hat
sich dann also mal erledigt, wenn sich die Damen und Herren das nächste
Mal zusammen setzen. :-)  (Natürlich gab es zuvor bereits andere
Compiler aus dem Controllerbereich, die es implementiert hatten, aber
die sind vermutlich den C-Normierern zu popelig, als dass sie die
kennen würden.  Zumindest `lack of application' hätte sich damit jedoch
auch erledigt, denn ganz ohne Nachfrage wird das kaum jemand da rein
gebaut haben.)

von Alexander I. (daedalus)


Lesenswert?

Vielen Dank, die Lösung mit dem Standardkonstrutkor von Karl-Heinz 
scheint mir die eleganteste zu sein. Funktioniert auch einwandfrei!

Vielen Dank für die Antworten!

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch wrote:

> Genau darum habe ich ja am Ende die Binärkonstanten (die mit dem 0b)
> bei GCC durchgeboxt.  Bei der Standardisierung von C99 ist dieses
> Feature vorgeschlagen worden, aber die Rationale erklärt dazu nur
> lapidar, dass der Vorschlag abgelehnt wurde ``due to lack of precedent
> and application''.

... was mir ehrlich gesagt völlig unverständlich ist. Jeder der mal 
einen Compiler gebaut hat, weiß doch aus dem Stand, dass eine derartige 
Erweiterung nun wirklich nicht das große Drama verursachen wird. Im 
Grunde könnte man mit dem gleichen Argument auch die Hex-Schreibweise 
aus der Sprache verbannen oder noch viel besser die unselige 
oktal-Schreibweise (ich wär sogar froh, wenn die aus C bzw. C++ 
verschwinden würde)

> Mal zusammen setzen. :-)  (Natürlich gab es zuvor bereits andere
> Compiler aus dem Controllerbereich, die es implementiert hatten, aber
> die sind vermutlich den C-Normierern zu popelig, als dass sie die
> kennen würden.

:-)

Ich denke mal, die sehen sich auch an, welcher Compiler das ist, ob den 
jemand kennt, wie gut er den bisherigen Standard umsetzt udgl.
Wenn ich einen C-Compiler schreiben würde und dem eine Erweiterung 
verpasse, dann wird das keinen wirklich interessieren. Bau ich das aber 
in den gcc ein, dann hat das gleich ein ganz anderes Gewicht. Nicht 
vergessen sollte man auch, dass in der Rationale ja auch Firmenvertreter 
sitzen. Die haben natürlich auch ein ganz anderes Interesse: Alles was 
nicht unbedingt notwendig ist, erst mal abblocken. Neue Forderungen aus 
dem Standard bedeuten für sie ja in erster Linie erst mal Änderungen am 
bestehenden Produkt was ja gleichbedeutend mit neuen Fehlern im Compiler 
und damit erhöhten Kosten ist.

> Zumindest `lack of application' hätte sich damit jedoch
> auch erledigt, denn ganz ohne Nachfrage wird das kaum jemand da rein
> gebaut haben.)

Ich hab überhaupt das Gefühl, dass die sich hier eher nach Oben 
orientieren als sich mit so Kleinigkeiten, die uns µC Programmieren das 
Leben ein klein wenig leichter machen würden, abzugeben. Seien wir uns 
ehrlich: Ob es Binärkonstanten gibt oder nicht, interessiert doch 
ausserhalb der µC Szene niemanden wirklich.

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.