www.mikrocontroller.net

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


Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht 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:
typedef struct
{
 int a;
 int b;
} summanden;

int Addiere(summanden param)
{
 return param.a+param.b;
}

Funktionsaufruf:
summanden test1 = {1,2};
Addiere(test1); // funktioniert
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:
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.

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Niklas Gürtler (erlkoenig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Makro.
summanden s;
#define ADD(a,b) s.a = (a); s.b = (b); Addiere (s);
ADD (5, 3);
ADD (42, 4);

Autor: Sven P. (haku) Benutzerseite
Datum:

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

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

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

Autor: Niklas Gürtler (erlkoenig)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Addiere({4,5}); // funktioniert NICHT, warum?

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

Oliver

Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

struct summanden
{
 int a;
 int b;

 summanden( int a_, int b_ ) : a( a_ ), b( b_ )  {}
};

int Addiere( const summanden & param )
{
 return param.a + param.b;
}

int main()
{
   Addiere( summanden( 5, 4 ) );
}

Noch besser allerdings wäre es, C++ nicht als verkapptes C zu benutzen
struct summanden
{
 int a;
 int b;

 summanden( int a_, int b_ ) : a( a_ ), b( b_ )  {}
 int Add() const { return a + b; }
};

int main()
{
  summanden test1( 1, 2 );
  int res1 = test1.Add();
  int res2 = summanden( 4, 5 ).Add();
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
enum UnitTypes {
   EINWERT,
   ZWEIWERT,
   DREIWERT
};

stuct Units
{
  std::string  text;
  UnitTypes    type;

  Units( const std::string & text_, UnitTypes type_ )
  : text( text_ ),
    type( type_ )
  {
  }
}

int main()
{
  std::list< Units > Liste;

  Liste.push_back( Units( "einwert", EINWERT ) );
  Liste.push_back( Units( "zweiwert", ZWEIWERT ) );
  Liste.push_back( Units( "dreiwert", DREIWERT ) );
}

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'

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.)

Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.