mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Funktion mit mehreren Ausgängen


Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Heute würde mir gesagt das man es tunlichst vermeiden sollte Funktionen 
mit mehreren Ausgängen zu Programmieren und die dies tut sind schlechte 
Programmier!
was sagt ihr zu diesen Thema?

Zum Beispiel:
int funktionXYZ(void)
{
   if(yxz)
     return 0;
   ...
   ...
   if(abc)
     return iVar;

   return 12;
}

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:

> Heute würde mir gesagt das man es tunlichst vermeiden sollte Funktionen
> mit mehreren Ausgängen zu Programmieren und die dies tut sind schlechte
> Programmier!

Bloedsinn. Solche Pauschalaussagen kommen immer von schlechten 
Programmierern. Richtig ist immer das, was leichter zu ueberblicken und 
zu verstehen ist - das kann mal diese, mal jene Variante sein.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja

Wobei der obige Quelltext auch kein Schmuckstück ist.

Autor: Nils S. (kruemeltee) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wobei der obige Quelltext auch kein Schmuckstück ist.
Und das machst du woran fest?
Ein switch/case würde hier nichts bringen, sind zwei verschiedene 
Variablen die abgefragt werden.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Funktion sollte ja nur verdeutlichen was ich meine.

Er hat underanderen noch eine schöne Begründung gesagt.
- Es geht auch nicht im Struktogramm!

Hab mit Ihn auch erst ma diskutiert aber hat leider nix gebracht.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nils S. schrieb:
>>Wobei der obige Quelltext auch kein Schmuckstück ist.
> Und das machst du woran fest?
> Ein switch/case würde hier nichts bringen, sind zwei verschiedene
> Variablen die abgefragt werden.

Nein, von switch habe ich hier nicht geträumt.
Was mich etwas daran stört, ist der Umstand, daß von den
drei returns genau eines ausgeführt wird; das drückt sich aber
nicht offensichtlich in der Struktur aus.
Wenn man mehrere formal unabhängige if hat, von denen aber
maximal eines erfüllt sein kann, dann erfordert das beim
Erfassen einen zusätzlichen Denkschritt.
Mit if - else if - else wird es dagegen klar ausgedrückt.

Deshalb fände ich etwas in dieser Art logischer:
int funktionXYZ(void)
{
   if(yxz)
   {
      return 0;
   }
   else if(abc)
   {
      return iVar;
   }
   else
   {
      return 12;
   }
}

Nur um die Nachfrage zu beantworten; eigentlich tut es hier nichts
zur Sache ist und ist auch nicht besonders relevant...

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja aber du hast auch 3 return leut der Aussage von meinen Lehrer darf 
man in einer Funktion max 1 return haben.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das is total banane, der erste return, der ausgeführt wird, beendet die 
Funktion, scheiß egal wieviele andere noch kommen.
Mein Proggenprof steht auch drauf sowas zu schreiben:

int abs(int x) //Absoluter Betrag
{
  if(x<0)
     return x;
  return -x;
}

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vorzeichenfehler, habs grad nach dem Abschicken gemerkt ;-)

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach, das ist wieder so eine Sache mit Theorie und Praxis.
Schau dir mal das an:
int foo(void) {
  int res = 0;
  
  res = a();
  if (!res) {
    res = b();
    if (!res) {
      res = c();
    }
  }
  return res;
}
Und dann das:
int foo(void) {
  int res = 0;

  res = a();
  if (res) return res;

  res = b();
  if (res) return res;

  res = c();
  return res;
Was ist nun wohl übersichtlicher? Auch bei mehrfach geschachtelten 
Schleifen oder switch()-Statements ist es ganz praktisch, wenn man im 
Fehlerfall direkt den Notausgang nehmen kann und sich nicht erst mit 
Flags und breaks durch alle Blöcke hangeln muss.
Bei Code, der z.B. Aufräumarbeiten erfordert ist es aber durchaus 
sinnvoll, nur ein Funktionsende zu haben.

Autor: xy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In den MISRA Richtlinien wird gefordert das die Funktionen nur einen 
Ausgang haben dürfen. Bei Sicherheitsrelevanter Software ist das so.

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> Er hat underanderen noch eine schöne Begründung gesagt.
> - Es geht auch nicht im Struktogramm!

Doch, das geht (natürlich(sic!)), zumindest in anständigen welchen, z.B. 
in Nassi-Shneiderman aka DIN 66261 :-) Man muss dazu nur wissen, dass 
(z.B.)
if b then
   block1
   return1
fi
block2
return2
semanitsch äquivalent ist mit
if b then
   block 1
   return1
else
   block2
   return2
fi
und das wiederum ist semantisch äquavalent mit
declare new __return_var
if b then
   block1
   __return_var := val1
else
   block2
   __return_var := val2
fi
return __return_var
Man muss also nur die impliziten 'else'-Zweige ins Diagramm aufnehmen. 
Bei switch/case läufts analog. ..und damit iss da Kaas bissn. (Und nein 
ich werde hier jetzt nicht den Smallstep-Beweis für die semantische 
Äquivalenz runterbeten, Beweis durch Offensichtlichkeit muss langen..).

Und zum Thema wann man was nimmt: Das hängt entscheidend von der 
Lesbarkeit ab. Extrem dienlich an dieser Stelle kann Code der folgenden 
Form sein - da wären tiefverschachtelte ifs zwar semantisch völlig 
äquivalent, aber fürs Verständnis halt extrem kontraproduktiv:
if b1
   trace (error b1)
   return ERROR_b1
if b2
   trace (error b2)
   return ERROR_b2
..
if bn
   trace (error bn)
   return ERROR_bn

return some_value
Zum Vergleich:
declare new __return_var
if b1
   trace (error b1)
   __return_var := ERROR_b1
else if b2
      trace (error b2)
      __return_var := ERROR_b2
..
                                    if bn
                                       trace (error bn)
                                       __return_var := ERROR_bn
                                    fi
                                 fi
                              fi
                           fi
..
   fi
fi

return __return_var

HTH

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was ist an MISRA so toll, außer daß einige Leute MISRA toll finden?

Wenn man sich mit einem scharfen Messer in den Finger schneiden kann,
essen wir die Kuh lieber in einem Stück.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> Ja aber du hast auch 3 return leut der Aussage von meinen Lehrer darf
> man in einer Funktion max 1 return haben.

So weltfremden Unfug können nur Pauker abschwallen. Und daß es nichts 
nutzt, mit so einen Scholastiker zu diskutieren, ist selbstredend...

Wie andere schon geschrieben haben: Es kommt auf Übersichtlichkeit und 
leichte Durchschaubarkeit am.

Und den, der in der Praxis Struktogramme benutzt, den möchte ich 
sehen.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich, aber nur gelegentlich zugegebenermaßen

Ob du mich sehen willst steht auf einem anderen Blatt :-)

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Und was ist an MISRA so toll, außer daß einige Leute MISRA toll finden?

Na es kostet was, alles was was kostet, das ★muss★ einfach toll sein 
;-))

Autor: Gast88 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also wie schon einige hier geschrieben haben, sollte man das IMO eher 
pragmatisch sehen. Wenn man return vernünftig anwendet, leidet die 
Übersichtlichkeit nicht. Dagegen kann es schnell verkrampft wirken, wenn 
man unbedingt die Regel, nur einen Ausgang zu nehmen, einhalten will. 
Ich wollte die Regel auch mal befolgen, habe aber schnell festgestellt, 
dass vernünftig eingesetzte return-Anweisungen viel übersichtlicher 
sind. Warum die Regel "nur ein Ausgang" bessere Programme ergeben soll, 
sehe ich ehrlich gesagt nicht, zumindest nicht in der Praxis.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist wie mit "niemals goto": es ist etwas Wahres dran in den
meisten Fällen, aber mit Verstand verwendet ist es manchmal doch
besser.

Wie mit vielen Ideologien halt.

Ich oute mich bei dieser Gelegenheit: Vor drei oder vier Jahren
habe ich auch goto benutzt, und halte es nach wie vor für richtig...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich finde das mehrfache Return schon äußerst nützlich, weil ja leider 
die C-Erfinder das Break einer Schleife auch unbedingt für das Switch 
mißbrauchen mußten.
Daher gehen mehrere Abbruchbedingungen einer Schleife übersichtlich 
geschrieben nur mit Returns:

  for( u; v; w){
     //... code
     switch( x ){
       case a: return b;
       case c: return d;
       // ... usw.
     }
  }

Ich schließe mich daher an, Verstehbarkeit geht vor Dogmatismus.

Peter

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich schließe mich daher an, Verstehbarkeit geht vor Dogmatismus.
Neben Lesbarkeit gibt es noch einen Grund das return gezielt 
einzusetzen: Optimierung der Laufzeit.

Gruß,
Nils

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Das ist wie mit "niemals goto": es ist etwas Wahres dran in den
> meisten Fällen, aber mit Verstand verwendet ist es manchmal doch
> besser.

Hast du schon mal versucht, aus einer inneren Schleife eine umschießende 
Schleife zu verlassen?

Ohne goto kommt ein entsetzlicher Krampf dabei raus.

Es gibt in C wenige, aber durchaus gute Gründe, goto zu benutzen

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nils schrieb:
> Neben Lesbarkeit gibt es noch einen Grund das return gezielt
> einzusetzen: Optimierung der Laufzeit.

Das glaube ich nun weniger. Heutige Optimizer sind clever genug, auch 
anders optimalen Code zu erzeugen - der hat nämlich keine Jump-Phobie 
und das Geschwätz von Paukern ist ihm sowieso wurscht...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler macht immer sein eigenes Ding, egal wieviel Returns und an 
welcher Stelle.

Auch wenn Du nur ein Return im Code hast, aber mehrere 
Abbruchbedingungen, dann kann er mehrere Returns draus machen.

Und wenn Du mehrere Returns hast, aber lokale Variablen aufm Stack, dann 
springt er von allen an das einzige Return am Ende, wo der Stack 
aufgeräumt wird.


Peter

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weis nicht, ob man solche Pauker mit Normen
beeindrucken kann, aber in der ISO/IEC 9899:TC3
steht:
6.8.6.4 The return statement
Constraints
1 A return statement with an expression shall not appear in a function whose return type
is void. A return statement without an expression shall only appear in a function
whose return type is void.
Semantics
2 A return statement terminates execution of the current function and returns control to
its caller. A function may have any number of return statements.
3 If a return statement with an expression is executed, the value of the expression is
returned to the caller as the value of the function call expression. If the expression has a
type different from the return type of the function in which it appears, the value is
converted as if by assignment to an object having the return type of the function.139

Punkt 2 sollte reichen (wenn er Englisch kann).

Sonst mit dem ganzen Wälzer (552 Seiten, 3700 KB)
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
erschlagen ;)

avr

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja, ich bin kein Fan von 1000 versteckten return irgendwo.

Aber was ein C-Compiler im Extremfall können muß, und was als
elegantes Programmieren bezeichnet wird, ist nicht ganz deckungsgleich.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da hast du recht. Es ist wie mit einem Küchenmesser: man kann ein tolles 
Menü damit zubereiten, oder die Schwiegermutter abstechen...

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eingesehen!
Das Menü wäre nur ein kurzfristiges Vergnügen.

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Uhu, Peter

> Heutige Optimizer sind clever genug, ...
> Der Compiler macht immer sein eigenes Ding, egal wieviel Returns und an welcher 
Stelle...

Ok. Würdet Ihr soweit gehen zu sagen, dass solche Codeoptimierungen 'von 
Hand' bei heutigen C-Compilern nichts bringen?

Nils

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nils schrieb:

> Ok. Würdet Ihr soweit gehen zu sagen, dass solche Codeoptimierungen 'von
> Hand' bei heutigen C-Compilern nichts bringen?

Das musst du fallweise testen. Und mit der naechsten Compilerversion 
kann es wieder anders sein. Man sollte sich also vor Optimierungen gut 
ueberlegen, ob man sie wirklich braucht. Bei groesseren Projekten steckt 
meist sowieso mehr Optimierungspotential in den Algorithmen und der 
Architektur als in einzelnen Codebloecken.

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:

> Bei groesseren Projekten steckt
> meist sowieso mehr Optimierungspotential in den Algorithmen und der
> Architektur als in einzelnen Codebloecken.

Ja, das stimmt. Guter Hinweis - wahrscheinlich sollte man sich 
tatsächlich das Gesamtdesign ins Gedächnis rufen, anstatt in solchen 
Blöcken zu optimieren.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nils schrieb:
> Ok. Würdet Ihr soweit gehen zu sagen, dass solche Codeoptimierungen 'von
> Hand' bei heutigen C-Compilern nichts bringen?

Ja, so ist es. Die Compiler können das meist so gut, daß man selbst als 
Assemblerprogrammierer seine liebe Not hat, mitzuhalten. (Vom 
Zeitaufwand gar nicht zu reden.)

Allerdings ist das meistens nur eine lokale Optimierung innerhalb einer 
Funktion. Der entgehen natürlich Design-Dummheiten und genau da kann man 
als Programmierer durch gut durchdachte Struktur und vor allem 
effiziente Algorithmen sehr viel herausholen.

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Uhu Uhuhu, Peter S., Peter D.:
Danke für Euren Einwand auf meine Antwort und Eure Erklärungen - wieder 
was gelernt, danke!

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.