Forum: Mikrocontroller und Digitale Elektronik Art der if-Auswahl nur Geschmackssache?


von __Son´s B. (bersison)


Lesenswert?

Hallo!
Habe hier 2 Lösungen für die selbe Aufgabe.
Ist es "reine Geschmackssache", oder gibt es bei der einen oder anderen 
Lösung ernsthafte Einwände?
1
//_1________________________________________
2
void EnergieRestAmpel(uint16_t RestZeit)
3
{
4
if(RestZeit >= ENERGIE_SCHWELLE_OBEN)
5
{
6
 LED_ENERGIE_GN_ON;              
7
 return;
8
}
9
if(RestZeit <= ENERGIE_SCHWELL_UNTEN)
10
{
11
 LED_ENERGIE_RT_ON;              
12
 return;
13
}
14
 LED_ENERGIE_GE_ON;              
15
}
16
17
//_2_________________________________________
18
void EnergieRestAmpel(uint16_t RestZeit)
19
{  
20
uint8_t Prio=3;
21
if(RestZeit >= ENERGIE_SCHWELLE_OBEN)  Prio=2;
22
if(RestZeit <= ENERGIE_SCHWELL_UNTEN)  Prio=1;
23
  
24
switch(Prio)
25
{
26
case 1:
27
 LED_ENERGIE_RT_ON;  
28
 break;
29
case 2:
30
 LED_ENERGIE_GN_ON;    
31
 break;
32
default:
33
 LED_ENERGIE_GE_ON;    
34
}
35
}
___________________________________________
Ich persönlich favorisiere die switch-Lösung aufgrund der tabellarischen 
Übersicht. Vor allem wenn mehr als 2 Vergleiche erfolgen. Nur muss 
einmalig die Priorität (von unten nach oben) festgelegt werden.

: Bearbeitet durch Moderator
von Walter T. (nicolas)


Lesenswert?

Such es Dir aus. Implementiere es. Du wirst im Laufe Deine Projekts 
ohnehin noch das eine oder andere mehrmals ändern, weil Dir am Anfang 
jede Woche die Vorteile der einen oder der anderen Lösung mehr liegen.

von ... (Gast)


Lesenswert?

void EnergieRestAmpel(const uint16_t RestZeit)
{
   if(RestZeit >= ENERGIE_SCHWELLE_OBEN)
      LED_ENERGIE_GN_ON;
   else if(RestZeit <= ENERGIE_SCHWELL_UNTEN)
      LED_ENERGIE_RT_ON;
   else
      LED_ENERGIE_GE_ON;
}

Natürlich müssen diese sinnlosen #defines ordentlich aussehen.
Sinnlos, weil man dafür auch einfach Funktionen nutzen kann.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

__Son´s B. schrieb:
1
void EnergieRestAmpel(uint16_t RestZeit)
2
{
3
if(RestZeit >= ENERGIE_SCHWELLE_OBEN)
4
{
5
 LED_ENERGIE_GN_ON;
6
 return;
7
}
8
if(RestZeit <= ENERGIE_SCHWELL_UNTEN)
9
{
10
 LED_ENERGIE_RT_ON;
11
 return;
12
}
13
LED_ENERGIE_GE_ON; // <= here
14
}
Lies das nochmal. Überlege welchen Sinn die Kombination >= und <= macht. 
Und wie oft die markierte zeile ausgeführt wird.

Hint: findige Software-Ingenöre haben "else" erfunden

von Possetitjel (Gast)


Lesenswert?

Michael R. schrieb:

> Lies das nochmal. Überlege welchen Sinn die Kombination
> >= und <= macht. Und wie oft die markierte zeile ausgeführt
> wird.

???

Zuviel Blut im Kaffee?

Die markierte Zeile wird ausgeführt, wenn RestZeit (echt)
kleiner als ENERGIE_SCHWELLE_OBEN, aber noch (echt) größer
als ENERGIE_SCHWELLE_UNTEN ist.

von Thomas H. (beon)


Lesenswert?

Im Endeffekt machen beide Codes das Gleiche. Meiner Meinung nach ist es 
Geschmackssache. Zitat von einem unserer Informatiker: "Code soll für 
einen selbst übersichtlich und lesbar sein. Optimierung macht der 
Compiler".

von Matthias M. (Firma: privat) (quadraturencoder)


Lesenswert?

switch() case statements sind normalerweise für Auflistungen gedacht. 
Mit enums kann man so z.B. eine Warnung generieren, wenn das 'case' 
Statement für einen später eingefügten Fall fehlt. Sehr hilfreich.

Dein Codebeispiel ist ok, aber das 'return' mitten im Code is Spaghetti 
und sollte vermieden werden. Wenn Du Jahre später mal am Ende der 
Funktion code hinzufügst könntest Du das eventuell übersehen.

IMHO ist es so besser:

void EnergieRestAmpel(uint16_t RestZeit)
{
  if (RestZeit >= ENERGIE_SCHWELLE_OBEN)
  {
    LED_ENERGIE_GN_ON;
  }
  else if(RestZeit <= ENERGIE_SCHWELL_UNTEN)
  {
    LED_ENERGIE_RT_ON;
  }
  else
  {
    LED_ENERGIE_GE_ON;
  }
}

Die geschwungenen Klammern kannst DU dann auch weglassen, und die Idee, 
die hinter der Formel steckt wird offensichtlicher. So würdest Du das 
Problem umgangssprachlich wohl auch ausdrücken: Wenn die Restzeit 
grösser ist, dann mach das, ansonsten wenn die Zeit kleiner ist, mach 
jenes, und wenn keines der beiden zutrifft, mach sonstwas.

von Peter D. (peda)


Lesenswert?

Der GCC erlaubt auch Switch mit Bereichen:
1
switch(RestZeit)
2
{
3
  case 0 ... ENERGIE_SCHWELL_UNTEN:
4
    LED_ENERGIE_RT_ON;
5
    break;
6
  case ENERGIE_SCHWELL_UNTEN + 1 ... ENERGIE_SCHWELLE_OBEN:
7
    LED_ENERGIE_GN_ON;
8
    break;
9
  default:
10
    LED_ENERGIE_GE_ON;
11
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Michael R. schrieb:
> Lies das nochmal.

Dito. Man könnte kritisieren, das die obere Schwelle 
'ENERGIE_SCHWELLE_OBEN' heisst, während die untere 
'ENERGIE_SCHWELL_UNTEN' heisst, da hat der Autor eben SCHWELL statt 
SCHWELLE geschrieben. Das ist aber auch schon alles. Zwischen den 
Schwellen passiert nun mal nichts.

von Possetitjel (Gast)


Lesenswert?

__Son´s B. schrieb:

> Habe hier 2 Lösungen für die selbe Aufgabe.
> Ist es "reine Geschmackssache",

Fast, aber nicht ganz, würde ich sagen.

> Ich persönlich favorisiere die switch-Lösung aufgrund
> der tabellarischen Übersicht. Vor allem wenn mehr als
> 2 Vergleiche erfolgen.

Ja.
Die zweite Variante ist ein ziemlich universelles Muster,
wie man M Variablen auf N Fallklassen abbilden kann. Die
if-Abfragen oben ermitteln erstmal die Fallnummer; der
switch ruft dann den Handler für den jeweiligen Fall auf.
Ich verwende das immer dann, wenn ich eine einigermaßen
feststehende, a priori bekannte Anzahl von Fällen habe,
aus denen zu jedem Zeitpunkt genau einer zutrifft.

Die erste Konstruktion benutze ich für Abläufe (endliche
Automanten, "state machines"). In der Steuerungstechnik
kennt (kannte) man das als Schrittkette (Ablaufkette).
Hier kann man ziemlich viele Zustände haben, deren Anzahl
sich auch mal ändern kann; ich will dann kein switch
haben, was über mehrere Seiten geht.

Geschachtelte if-then-else verwende ich nie, dazu ist
mein IQ zu niedrig.

von Tom (Gast)


Lesenswert?

Was Du tust, ist 1) aus der RestZeit ein "Warnlevel" zu generieren und 
2) das WarnLevel anzuzeigen.

Wenn man das übertrieben sauber trennen will, könnte man zuerst die 
RestZeit in irgendeinen abstrakten Zustand übersetzen und dann diesen 
irgendwie anzeigen. Dein zweiter Ansatz geht ein wenig in diese 
Richtung, wobei mir die "Priorität" nicht ganz klar ist.
1
// energy_analysis.h + .c
2
typedef enum {ENERGY_OK, ENERGY_WARNING, ENERGY_CRITICAL} eEnergyState;
3
4
eEnergyState classify_energy_level(uint16_t RestZeit)
5
{
6
    if(RestZeit >= ENERGIE_SCHWELLE_OBEN)
7
        return ENERGY_OK;
8
    if(RestZeit <= ENERGIE_SCHWELL_UNTEN)
9
        return ENERGY_CRITICAL;
10
    return ENERGY_WARNING;
11
}
12
13
// hmi.h + .c
14
void displayEnergyLevel(eEnergyState e)
15
{
16
    switch(e)
17
    {
18
    case ENERGY_OK: LED_ENERGIE_GN_ON; break;
19
    case ENERGY_WARNING: LED_ENERGIE_GE_ON; break;
20
    case ENERGY_CRITICAL: LED_ENERGIE_RT_ON; break;
21
    }
22
}
23
24
// main.c
25
void DoTheAmpel(uint16_t RestZeit)
26
{
27
    eEnergyState s = classify_energy_level(RestZeit);
28
    displayEnergyLevel(s);
29
}
In diesem einfachen Fall ist das wahrscheinlich in dieser Form Quatsch. 
Wenn es groß und kompliziert wird, macht man sich aber das Leben auf 
Dauer einfacher, wenn man Aufgaben strikt auf Module aufteilt und 
Querabhängigkeiten zwischen diesen vermeidet.

von Peter D. (peda)


Lesenswert?

Possetitjel schrieb:
> Geschachtelte if-then-else verwende ich nie, dazu ist
> mein IQ zu niedrig.

Geht mir auch so.
Ich finde die extrem unlesbar.

von Karl (Gast)


Lesenswert?

Peter D. schrieb:
> Ich finde die extrem unlesbar.

Mit einer ordentlichen Programmiersprache sind die auch gut lesbar. Darf 
man halt nicht diesen Klammermist nehmen.

Thomas H. schrieb:
> Im Endeffekt machen beide Codes das Gleiche.

Die Varianten kompilieren durchaus unterschiedlich. Bei if ... else 
stehen die auszuführenden Anweisungen direkt hinter dem Vergleich, dann 
folgt der nächste Vergleich. Bei case stehen alle Vergleiche zusammen, 
von dort wird zu den auszuführnenden Anweisungen gesprungen.

Ich hab auch schon ein Kompilat gesehen, wo ein case mit aufsteigender 
Nummerierung (also a = 1, 2, 3) derart aufgelöst wurde, dass anhand a 
eine Adresse einer Lookup-Table berechnet wurde, in der dann die 
Sprungadresse zum auszuführenden Code stand. Das geht aber nur mit 
Aufzählungen, nicht mit Bereichen oder <> Vergleichen.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Possetitjel schrieb:
> Zuviel Blut im Kaffee?
>
> Die markierte Zeile wird ausgeführt, wenn RestZeit (echt)
> kleiner als ENERGIE_SCHWELLE_OBEN, aber noch (echt) größer
> als ENERGIE_SCHWELLE_UNTEN ist.

Ja. zuviel Blut im Kaffee ;-) sorry, überlesen

von W.A. (Gast)


Lesenswert?

Michael R. schrieb:
> Lies das nochmal. Überlege welchen Sinn die Kombination >= und <= macht.

Lies das nochmal.
ENERGIE_SCHWELLE_OBEN und ENERGIE_SCHWELL_UNTEN sind vermutlich 
verschieden.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

W.A. schrieb:
> Lies das nochmal.
> ENERGIE_SCHWELLE_OBEN und ENERGIE_SCHWELL_UNTEN sind vermutlich
> verschieden.

Ja, schon gut :-) hab das analysiert. Mein Brain 1.9.68 hat Erkennung 
von Wörtern in GROSSBUCHSTABEN auf char[15] definiert.

Und wo krieg ich jetzt ein Update her? Cheffe mein, 2.0 wäre nicht, zu 
viele Subsysteme die das nicht mitmachen...

von Egon N. (egon2321)


Lesenswert?

Peter D. schrieb:
> Possetitjel schrieb:
>> Geschachtelte if-then-else verwende ich nie, dazu ist
>> mein IQ zu niedrig.
>
> Geht mir auch so.
> Ich finde die extrem unlesbar.

Else If hat aber den Vorteil, dass man sofort sieht, dass sich beide 
Segmente ausschließen.

Das ist mit zwei If hintereinander nicht sauber definiert.

Die Switch Case mit der vorherigen If Abfrage ist meiner Meinung nach 
unschön, fehleranfällig und unübersichtlich. Es sollte zu jeder Zeit 
klar sein was passiert, sprich man sollte grob die Funktion erkennen 
können obwohl man maximal Zeile+-1 sieht.

BTW: Ich bin kein Fan von deutschen Bezeichnungen. ein UPPER_LIMIT bzw. 
LOWER_LIMIT ist da schöner, kann man auch noch abkürzen usw. Energie 
z.B. mit E reinnehmen. 40 Zeichen lange Defines will man ehrlich gesagt 
nicht.

: Bearbeitet durch User
von Jobst Q. (joquis)


Lesenswert?

__Son´s B. schrieb:
> Ist es "reine Geschmackssache", oder gibt es bei der einen oder anderen
> Lösung ernsthafte Einwände?

Nicht nach meinem Geschmack ist auf jeden Fall das

> LED_ENERGIE_RT_ON;

Was soll das sein? Eine Konstante wie die meisten #defines ist es 
jedenfalls nicht. Damit sich überhaupt etwas tut, muss es wohl eine 
Funktion sein.
Dann würde ich das aber zumindest kenntlich machen:

LED_ENERGIE_RT_ON ();

Noch besser fände ich es allerdings, Funktionen nicht hinter #defines zu 
verstecken.

von Hunsbuckel (Gast)


Lesenswert?

Mit den ganzen -wo auch immer- deklarierten und initialisierten 
Variablen und Funktionen ( wie JoQuis schon zutreffend anmerkte ) kann 
das sowieso keine Sau richtig lesen!

Ich nenne sowas blah - blah - Code !!!

von Possetitjel (Gast)


Lesenswert?

Egon N. schrieb:

> Peter D. schrieb:
>> Possetitjel schrieb:
>>> Geschachtelte if-then-else verwende ich nie, dazu ist
>>> mein IQ zu niedrig.
>>
>> Geht mir auch so.
>> Ich finde die extrem unlesbar.
>
> Else If hat aber den Vorteil, dass man sofort sieht,
> dass sich beide Segmente ausschließen.
>
> Das ist mit zwei If hintereinander nicht sauber definiert.

Da ich durch Tcl geprägt bin, würde ich sowieso in jedem
Fall schreiben:

if(bedingung1) {
  aktion;
}

if(bedingung2) {
  andere_aktion;
}

Nach meinem laienhaften Verständnis der C-Syntax müsste das
eindeutig sein.
Das sind halt zwei isolierte Statements und gut.

Das Problem bei if/elseif ist, dass es zwar syntaktisch
eine Anweisung bleibt, man aber mehrere unabhängige
Bedingungen abprüfen kann, und das ist Teufelswerk.

Ganz spaßig wird es, wenn man in den then-Zweigen weitere
if-Abfragen unterbringt -- das ist dann genau der Fall,
den Peter als unlesbar bezeichnet.

> Die Switch Case mit der vorherigen If Abfrage ist meiner
> Meinung nach unschön, fehleranfällig und unübersichtlich.

Da bin ich eben komplett anderer Meinung.

Ein Problem, bei dem M Variablen zu N unterschiedlichen
Fällen führen, ist schon rein inhaltlich immer ein großer
Matschklumpen.
Ich finde es bei dieser Konstellation gut, erstmal zu
ermitteln "Welcher Fall liegt eigentlich vor?" (das passiert
in dem Block mit den if-Abfragen), und wenn man das weiss,
kann man den Fall anhand der Fallnummer behandeln, das macht
die switch-Anweisung.

Die Schnittstelle zwischen beiden besteht nur in der Fallnummer.

> Es sollte zu jeder Zeit klar sein was passiert, sprich man
> sollte grob die Funktion erkennen können obwohl man maximal
> Zeile+-1 sieht.

Das ist zwar wünschenswert, aber nicht realistisch.

von A. S. (Gast)


Lesenswert?

Hier ist die erste Lösung deutlich kürzer.

Die zweite benötigt ein weiteres Token (Prio).

Prinzipiell ist die zweite okay, hier bläht sie unnötig auf.

von S. R. (svenska)


Lesenswert?

Possetitjel schrieb:
> Da ich durch Tcl geprägt bin, würde ich sowieso in jedem
> Fall schreiben:
>
> if(bedingung1) {
>   aktion;
> }
>
> if(bedingung2) {
>   andere_aktion;
> }

Wenn "bedingung1" und "bedingung2" sich nicht gegenseitig ausschließen, 
dann werden beide Aktionen ausgeführt. Das ist nicht überall gewünscht, 
insbesondere hier nicht.

Außerdem muss in deinem Code "bedingung2" auch dann ausgewertet werden, 
wenn "bedingung1" schon zutraf.

von Axel S. (a-za-z0-9)


Lesenswert?

__Son´s B. schrieb:
> Ich persönlich favorisiere die switch-Lösung aufgrund der tabellarischen
> Übersicht.

Ich nicht. Ich finde es im Gegenteil vollkommen bescheuert, erst eine 
Hilfsvariable per if-Kaskade zu setzen und dann ein switch() Statement 
zur Auswertung der Hilfsvariable zu verwenden. Das führt garantiert zu 
längerem Code und ist kein bißchen übersichtlich, weil man jetzt an 
zwei Stellen nachsehen muß - wo die Hilfsvariable gesetzt wird und wo 
sie ausgewertet wird.

Persönlich würde ich das als if .. else if ... else if ... else Kaskade 
schreiben. Vernünfig eingerückt und geklammert ist das sehr gut lesbar - 
zumindest so lange alles auf einen Bildschirmseite paßt. Das 
standardmäßige switch() Statement paßt halt nicht, weil das nur gegen 
Konstanten vergleichen kann. Auf eine gcc-Erweiterung sollte man im 
Sinne der Portabilität verzichten.

Wenn es nicht auf eine Seite paßt; etwa weil doch mehr Code nach jedem 
if kommt, und wenn das tatsächlich so verkapselt ist, daß es keinen 
gemeinsamen Code nach der Verzweigung gibt, dann ist die Variante mit 
abgeschlossenen if () { ...; return; } Blöcken auch ok. Das Argument 
"Spaghetti" greift hier nicht, denn es geht ja nur darum, einen 
Codeblock (den Funktionsrumpf) geordnet zu verlassen.

von Possetitjel (Gast)


Lesenswert?

S. R. schrieb:

> Possetitjel schrieb:
>> Da ich durch Tcl geprägt bin, würde ich sowieso in jedem
>> Fall schreiben:
>>
>> if(bedingung1) {
>>   aktion;
>> }
>>
>> if(bedingung2) {
>>   andere_aktion;
>> }
>
> Wenn "bedingung1" und "bedingung2" sich nicht gegenseitig
> ausschließen, dann werden beide Aktionen ausgeführt. Das
> ist nicht überall gewünscht, insbesondere hier nicht.

???

(Achtung -- kein C, sondern Tcl:)
1
 
2
set RestLaufzeit 0 
3
4
if { $RestEnergie >= ENERGIE_SCHWELLE_UNTEN } then { 
5
  set RestLaufzeit 1 
6
} 
7
8
if { $RestEnergie >= ENERGIE_SCHWELLE_OBEN } then { 
9
  incr RestLaufzeit 
10
}

Ich sehe das Problem nicht.


> Außerdem muss in deinem Code "bedingung2" auch dann
> ausgewertet werden, wenn "bedingung1" schon zutraf.

Selbstverständlich. Soll ja.

von Possetitjel (Gast)


Lesenswert?

Axel S. schrieb:

> Ich finde es im Gegenteil vollkommen bescheuert, erst
> eine Hilfsvariable per if-Kaskade zu setzen und dann
> ein switch() Statement zur Auswertung der Hilfsvariable
> zu verwenden.

Steht Dir frei. Alles kann, nichts muss ;)


> Das führt garantiert zu längerem Code

Mag sein -- aber auch zu intakteren Zähnen und Tischkanten.
(Zumindest bei mir.)


> und ist kein bißchen übersichtlich,

Sehr mutig, dass Du so genau weisst, was ich übersichtlich
finde.


> weil man jetzt an zwei Stellen nachsehen muß - wo die
> Hilfsvariable gesetzt wird und wo sie ausgewertet wird.

Das ist für mich keine echte Komplikation.

In wirklich richtig komplizierten Fällen -- und nur über
die lohnt es sich zu diskutieren -- muss ich sowieso über
zwei getrennte Fragen nachdenken:

1. Woran erkenne ich den jeweiligen Fall?
2. Welche Aktion ist im jeweiligen Fall notwendig?

Der Quelltext widerspiegelt somit nur, wie mein Gehirn
funktioniert.


> Persönlich würde ich das als if .. else if ... else if ... else
> Kaskade schreiben. Vernünfig eingerückt und geklammert ist
> das sehr gut lesbar - zumindest so lange alles auf einen
> Bildschirmseite paßt.

Im konkreten Beispiel stimmt das -- weil sich nämlich beide
Bedingungen auf dieselbe Variable beziehen. Es ist also aus
inhaltlichen Gründen sowieso sichergestellt, dass sich die
Fälle gegenseitig ausschließen.

Wenn mehrere Variablen mit voneinander abhängigen Bedingungen
eine Rolle spielen, ist das aber keineswegs mehr so.

von Karl (Gast)


Lesenswert?

Possetitjel schrieb:
> Nach meinem laienhaften Verständnis der C-Syntax müsste das
> eindeutig sein.
> Das sind halt zwei isolierte Statements und gut.

Nach meinem Verständnis ist das Schrott. Die Statements gehören im 
obigen Beispiel zusammen und dann kann man sie auch zusammen behandeln. 
Das in mehrere ifs aufzuteilen ist nur fehleranfällig.

> Das Problem bei if/elseif ist, dass es zwar syntaktisch
> eine Anweisung bleibt, man aber mehrere unabhängige
> Bedingungen abprüfen kann, und das ist Teufelswerk.

Isses schon so schlimm wie goto, oder nur so schlimm wie upn?

Der GROSSE Vorteil von if ... else ist, dass man damit sehr effizient 
Abfragen zusammenfassen kann, die der Compiler dann sehr effizient in 
Maschinencode umsetzt. Wer diesen Vorteil gerade auf µCs nicht nutzt, 
weil er davon Kopfschmerzen bekommt, sollte vielleicht besser Bäcker 
werden.

> Ganz spaßig wird es, wenn man in den then-Zweigen weitere
> if-Abfragen unterbringt -- das ist dann genau der Fall,
> den Peter als unlesbar bezeichnet.

Aus aktuellem Anlass:
1
procedure rtc_checksummer();
2
begin
3
  if rtc.summ and Rsauto <> 0 then begin  // prüfen auf Flag Auto
4
    if rtc.wday = 7 then begin  // wenn Sonntag
5
      if rtc.day >= $25 then begin  // wenn letzter Sonntag im Monat
6
        if rtc.month = $03 then begin  // wenn März, Umschalten auf Sommerzeit
7
          if (rtc.summ and Rsumm) = 0 then begin  //wenn Flag nicht gesetzt
8
            if rtc.hh = $02 then begin
9
              rtc.hh := $03;
10
              rtc.summ := Rsauto or Rsumm;
11
              rtc_setsummer();  // Sommerzeit schreiben
12
            end;
13
          end;
14
        end else if rtc.month = $10 then begin  // wenn Oktober, Umschalten auf Winterzeit
15
          if (rtc.summ and Rsumm) <> 0 then begin  //wenn Flag gesetzt
16
            if rtc.hh = $03 then begin
17
              rtc.hh := $02;
18
              rtc.summ := Rsauto;
19
              rtc_setsummer();  // Winterzeit schreiben
20
            end;
21
          end;
22
        end;
23
      end;
24
    end;
25
  end;
26
end;


Was bitte ist daran unlesbar? Und, schon Kopfschmerzen?

: Bearbeitet durch Moderator
von Possetitjel (Gast)


Lesenswert?

Karl schrieb:

> Possetitjel schrieb:
>> Nach meinem laienhaften Verständnis der C-Syntax müsste
>> das eindeutig sein.
>> Das sind halt zwei isolierte Statements und gut.
>
> Nach meinem Verständnis ist das Schrott.

Das ist keine sachlich begründete Aussage und daher nicht
hilfreich.


> Die Statements gehören im obigen Beispiel zusammen und
> dann kann man sie auch zusammen behandeln.

Das ist zwar richtig, aber eine Besonderheit des konkreten
Beispiels .

Es gibt jedoch Fälle, in denen das nicht so ist, und dann
ist die Formulierung als unabhängige Bedingungen nützlich.
Nichts anderes wollte ich ausdrücken.


>> Das Problem bei if/elseif ist, dass es zwar syntaktisch
>> eine Anweisung bleibt, man aber mehrere unabhängige
>> Bedingungen abprüfen kann, und das ist Teufelswerk.
>
> Isses schon so schlimm wie goto, oder nur so schlimm
> wie upn?

Was ist upn?

Davon abgesehen: Dein gutes Gedächtnis beeindruckt -- aber
ich bin nicht sicher, inwieweit Du verstehst, was Du liest.
Es gibt einen sachlichen Zusammenhang zwischen der goto-
Diskussion und dieser hier.
Das war mir gar nicht aufgefallen; ich danke für den
Hinweis.

> Der GROSSE Vorteil von if ... else ist, dass man damit
> sehr effizient Abfragen zusammenfassen kann, die der
> Compiler dann sehr effizient in Maschinencode umsetzt.

Irrelevant. Optimierende Compiler existieren. Du bist auf
dem Stand von vor 50 Jahren stehengeblieben.


> Aus aktuellem Anlass:procedure rtc_checksummer();
> begin
>   if rtc.summ and Rsauto <> 0 then begin  // prüfen auf Flag Auto
>     if rtc.wday = 7 then begin  // wenn Sonntag
>       if rtc.day >= $25 then begin  // wenn letzter Sonntag im Monat
>         if rtc.month = $03 then begin  // wenn März, Umschalten auf
> Sommerzeit
>           if (rtc.summ and Rsumm) = 0 then begin  //wenn Flag nicht
> gesetzt
>             if rtc.hh = $02 then begin
>               rtc.hh := $03;
>               rtc.summ := Rsauto or Rsumm;
>               rtc_setsummer();  // Sommerzeit schreiben
>             end;
>           end;
>         end else if rtc.month = $10 then begin  // wenn Oktober,
> Umschalten auf Winterzeit
>           if (rtc.summ and Rsumm) <> 0 then begin  //wenn Flag gesetzt
>             if rtc.hh = $03 then begin
>               rtc.hh := $02;
>               rtc.summ := Rsauto;
>               rtc_setsummer();  // Winterzeit schreiben
>             end;
>           end;
>         end;
>       end;
>     end;
>   end;
> end;
>
> Was bitte ist daran unlesbar? Und, schon Kopfschmerzen?

Das ist nicht nur unlesbar, das ist hässlich. Dabei wäre es
so einfach, es besser zu machen.
1
 
2
set SwitchToSummertime true 
3
... 
4
if { rtc.wday != 7 }  then { set SwitchToSummertime false } 
5
if { rtc.day < 25 }   then { set SwitchToSummertime false } 
6
if { rtc.month != 3 } then { set SwitchToSummertime false } 
7
...

Man kann ein wired-AND auf die unterschiedlichsten Arten
ausdrücken.

von Harlekin (Gast)


Lesenswert?

Possetitjel schrieb:
> set SwitchToSummertime true
> ...
> if { rtc.wday != 7 }  then { set SwitchToSummertime false }
> if { rtc.day < 25 }   then { set SwitchToSummertime false }
> if { rtc.month != 3 } then { set SwitchToSummertime false }
> ...

Danke. Wieder was gelernt.

Gibt es hierzu empfehlenswerte Bücher?

von Rolf M. (rmagnus)


Lesenswert?

Possetitjel schrieb:
> Das Problem bei if/elseif ist, dass es zwar syntaktisch
> eine Anweisung bleibt, man aber mehrere unabhängige
> Bedingungen abprüfen kann, und das ist Teufelswerk.

Warum?

>> Die Switch Case mit der vorherigen If Abfrage ist meiner
>> Meinung nach unschön, fehleranfällig und unübersichtlich.
>
> Da bin ich eben komplett anderer Meinung.

Ich finde sie nur unnötig aufgebläht. Es steht quasi doppelt da.

> Ich finde es bei dieser Konstellation gut, erstmal zu
> ermitteln "Welcher Fall liegt eigentlich vor?" (das passiert
> in dem Block mit den if-Abfragen), und wenn man das weiss,
> kann man den Fall anhand der Fallnummer behandeln, das macht
> die switch-Anweisung.

"Fallnummer"? Also wenn man das so macht, dann sollte man (ähnlich wie 
Tom es gezeigt hat) den Fällen auch Namen geben. Irgendwelche 
Magic-Numbers machen es alles andere als übersichtlicher. Dann muss ich 
beim Lesen des switch/case erst wieder oben nachschauen, welches 
Ergebnis der if-Abfrage denn nun zu Fall Nummer 3 gehört, was den 
Lesefluss meiner Meinung nach stark stört.

Possetitjel schrieb:
> In wirklich richtig komplizierten Fällen -- und nur über
> die lohnt es sich zu diskutieren -- muss ich sowieso über
> zwei getrennte Fragen nachdenken:
>
> 1. Woran erkenne ich den jeweiligen Fall?
> 2. Welche Aktion ist im jeweiligen Fall notwendig?
>
> Der Quelltext widerspiegelt somit nur, wie mein Gehirn
> funktioniert.

Hmm, dann funktionieren unsere Gehirne verschieden ;-)
Wenn ich das im Kopf durchgehen würde, würde ich sagen:

Wenn der Wert kleiner ist als die Untergrenze, dann soll die rote LED 
angehen. Wenn er stattdessen größer ist als die Obergrenze, soll die 
grüne LED angehen, und sonst die gelbe. Das würde der if/else-Kaskade 
entsprechen.
Die switch/case-Variante, die dann deiner Gehirnfunktion entsprechen 
müsste, würde ich so lesen:

Wenn nichts anderes gilt, haben wir Fall 3. Wenn der Wert kleiner ist 
als die Untegrenze ist, ist das Fall 1. Wenn er größer ist als die 
Obergrenze, ist das Fall 2.
In Fall 1 mache die rote LED an, in Fall 2 die grüne und in Fall 3 die 
gelbe.

Da hab ich ja im zweiten Satz schon vergessen, welcher Fall im ersten 
Satz welcher Bedingung zugeordnet war.

> Im konkreten Beispiel stimmt das -- weil sich nämlich beide
> Bedingungen auf dieselbe Variable beziehen. Es ist also aus
> inhaltlichen Gründen sowieso sichergestellt, dass sich die
> Fälle gegenseitig ausschließen.
>
> Wenn mehrere Variablen mit voneinander abhängigen Bedingungen
> eine Rolle spielen, ist das aber keineswegs mehr so.

Ja, ab einer gewissen Komplexität ist die Trennung durchaus sinnvoll. 
Aber zwingend ist für mich dann auch wieder, dass keine magischen 
Fallnummern verwendet werden, sondern aussagekräftige Bezeichnungen.

von __Son´s B. (bersison)


Lesenswert?

FAZIT:
Vielen Dank für die vielen konstruktiven Gedanken, Geschmäcker, 
Bemerkungen und Anregungen! Eure Ideen werden mich noch lange begleiten.
So macht Forum Spaß :-)

1| Rechtschreibfehler "SCHWELL vs. SCHWELLE" ist mir gar nicht 
aufgefallen...
2| Da es sich um nur 2(+1) Abfragen handelt, werde ich if/else ohne 
return verwenden.

von Axel S. (a-za-z0-9)


Lesenswert?

Possetitjel schrieb:
>> Persönlich würde ich das als if .. else if ... else if ... else
>> Kaskade schreiben. Vernünfig eingerückt und geklammert ist
>> das sehr gut lesbar - zumindest so lange alles auf einen
>> Bildschirmseite paßt.
>
> Im konkreten Beispiel stimmt das -- weil sich nämlich beide
> Bedingungen auf dieselbe Variable beziehen. Es ist also aus
> inhaltlichen Gründen sowieso sichergestellt, dass sich die
> Fälle gegenseitig ausschließen.
>
> Wenn mehrere Variablen mit voneinander abhängigen Bedingungen
> eine Rolle spielen, ist das aber keineswegs mehr so.

Doch. Bei einer if ... else if ... else if ... Kaskade ist 
sichergestellt daß maximal einer der Blöcke ausgeführt wird. Und wenn 
es ein abschließendes else gibt, dann sogar genau einer. Vollkommen 
egal, wieviele Variablen in die Test-Ausdrücke der if()'s einfließen.

Im Prinzip ist das genauso [1] wie eine switch() Anweisung, wo auch 
immer nur einer der Blöcke ausgeführt wird. Nur daß man mit switch() nur 
sehr begrenzte Tests hat - man kann nur eine Variable auf bestimmte 
konstante Werte testen. if() hingegen kann beliebig komplexe Tests 
ausführen. Nicht daß man Tests kompliziert machen sollte, aber bereits 
die simple Unterteilung eines Bereichs in 3 Teile ist zu kompliziert für 
switch(), aber trivial für if().

[1] genau genommen kann switch() mehr als das; wenn man am Ende eines 
case: Blocks kein break hat, passiert ein fall through in den nächsten 
Block. Das braucht man zwar selten, aber es sorgt regelmäßig für 
Verwirrung.


Possetitjel schrieb:
> Sehr mutig, dass Du so genau weisst, was ich übersichtlich
> finde.

Stell dir einfach mal vor, der Code wäre länger. Es wären 10 Fälle und 
das switch() enthielte so viel Code, daß der ganze Krempel 3 
Bildschirmseiten braucht. Und jetzt suchst du einen Bug, der darin 
besteht, daß case 42: ausgeführt wird, obwohl er eigentlich nicht 
sollte.

Dann ist eine Kaskade von if()'s deutlich besser lesbar, weil 
ausgeführter Code und die zugehörige Bedingung beieinander stehen. Und 
nicht durch 2½ Bildschirmseiten Codewüste voneinander getrennt sind.

von __Son´s B. (bersison)


Lesenswert?

void EnergieRestAmpel(uint16_t RestZeit)
{
 if(RestZeit >= ENERGIE_SCHWELLE_OBEN) LED_ENERGIE_GN_ON;
 else if(RestZeit <= ENERGIE_SCHWELLE_UNTEN) LED_ENERGIE_RT_ON;
 else LED_ENERGIE_GE_ON;
}

In diesem Zusammenhang verstehe ich folgende Fehlermeldung in beiden 
else-Zeilen nicht;
'else' without a previous 'if'
Mit geschweifter Klammer läuft der Compiler sauber durch!
Code ist doch OK? Ist doch nur ein Anweisung hinter if(RestZeit...).

von Dergute W. (derguteweka)


Lesenswert?

Moin,

__Son´s B. schrieb:
> Ist doch nur ein Anweisung hinter if(RestZeit...

Die "Anweisung" scheint mir ein Macro zu sein (das aus mehreren 
Statements bestehen kann und das wohl auch tut).

Gruss
WK

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Dergute W. schrieb:
> Moin,
>
> __Son´s B. schrieb:
>> Ist doch nur ein Anweisung hinter if(RestZeit...
>
> Die "Anweisung" scheint mir ein Macro zu sein (das aus mehreren
> Statements bestehen kann und das wohl auch tut).

ist mit sicherheit so. Phöse ;-)

Wenn man jetzt den "do { x; y; z; } while (0)" Trick empfiehlt, gibts 
sicher wieder Geschrei ;-)

von Jobst Q. (joquis)


Lesenswert?

__Son´s B. schrieb:
> void EnergieRestAmpel(uint16_t RestZeit)
> {
>  if(RestZeit >= ENERGIE_SCHWELLE_OBEN) LED_ENERGIE_GN_ON;
>  else if(RestZeit <= ENERGIE_SCHWELLE_UNTEN) LED_ENERGIE_RT_ON;
>  else LED_ENERGIE_GE_ON;
> }
>
> In diesem Zusammenhang verstehe ich folgende Fehlermeldung in beiden
> else-Zeilen nicht;
> 'else' without a previous 'if'
> Mit geschweifter Klammer läuft der Compiler sauber durch!
> Code ist doch OK? Ist doch nur ein Anweisung hinter if(RestZeit...).

Das kommt eben durch den Makromurks LED_ENERGIE_GN_ON usw.

Mit

void EnergieRestAmpel(uint16_t RestZeit)
 {
 if(RestZeit >= ENERGIE_SCHWELLE_OBEN) SchalteEnergieAmpel(GRUEN);
 else if(RestZeit <= ENERGIE_SCHWELLE_UNTEN) SchalteEnergieAmpel(ROT);
 else SchalteEnergieAmpel(GELB);
 }

wär das kein Problem.

von Jobst Q. (joquis)


Lesenswert?

Der Vollständigkeit halber gäbe es auch noch die kompakte Lösung:

SchalteEnergieAmpel((RestZeit >= ENERGIE_SCHWELLE_OBEN)?GRUEN:
                    (RestZeit <= ENERGIE_SCHWELLE_UNTEN)?ROT:GELB);

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Geschachtelter, bedingter Zuweisungsoperator rulez...!

Gruss
WK

von __Son´s B. (bersison)


Lesenswert?

Dergute W. schrieb:
> Die "Anweisung" scheint mir ein Macro zu sein (das aus mehreren
> Statements bestehen kann und das wohl auch tut).

Stimmt - übersehen oder verdrängt...

von Cyblord -. (cyblord)


Lesenswert?

Jobst Q. schrieb:
> Der Vollständigkeit halber gäbe es auch noch die kompakte Lösung:
>
> SchalteEnergieAmpel((RestZeit >= ENERGIE_SCHWELLE_OBEN)?GRUEN:
>                     (RestZeit <= ENERGIE_SCHWELLE_UNTEN)?ROT:GELB);

Kompakt ist super, wenn man Speicherplatz für den Quellcode sparen muss, 
oder an einem Wettbewerb für den dümmsten Programmierer teilnehmen will. 
Ansonsten ist "kompakter Quellcode" sicher kein Ziel das man antreben 
sollte. Versuchs mal mit lesbar und erweiterbar. Ist aber nur was für 
Erwachsene.

von Einer K. (Gast)


Lesenswert?

Karl schrieb:
> Isses schon so schlimm wie goto,....?
Goto könnte man auch für das erste Beispiel verwenden.
Dann würden sich die eingestreuten return Statements vermeiden lassen.

Michael R. schrieb:
> Wenn man jetzt den "do { x; y; z; } while (0)" Trick empfiehlt, gibts
> sicher wieder Geschrei ;-)
Natürlich!

Ich bevorzuge auch einzeln stehende if Statments, vor if/else Kaskaden.
Switch/case ist mir auch nicht unbedingt recht, da es einen weiteren 
Block {} einführt. Und dazu noch Blöcke ohne {} beinhaltet.

Block Verschachtlungen bis zur Tiefe 2 sind für mich noch leicht zu 
erfassen. Über eine Tiefe von 5 bis 7, ist Ende. Ins Besondere, wenn da 
noch komplizierte Bedingungen im Spiel sind.
Das überlasse ich dann lieber Typen wie Chuck Norris.


Aber wie immer:
1. die konkrete Anwendung
2. die Firmen Richtlinie
3. persönliche Vorlieben
entscheiden.

von Walter K. (Gast)


Lesenswert?

Cyblord -. schrieb:
> Jobst Q. schrieb:
>> Der Vollständigkeit halber gäbe es auch noch die kompakte Lösung:
>>
>> SchalteEnergieAmpel((RestZeit >= ENERGIE_SCHWELLE_OBEN)?GRUEN:
>>                     (RestZeit <= ENERGIE_SCHWELLE_UNTEN)?ROT:GELB);
>
> Kompakt ist super, wenn man Speicherplatz für den Quellcode sparen muss,
> oder an einem Wettbewerb für den dümmsten Programmierer teilnehmen will.

Was hat die sinnvolle Benutzung des ternären Operators ?: in C mit 
'duemmsten Programmierer' zu tun?

von Cyblord -. (cyblord)


Lesenswert?

Walter K. schrieb:

> Was hat die sinnvolle Benutzung des ternären Operators ?: in C mit
> 'duemmsten Programmierer' zu tun?

Wer noch nicht mal den Kern der Kritik versteht sollte nicht versuchen 
auch noch darüber zu diskutieren.

von A. S. (Gast)


Lesenswert?

Cyblord -. schrieb:
> Kompakt ist super, wenn man Speicherplatz für den Quellcode sparen muss,
> oder an einem Wettbewerb für den dümmsten Programmierer teilnehmen will.
> Ansonsten ist "kompakter Quellcode" sicher kein Ziel das man antreben
> sollte. Versuchs mal mit lesbar und erweiterbar. Ist aber nur was für
> Erwachsene.

Das stimmt einfach nicht. Wenn Du in größeren Projekten arbeitest, ist 
Lesbarkeit das primäre Ziel. Und da hängt es von den projekt- und 
teamspezifischen Gewohnheiten ab, ob lange Zeilen gut sind. Wenn die 
IDE einzeilige Suchergebnisse liefert UND 80 Zeichen im Editor sichtbar 
sind, dann musst Du schon lange knobeln um folgenden Code besser zu 
machen:
1
    if(     RestZeit >= ENERGIE_SCHWELLE_OBEN)  {SchalteEnergieAmpel(GRUEN);}
2
    else if(RestZeit <= ENERGIE_SCHWELLE_UNTEN) {SchalteEnergieAmpel(ROT);}
3
    else                                        {SchalteEnergieAmpel(GELB);}
Auch wenn es den Programmierrichtlinien für Newbies widerspricht.

von Egon N. (egon2321)


Lesenswert?

Achim S. schrieb:
> if(     RestZeit >= ENERGIE_SCHWELLE_OBEN)
> {SchalteEnergieAmpel(GRUEN);}
>     else if(RestZeit <= ENERGIE_SCHWELLE_UNTEN)
> {SchalteEnergieAmpel(ROT);}
>     else
> {SchalteEnergieAmpel(GELB);}

Bin ich der einzige der sich über ein cmp zwischen "RestZeit" und 
"ENERGIE_SCHWELLE_*" wundert?

Allein das ist schon der nächste Punkt der Lesbarkeit. Man sollte nicht 
nachschlagen müssen was welche Variablen machen...

von A. S. (Gast)


Lesenswert?

Egon N. schrieb:
> Bin ich der einzige der sich über ein cmp zwischen "RestZeit" und
> "ENERGIE_SCHWELLE_*" wundert?

Naja, die Begriffe sind wie der Code (hoffentlich) sinnfreie Beispiele. 
In meiner Antwort ging es z.B. nur um die Anordnung, daher originale 
Namen. Eine echte Aufgabe (und damit sinnvolle Namen) kennen wir eh 
nicht. Darum macht es beispielsweise (wie oben) auch keinen Sinn, über 
Lösungen zu streiten, die einer ganz anderen if-Struktur bedürfen.

von Bär Luskoni (Gast)


Lesenswert?

Egon N. schrieb:
> Bin ich der einzige der sich über ein cmp zwischen "RestZeit" und
> "ENERGIE_SCHWELLE_*" wundert?

Nein, da sind noch mindestens 4 Andere. Wenn mein Kollege wiederkommt, 
sind es dann sogar 5.

von Cyblord -. (cyblord)


Lesenswert?

Achim S. schrieb:
> Auch wenn es den Programmierrichtlinien für Newbies widerspricht.

Süß. Der Blinde möchte Picasso über Farbe belehren.

von Jobst Q. (joquis)


Lesenswert?

Cyblord -. schrieb:
> Kompakt ist super, wenn man Speicherplatz für den Quellcode sparen muss,
> oder an einem Wettbewerb für den dümmsten Programmierer teilnehmen will.
> Ansonsten ist "kompakter Quellcode" sicher kein Ziel das man antreben
> sollte. Versuchs mal mit lesbar und erweiterbar. Ist aber nur was für
> Erwachsene.

Eine verschachtelte bedingte Zuweisung ist genauso erweiterbar wie eine 
if-else Konstruktion.

a = (b>c)? 1:
   (d<e)? 2:
   (f==g)? 3:
    ...
   (y!=z)? 24:
   0;


Kompakt ist auch super für die Lesbarkeit, für mich jedenfalls. Und ich 
schreibe Quelltext für mich und den Compiler, nicht für den 
Kindergarten.

Eine Zeile ist nun mal schneller zu überblicken als eine halbe Seite. Je 
weniger Ballast und Redundanzen, umso schlechter können sich Fehler 
verstecken.

Geschwätzigen Quellcode zu schreiben lohnt sich nur, wenn man nicht nach 
Funktionalität, sondern nach Zeilen bezahlt wird.

von Curby23523 N. (Gast)


Lesenswert?

1
int a = 10;
2
bool b;
3
4
if(a == 10)
5
  b = true;
6
else
7
  b = false;

oder?
1
int a = 10;
2
bool b;
3
4
if(a == 10){
5
  b = true;
6
}
7
else{
8
  b = false;
9
}

oder?
1
int a = 10;
2
bool b;
3
4
b = (a == 10) ? true : false;

C) finde ich in so einem einfachen Fall am besten.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Egon N. schrieb:
> Bin ich der einzige der sich über ein cmp zwischen "RestZeit" und
> "ENERGIE_SCHWELLE_*" wundert?
Ich finde es auch interessant, eine Energie mit einer Zeit zu 
vergleichen. Besonders, wenn man bedenkt, dass jeder Vergleich eine 
Subtraktion ist, denn dann steht da "Zeit-Energie"...

Die Lesbarkeit und Verständlichkeit eines Codes beginnt also tatsächlich 
weit, weit vor der Diskussion über die Verwendung des ternären 
Operators.

Curby23523 N. schrieb:
> C) finde ich in so einem einfachen Fall am besten.
Ich nehme D)
1
int a = 10;
2
bool b;
3
4
if (a == 10) b = true;
5
else         b = false;

Man könnte aber auch E) nehmen:
1
int a = 10;
2
bool b;
3
4
b = (a == 10);
Denn das Ergebnis des == Operators ist schon bool...

: Bearbeitet durch Moderator
von Tom (Gast)


Lesenswert?

Lothar M. schrieb:
> if (a == 10) b = true;

So wäre es noch konsequenter:
1
if ( (a == 10) == true )
2
     b = true;

von Karl (Gast)


Lesenswert?

Possetitjel schrieb:
> Dabei wäre es
> so einfach, es besser zu machen.
>
> set SwitchToSummertime true
> ...
> if { rtc.wday != 7 }  then { set SwitchToSummertime false }
> if { rtc.day < 25 }   then { set SwitchToSummertime false }
> if { rtc.month != 3 } then { set SwitchToSummertime false }
> ...

Dein Ernst?

Das ist der totale Schrott!

Du willst sicher wieder eine Begründung:

Erstens: Muss der Controller hier alle if-Anfragen prüfen, obwohl er bei 
meiner Abfrage schon in 6 von 7 Fällen bei der Sonntags-Abfrage 
aussteigen kann. Unnötige Programmlaufzeit.

Zweitens: Wird damit erheblich mehr Code erzeugt. Unnötiger 
Speicherbedarf.

Drittens: Braucht es dann noch zwei zusätzliche ifs und zwei zusätzliche 
Variablen. Unnötig kompliziert.

Da wundert es mich nicht, dass die Leute rumjammern, dass sie mit dem 
8-Bitter nicht auskommen und es der 32-Bitter sein muss, weil der 
Speicher nicht reicht. Oder vielleicht doch lieber der Raspi, um die LED 
zu schalten?

Wenn Du schon an so einfachen Programmkonstrukten scheiterst, wie sehen 
dann umfangreichere Programme für Dich aus? Vielleicht doch das falsche 
Hobby?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Tom schrieb:
> So wäre es noch konsequenter:
>
1
> if ( (a == 10) == true )
2
>      b = true;
3
>
urgs... wer sowas schreibt, frisst auch kleine Kinder ;-)

von Jobst Q. (joquis)


Lesenswert?

Curby23523 N. schrieb:
> int a = 10;
> bool b;
>
> if(a == 10)
>   b = true;
> else
>   b = false;

geht kürzer:

bool b = true;

Wenn man a gerade 10 zugewiesen hat, wozu dann noch mit 10 vergleichen?

von Einer K. (Gast)


Lesenswert?

Jobst Q. schrieb:
> Curby23523 N. schrieb:
>> int a = 10;
>> bool b;
>>
>> if(a == 10)
>>   b = true;
>> else
>>   b = false;
>
> geht kürzer:
>
> bool b = true;

Ich finde es grausam, für sowas ein if einzusetzen.

Eher so:
1
int  a = 10;
2
bool b = 10 == a;

Ich setze bei Vergleichen meist die Konstante nach links.
Also so: if(10 == a)
und eher nicht: if(a == 10)

Um halt das evtl ungewollte if(a = 10) zu vermeiden.
Denn, wenn ich versehentlich if(10 = a) schreibe schimpft der Kompiler 
mit mir, während er das versehentliche if(a = 10) klaglos schluckt.

von Karl (Gast)


Lesenswert?

Jobst Q. schrieb:
> Wenn man a gerade 10 zugewiesen hat, wozu dann noch mit 10 vergleichen?

https://de.wikipedia.org/wiki/Beispiel

Dass sich dazwischen noch Code befinden könnte, der a verändert...

von Karl (Gast)


Lesenswert?

Arduino F. schrieb:
> Um halt das evtl ungewollte if(a = 10) zu vermeiden.
> Denn, wenn ich versehentlich if(10 = a) schreibe schimpft der Kompiler
> mit mir, während er das versehentliche if(a = 10) klaglos schluckt.

Nimm halt eine richtige Programmiersprache, dann passiert sowas nicht.

Oder ist der Algorithmus für Deine Einkaufsliste auch: Wenn Null == 
Bier, dann Nachkaufen?

Hochsprachen sollten eigentlich dazu dienen, den Maschinencode 
menschenkombatibel zu machen. Also Algorithmen so formulieren zu können, 
wie Menschen sie denken. Stattdessen sehe ich hier einen Haufen 
Beispiele, die sich irgendwelcher Hilfskonstrukte bedienen, nur um 
menschenkombatiblen Code zu vermeiden.

Da ist der Sinn einer Hochsprache irgendwie verfehlt.

von Einer K. (Gast)


Lesenswert?

Karl schrieb:
> Nimm halt eine richtige Programmiersprache, dann passiert sowas nicht.
Du meinst besser Forth, als C++?
Vielleicht, sollte ich mal drüber nachdenken....


Bei sowas if(a = 10) kann man schon mal länger nach einem Fehler suchen.
Das Auge flutscht drüber weg, und der Kompiler jammert nicht.

if(10 == a) sieht vielleicht anfangs etwas komisch aus, aber man kann 
sich daran gewöhnen und ist Funktional gleichwertig zu if(a == 10)

Also wohl wieder eher ein Fall von: "Was der Bauer nicht kennt, das 
frisst er nicht"

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Man koennte dem compiler auch sagen, dass er halt mal ein Auge auf 
solche Konstrukte haben soll und doch ein wenig grummeln, wenn er eins 
findet:
1
hello.c: In function main:
2
hello.c:4:18: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
3
 int main() { if (a=5) printf("Hello\n"); }

Gruss
WK

von Jobst Q. (joquis)


Lesenswert?

Karl schrieb:
> Dass sich dazwischen noch Code befinden könnte, der a verändert..

könnte man verdeutlichen indem man ... dazwischen setzt.

von Karl (Gast)


Lesenswert?

Arduino F. schrieb:
> Du meinst besser Forth, als C++?

Pascal, Ada...

> if(10 == a) sieht vielleicht anfangs etwas komisch aus, aber man kann
> sich daran gewöhnen und ist funktional gleichwertig zu if(a == 10)
1
lds r16, a
2
cpi r16, 10
3
breq j10
4
rjmp j20
5
j10:
6
  // if
7
j20:
8
  // end if

Sieht auch komisch aus, kann man sich auch dran gewöhnen und funktional 
ist es gleichwertig zu if a = 10.

Nochmal: Der Sinn einer Hochsprache ist, dass man sich eben nicht 
komische Konstrukte ausdenken muss, sondern Algorithmen menschlich 
verständlich schreiben kann. Sonst kannste auch Assembler schreiben - 
was ich seit Jahren mache.

Wenn eine Sprache solche Konstrukte verlangt, dann isses vielleicht 
keine Hochsprache, sondern ein besserer Makro-Assembler.

von Harlekin (Gast)


Lesenswert?

Karl schrieb:
>> set SwitchToSummertime true
>> ...
>> if { rtc.wday != 7 }  then { set SwitchToSummertime false }
>> if { rtc.day < 25 }   then { set SwitchToSummertime false }
>> if { rtc.month != 3 } then { set SwitchToSummertime false }
>> ...
>
> Das ist der totale Schrott!
>
> Du willst sicher wieder eine Begründung:
>
> Erstens: Muss der Controller hier alle if-Anfragen prüfen, obwohl
> er bei meiner Abfrage schon in 6 von 7 Fällen bei der
> Sonntags-Abfrage aussteigen kann. Unnötige Programmlaufzeit.

Wie oft wird die Funktion aufgerufen? Einmal pro Tag?

>
> Zweitens: Wird damit erheblich mehr Code erzeugt. Unnötiger
> Speicherbedarf.
> Drittens: Braucht es dann noch zwei zusätzliche ifs und zwei
> zusätzliche Variablen. Unnötig kompliziert.

Was nützen die beiden Punkte, wenn sich wegen fehlender 
Übersichtlichkeit ein Fehler eingeschlichen hat?

Bei zeitkritischen Funktionen werde ich in Zukunft weiterhin mal 
verschachteln. Ansonsten werde ich zugunsten der Lesbarkeit, 
Zusatzoperationen in Kauf nehmen.

Ich durfte mich oft genug durch Code kämpfen, wo sich verschachtelte if 
else Konstrukte über mehrere Bildschirmseiten erstreckten. Da hilft 
selbst korrektes Einrücken wenig. Selbst bei obigem Beispiel brauche ich 
wegen der Verschachtelung einfach länger.
Beitrag "Re: Art der if-Auswahl nur Geschmackssache?"

von Jobst Q. (joquis)


Lesenswert?

Karl schrieb:
> Hochsprachen sollten eigentlich dazu dienen, den Maschinencode
> menschenkombatibel zu machen.

Meinst du damit solche Ungetüme:

Karl schrieb:
> Aus aktuellem Anlass:procedure rtc_checksummer();
> begin
>   if rtc.summ and Rsauto <> 0 then begin  // prüfen auf Flag Auto
>     if rtc.wday = 7 then begin  // wenn Sonntag
>       if rtc.day >= $25 then begin  // wenn letzter Sonntag im Monat
>         if rtc.month = $03 then begin  // wenn März, Umschalten auf
> Sommerzeit
>           if (rtc.summ and Rsumm) = 0 then begin  //wenn Flag nicht
> gesetzt
>             if rtc.hh = $02 then begin
>               rtc.hh := $03;
>               rtc.summ := Rsauto or Rsumm;
>               rtc_setsummer();  // Sommerzeit schreiben
>             end;
>           end;
>         end else if rtc.month = $10 then begin  // wenn Oktober,
> Umschalten auf Winterzeit
>           if (rtc.summ and Rsumm) <> 0 then begin  //wenn Flag gesetzt
>             if rtc.hh = $03 then begin
>               rtc.hh := $02;
>               rtc.summ := Rsauto;
>               rtc_setsummer();  // Winterzeit schreiben
>             end;
>           end;
>         end;
>       end;
>     end;
>   end;
> end;

Das ist wahrhaft menschencombatibel.

https://www.urbandictionary.com/define.php?term=combatible

von Tom (Gast)


Lesenswert?

1
bool is_sunday = (rtc.wday == 7);
2
bool is_last_week_in_month = (rtc.day > 24); // only for months with 31 days (e.g. March and October)
3
bool is_last_sunday_in_month = is_sunday && is_last_week_in_month;
4
5
bool is_march = (rtc.month == 3);
6
bool is_october = (rtc.month == 10);
7
8
bool do_switch_to_summertime = is_march && is_last_sunday_in_month;
9
bool do_switch_to_wintertime = is_october && is_last_sunday_in_month;
10
11
if (do_switch_to_summertime)
12
   rtc_set_summer();
13
if (do_switch_to_wintertime)
14
   rtc_set_winter();

von Possetitjel (Gast)


Lesenswert?

Karl schrieb:

>> set SwitchToSummertime true
>> ...
>> if { rtc.wday != 7 }  then { set SwitchToSummertime false }
>> if { rtc.day < 25 }   then { set SwitchToSummertime false }
>> if { rtc.month != 3 } then { set SwitchToSummertime false }
>> ...
>
> Dein Ernst?

Selbstverständlich. Mein voller Ernst.


> Das ist der totale Schrott!

:)


> Du willst sicher wieder eine Begründung:

Ja, wenn sie sich nicht auf den Kernpunkt beschränkt,
dass ich eben dämlich bin, wäre eine Begründung ganz
nett...


> Erstens: Muss der Controller hier alle if-Anfragen
> prüfen, obwohl er bei meiner Abfrage schon in 6
> von 7 Fällen bei der Sonntags-Abfrage aussteigen
> kann. Unnötige Programmlaufzeit.

Das stimmt.

Die Kette von Einzelbedingungen, die ich hingeschrieben
habe, wird immer komplett ausgewertet, das ist in der
Laufzeit etwas ungünstiger als geschachteltes if.
Das lässt sich aber sehr leicht abmildern.

> Zweitens: Wird damit erheblich mehr Code erzeugt.
> Unnötiger Speicherbedarf.

Erheblich... naja.

Die Zahl der Vergleiche und der Sprünge wird nicht
(wesentlich) beeinflusst, nur die Variablenzuweisung
kommt neu dazu. Sind dann halt 21 statt 14 Befehle.
Auch das lässt sich sehr leicht abmildern, ohne meine
Grundidee aufzugeben.

> Drittens: Braucht es dann noch zwei zusätzliche ifs
> und zwei zusätzliche Variablen. Unnötig kompliziert.

Ist im Regelfall nicht relevant.


> Da wundert es mich nicht, dass die Leute rumjammern,
> dass sie mit dem 8-Bitter nicht auskommen und es
> der 32-Bitter sein muss, weil der Speicher nicht
> reicht. Oder vielleicht doch lieber der Raspi, um
> die LED zu schalten?

Lächerlich.

Ich wollte ein Prinzip, eine Grundidee zeigen und habe
NATÜRLICH darauf verzichtet, sie durch Optimierung
zu verwässern.
Selbstverständlich KANN man das in der Praxis etwas
kompakter formulieren, ohne die Grundidee aufzugeben.

Dazu kommt noch: Die Bedingung ist in Deinem Beispiel
nur ein längliches UND aus mehreren Teilbedingungen;
ein strukturell so wenig komplexer Ausdruck lässt sich
auch anders als von mir vorgeschlagen behandeln.


> Wenn Du schon an so einfachen Programmkonstrukten
> scheiterst,

Schätzungsweise definieren wir "scheitern" deutlich
verschieden.

> wie sehen dann umfangreichere Programme für Dich
> aus?

So wie für alle anderen auch: Beschissen.
Zeige mir den Programmierer, der nicht viel lieber
selbst programmiert, als fremde Quelltexte zu lesen.

von Jobst Q. (joquis)


Lesenswert?

if((rtc.wday != 7)||(rtc.day < 25)||(rtc.min != 0)||(rtc.sec != 
0))return;
if((rtc.mon == 3) && (rtc.h == 2)) rtc_set_summer();
if((rtc.mon == 10) && (rtc.h == 3)) rtc_set_winter();

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

Karl schrieb:

> Arduino F. schrieb:
>> Um halt das evtl ungewollte if(a = 10) zu vermeiden.
>> Denn, wenn ich versehentlich if(10 = a) schreibe
>> schimpft der Kompiler mit mir, während er das
>> versehentliche if(a = 10) klaglos schluckt.
>
> Nimm halt eine richtige Programmiersprache, dann
> passiert sowas nicht.

Karl, das ist kindisches Gezänk, das bringt doch
niemanden weiter.

Die Diskussion hatten wir doch neulich schon: Nenne
bitte eine Programmiersprache, die es hinsichtlich
* Ressourceneffizienz,
* Portabilität,
* Ausdruckskraft
ungefähr mit C aufnehmen kann, aber nicht die zahlreichen
Macken von C hat!

Das Ergebnis war auch schon neulich: Es gibt keine.

Es ist völlig egal, ob man C eine "richtige Programmier-
sprache" oder nur einen "portablen Makroassembler" nennt --
der betrübliche Fakt ist der, dass man keine Alternative
hat.

von Possetitjel (Gast)


Lesenswert?

Jobst Q. schrieb:

> Kompakt ist auch super für die Lesbarkeit, für mich
> jedenfalls.

Da schließe ich mich weitgehend an.


> Und ich schreibe Quelltext für mich und den Compiler,
> nicht für den Kindergarten.

Hier nicht.
Ich denke, es ist ganz gut, dass wir keine Kollegen sind
und auch sonst nicht zusammen an einem Projekt arbeiten.


> Je weniger Ballast und Redundanzen, umso schlechter
> können sich Fehler verstecken.

Aufgrund dieses fundamentalen Zusammenhanges sind Leute
wie C. E. Shannon, R. W. Hamming, die Herrn Reed und
Solomon usw. bis heute unbeachtete Spinner geblieben,
und Paritätsbits haben ihren vedienten Platz im
Kuriositätenkabinett der Technik gefunden... :)

von Harlekin (Gast)


Lesenswert?

Jobst Q. schrieb:
> if((rtc.wday != 7)||(rtc.day < 25)||(rtc.min != 0)||(rtc.sec !=
> 0))return;
> if((rtc.mon == 3) && (rtc.h == 2)) rtc_set_summer();
> if((rtc.mon == 10) && (rtc.h == 3)) rtc_set_winter();

Elegant, schnell, kompakt. Bravo


Für Karl sollten wir die Reihenfolge der ersten Zeile optimieren ;-)

if((rtc.min != 0)||(rtc.sec !=0)||(rtc.wday != 7)||(rtc.day < 
25))return;

Begründung:
Wenn ich mich recht entsinne werden in C die Bedingungen von links 
geprüft und sobald eine Oderbedingung true ist, wird zurückgesprungen.

min ist 1/60
sec ist 1/60
wday ist 1/7
day ist ca 1/6

von Possetitjel (Gast)


Lesenswert?

Axel S. schrieb:

>> Im konkreten Beispiel stimmt das -- weil sich nämlich beide
>> Bedingungen auf dieselbe Variable beziehen. Es ist also aus
>> inhaltlichen Gründen sowieso sichergestellt, dass sich die
>> Fälle gegenseitig ausschließen.
>>
>> Wenn mehrere Variablen mit voneinander abhängigen Bedingungen
>> eine Rolle spielen, ist das aber keineswegs mehr so.
>
> Doch. Bei einer if ... else if ... else if ... Kaskade ist
> sichergestellt daß maximal einer der Blöcke ausgeführt wird.

Missverständnis. Meine Schuld. (s.u.)


> Im Prinzip ist das genauso [1] wie eine switch() Anweisung,
> wo auch immer nur einer der Blöcke ausgeführt wird. Nur daß
> man mit switch() nur sehr begrenzte Tests hat - man kann nur
> eine Variable auf bestimmte konstante Werte testen. if()
> hingegen kann beliebig komplexe Tests ausführen. Nicht daß
> man Tests kompliziert machen sollte, aber bereits die simple
> Unterteilung eines Bereichs in 3 Teile ist zu kompliziert
> für switch(), aber trivial für if().

Die Verwandschaft zwischen if/elseif und switch/break ist
erstmal klar; bezüglich des letztlich ausgeführten Anweisungs-
blockes sind beides quasi 1-aus-N-Decoder.

Ich meinte aber etwas anderes:

Im Beispiel gibt es eine Variable (mit einem Wertebereich,
über dem eine Ordnungsrelation definiert ist), und es gibt
zwei Schwellwerte.
Da es zwei Schwellwerte gibt, existieren drei unterscheidbare
Teilintervalle, in denen der Variablenwert liegen kann.
Um die Steuervariable gegen die beiden Schwellwerte zu
testen, sind zwei Bedingungsausdrücke notwendig, die
logischerweise zwei Wahrheitswerte liefern.

Mit zwei Wahrheitswerten sind aber VIER Kombinationen
ausdrückbar!

Der scheinbare Widerspruch rührt natürlich daher, dass die
beiden Bedingungen nicht unabhängig sind, sondern sich auf
dieselbe Variable beziehen: Sie kann nur ENTWEDER im einen
ODER im anderen ODER im dritten Intervall liegen.

Die Kombination, dass sie KLEINER als die untere, aber
gleichzeitig GRÖSSER als die obere Schwelle ist, kann aus
inhaltlichen Gründen nicht auftreten, der Fall ist per se
ausgeschlossen.

Deswegen -- weil es zwar mehrere Bedingungen, aber nur ein
und dieselbe Steuervariable gibt -- ist die if/elsif-
Konstruktion im vorliegenden Fall machbar und sinnvoll.
Hochtrabend mengentheoretisch formuliert: Die möglichen
Fälle bilden inhaltlich eine Partition, und die if/elseif-
Konstrukion bildet diese Partition korrekt ab.

So. Jetzt mein Punkt: Es GIBT Fälle, in denen mehrere
Bedingungsausdrücke vorliegen, die sich aber NICHT ALLE
wie im Beispiel auf dieselbe Steuervariable beziehen,
sondern in denen mehrere verschiedene Steuervariablen in
unterschiedlicher Kombination vorkommen.
Überdies kann der Fall eintreten, dass sich die Bedingungen
für die unterschiedlichen Steuervariablen gegenseitig
beeinflussen ("Der Busfahrer kann männlich oder weiblich
sein; wenn es ein Mann ist, kann er einen Bart tragen oder
nicht. Wenn es eine Frau ist, interessiert der Bart nicht.")

In diesen -- und PRIMÄR in diesen -- Fällen ist meiner
unmaßgeblichen Meinung nach die geteilte Konstruktion mit
dem if-Abschnitt und der abschließenden switch-Anweisung
sinnvoll.
(Im Prinzip ist das nämlich nichts weiter wie eine Art
Normalform: Erstmal wird alles auf garantiert disjunkte
Basisfälle zurückgeführt; dann werden bei Bedarf im switch
die Basisfälle wieder gruppenweise zusammengefasst.)


> Possetitjel schrieb:
>> Sehr mutig, dass Du so genau weisst, was ich übersichtlich
>> finde.
>
> [...]
>
> Dann ist eine Kaskade von if()'s deutlich besser lesbar,
> weil ausgeführter Code und die zugehörige Bedingung
> beieinander stehen. Und nicht durch 2½ Bildschirmseiten
> Codewüste voneinander getrennt sind.

Ich hoffe, mein Punkt ist klarer geworden: Wenn von vornherein
INHALTLICH disjunkte Fallklassen vorliegen, ist if/elseif
optimal, weil es genau das abbildet. (Das ist im Beispiel der
Fall.)

Das bedeutet aber im Umkehrschluss nicht, dass die diskutierte
if/switch-Konstruktion generell sinnlos ist: Da das eine Art
Normalformkonstruktion ist, ist sie gerade in komplizierten
Fällen nützlich, wenn man KEINE offensichtlich disjunkten
Fallklassen hat.

(Sie ist auch nützlich, wenn man SEHR VIELE diskjunkte Fälle
hat, aber das ist ein anderes Thema.)

von Dirk (Gast)


Lesenswert?

Karl schrieb:
> Der GROSSE Vorteil von if ... else ist, dass man damit sehr effizient
> Abfragen zusammenfassen kann, die der Compiler dann sehr effizient in
> Maschinencode umsetzt. Wer diesen Vorteil gerade auf µCs nicht nutzt,
> weil er davon Kopfschmerzen bekommt, sollte vielleicht besser _Bäcker_
> werden.
Der Bäcker der vermutlich seit dem letzten Wochenende zu späte Brötchen 
backt, weil er versucht hat seine komplizierte Sommerzeitumstellung in 
einem µC zu zu testen oder die Chance verpasst hat seine süße 
Treppenkunst der 'Programmierung' auch in einem Feldversuch zu testen 
hat sicherlich nichts von konventioneller Effizienz verstanden:
1
01:if rtc.summ and Rsauto <> 0 then begin  // prüfen auf Flag Auto
2
02:  if rtc.wday = 7 then begin  // wenn Sonntag
3
03:    if rtc.day >= $25 then begin  // wenn letzter Sonntag im Monat
4
04:      if rtc.month = $03 then begin  // wenn März, Umschalten auf Sommerzeit
5
05:        if (rtc.summ and Rsumm) = 0 then begin  //wenn Flag nicht gesetzt
6
06:          if rtc.hh = $02 then begin
7
07:            rtc.hh := $03;
8
08:            rtc.summ := Rsauto or Rsumm;
9
09:            rtc_setsummer();  // Sommerzeit schreiben
10
10:          end;
11
11:        end;
12
12:      end else if rtc.month = $10 then begin  // wenn Oktober, Umschalten auf Winterzeit
13
13:        if (rtc.summ and Rsumm) <> 0 then begin  //wenn Flag gesetzt
14
14:          if rtc.hh = $03 then begin
15
15:            rtc.hh := $02;
16
16:            rtc.summ := Rsauto;
17
17:            rtc_setsummer();  // Winterzeit schreiben
18
18:          end;
19
19:        end;
20
20:      end;
21
21:    end;
22
22:  end;
23
22:end;
Zeile 09:  rtc_setsummer();  // Sommerzeit schreiben
Zeile 17:  rtc_setsummer();  // Winterzeit schreiben
==> der Bäcker versucht dem Compiler mittels Kommentar den Code zu 
erklären, während traditionelle Programmierer Kommentare dazu verwenden 
den verwendeten (!) Code für Menschen lesbarer zu gestalten.
Natürlich kann ein Bäcker nicht wissen, dass praktisch (für Menschen) 
selbsterklärender Code:
"wenn (rtc.tag.akt) größer (tag.36) dann evt. Umstellung" (Pascal "if 
rtc.day >= $25 then") durch die Kommentierung mit einem Wochentag der 
nicht in der Zeile vorkommt ("... Sonntag im Monat") nicht besser 
funktioniert.

Die Frage:
>Was bitte ist daran unlesbar? Und, schon Kopfschmerzen?
die ein Bäcker bei so einem Kunstwerk an die Öffentlichkeit stellen 
muss, da er naturgemäß keinen eigenen Zugriff auf den Quelltext hat, 
verbietet diesem natürlich den Code leserlicher zu gestalten.

(etwas kreativ, u.U. nicht mit jedem Pascal-Compiler religiös vereinbar, 
aber technisch identisch mit dem original Backwerk):
1
{$define th:=then } {$define th_:=then begin}
2
{$define el:=else } {$define el_:=else begin}
3
{$define _el:=end} {$define _th:=end}
4
5
01: if rtc.summ and Rsauto <> 0 // prüfen auf Flag Auto
6
02: th if rtc.wday = 7          // wenn Sonntag
7
03:    th if rtc.day >= $25     // wenn letzter Sonntag im Monat
8
04:       th if rtc.month = $03 // wenn März, Umschalten auf Sommerzeit
9
05:       th_ if (rtc.summ and Rsumm) = 0 // wenn Flag nicht gesetzt
10
06:           th if rtc.hh = $02
11
07:              th_ rtc.hh := $03;
12
08:                  rtc.summ := Rsauto or Rsumm;
13
09:                  rtc_setsummer(); // Sommerzeit schreiben
14
10:                 _th;
15
11:          _th
16
12:       el if rtc.month = $10 // wenn Oktober, Umschalten auf Winterzeit
17
13:          th if (rtc.summ and Rsumm) <> 0//wenn Flag gesetzt
18
14:             th if rtc.hh = $03
19
15:                th_ rtc.hh := $02;
20
16:                    rtc.summ := Rsauto;
21
17:                    rtc_setsummer(); // Winterzeit schreiben
22
18:                   _th;
23
24
// verkürzte Version mit gleichrangigen Bedingungen, um sowohl Kommentar
25
// als auch hexadezimale Brötchenfehler lesen zu können:
26
{$define a_:= and } {$define o_:= or }
27
28
01: if (rtc.summ and Rsauto <> 0 ) // wenn Flag=Auto
29
02: a_ (rtc.wday = 7)              // und Sonntag
30
03: a_ (rtc.day >= $25)            // und Tag > 37 (letzte Woche)
31
04:    th if (rtc.month = $03) // dann wenn März,
32
05:       th_ if ((rtc.summ and Rsumm) = 0) //dann wenn Flag nicht gesetzt
33
06:           a_ (rtc.hh = $02 ) // und Stunde=2
34
07:           th_ rtc.hh := $03;
35
08:               rtc.summ := Rsauto or Rsumm; //'Umschalten' auf Szt
36
09:               rtc_setsummer(); // Sommerzeit schreiben (ident mit WZ_write?)
37
10:              _th; // flag !=rsumm & stunde = 2
38
11:          _th // month $03
39
12:       el if (rtc.month = $10) //sonst wenn Okt(Dez:10;Hex:$0a),
40
13:          a_ ((rtc.summ and Rsumm) <> 0) //und Flag gesetzt
41
14:          a_ (rtc.hh = $03)              //und Stunde = 3
42
15:          th_ rtc.hh := $02;
43
16:              rtc.summ := Rsauto; // 'Umschalten' auf Wz
44
17:              rtc_setsummer(); // Winterzeit schreiben
45
18:             _th; // month $10 & flag == rsumm & stunde = 3
Vorteil: zumindest lesbarer als gleichrangige UND-Bedingungen als 
abhängige "wenn ... dann"-Bedingung zu texten (i.A. werten Compiler ohne 
spezielle Option es exakt gleich aus)
(Nebenvorteil: da viele Bäcker Angst haben einen µC mit ein paar Takten 
zu viel zu überlasten, könnten diese den häufigsten Ausschlussgrund 
(day<>7) an den Anfang der Abfrage stellen und so den µC etwas schonen)

Zusammenfassung: lesbarer Code kann zwar ein paar Takte 'kosten' aber 
Karl der Bäcker bräuchte mehrere Zeitumstellungen bis er die Fehler in 
seinem Code experimentell überprüfen könnte.
Umfangreiche Programmkonstrukte, wie eine Zeitumstellung vor Ende des 36 
Tages im Monat, dürften Bäcker die Karl aus seinen Kopfschmerzen kennt 
sicherlich überfordern. Umfangreiche Programme dürften für Bäcker wie 
Karl wohl deutlich mehr "begin" "end" enthalten.


Arduino F. schrieb:
> Um halt das evtl ungewollte if(a = 10) zu vermeiden.
technisch sehr sinnvoll, aber etwas inkompatibel mit dt./eng. Schreib 
und wohl auch Denkmustern:
sprachlich: wenn der µC eine Spannung von 230V hat, dann liegt ein 
Fehler vor.
umgekehrt: wenn eine Spannung von 230V der µC hat, dann ....auch Fehler 
aber sprachlich wohl Jedi.

Beim programmieren:
if 230 = uC ... ok (aber Denkmurks)
if uC = 230 ... Bude fackelt ab ... (noch schlechter)
Es könnte sein, dass durch die damalige Sparmaßnahme beim 
Zuweisungsoperator in C der Keim der Zerstörung mit angelegt wurde, 
ähnlich dem Whitespace-Operator in C  (u.U. etwas übertrieben für eine 
so gefährliche Programmiersprache)

NB.: für den OP könnte es wohl Hoffnung mit C++20 geben (soll 2020 auf 
den Markt kommen) da dann der Spaceship-Operator endlich Einzug in die 
gefährliche Welt von C++ findet.

von Harlekin (Gast)


Lesenswert?

Dirk schrieb:
> Karl (schrieb) Der GROSSE Vorteil..

nettes Wortspiel ;-)

von Possetitjel (Gast)


Lesenswert?

Rolf M. schrieb:

> Possetitjel schrieb:
>> Das Problem bei if/elseif ist, dass es zwar syntaktisch
>> eine Anweisung bleibt, man aber mehrere unabhängige
>> Bedingungen abprüfen kann, und das ist Teufelswerk.
>
> Warum?

Bei if/elseif schließen sich die (die Fälle behandelnden)
Anweisungsblöcke per Konstruktion aus. Bei unabhängigen
Bedingungen "überlappen" sich die Teilmengen jedoch inhalt-
lich.
Das Konstrukt der Hochsprache spiegelt somit formal einen
ganz anderen Fall vor, als letztlich inhaltlich vorliegt.

Beispiel: Gegeben seien die Bedingungen c1, c2 und c3,
die jeweils wahr oder falsch sein können. Es ergeben
sich formal acht Fallklassen.

Wenn alle acht formal denkbaren Fallklassen tatsächlich
inhaltlich verschieden sind, ist die Sache noch relativ
einfach: Man kommt mit if/then auf drei Ebenen durch die
Sache durch, muss aber Bedingungen mehrfach schreiben
(was nicht dramatisch, aber auch nicht schön ist -- "DRY").
Alternativ kann man auch if/elseif auf einer Ebene verwenden,
muss dann aber alle drei Bedingungen viermal negiert und
viermal nichtnegiert schreiben. Geht auch.

Die if/switch-Konstruktion sieht dort so aus:
1
 
2
set fallnr 0 
3
if { $c1 } then { set  fallnr 4 }
4
if { $c2 } then { incr fallnr 2 }
5
if { $c3 } then { incr fallnr 1 }
6
7
switch $fallnr { 
8
... 
9
}

Noch schlimmer wird es aber, wenn die formal denkbaren
Fälle inhaltlich NICHT alle unterschiedlich sind.

Bei der if/then/else- bzw. if/elseif-Variante schreibt
man entweder den die Fälle behandelnden Code mehrfach,
oder man lagern ihn in Funktionen aus, oder man versucht,
die Bedingungen umzuformulieren.
Letzteres ist gefährlich; es ist eine Konzentrationsübung,
dabei Vollständigkeit und Widerspruchsfreiheit abzusichern.

Verwendet man die if/switch-Konstruktion, muss man von der
Struktur her überhaupt nichts anpassen, sondern ändert
lediglich die Zuordnung der Fallnummern in der switch-
Anweisung.

Dieses Beispiel mit drei binären Bedingungen ist noch
ziemlich gutartig; wenn es drei Bedingungen mit drei,
drei und zwei Belegungen gibt, sind das formal schon
18 Fallklassen.

> "Fallnummer"? Also wenn man das so macht, dann sollte
> man (ähnlich wie Tom es gezeigt hat) den Fällen auch
> Namen geben. Irgendwelche Magic-Numbers machen es alles
> andere als übersichtlicher. Dann muss ich beim Lesen des
> switch/case erst wieder oben nachschauen, welches
> Ergebnis der if-Abfrage denn nun zu Fall Nummer 3 gehört,
> was den Lesefluss meiner Meinung nach stark stört.

Das stimmt -- aber hast Du einen besseren Vorschlag?


> Hmm, dann funktionieren unsere Gehirne verschieden ;-)

Das ist gut möglich :)


> Wenn ich das im Kopf durchgehen würde, würde ich sagen:
> [...]
>
> Da hab ich ja im zweiten Satz schon vergessen, welcher
> Fall im ersten Satz welcher Bedingung zugeordnet war.

Ja... das Beispiel ist ungünstig, weil für die LEDs die
if/elseif-Kette aus inhaltlichen Gründe die richtige
Konstruktion ist.
Das will ich auch gar nicht bestreiten; es ging mir nur
darum, dass der if/switch-Vorschlag nicht SO bescheuert
ist, wie er zunächst aussieht -- auch wenn er für das
konkrete Beispiel nicht gut passt.


>> Im konkreten Beispiel stimmt das -- weil sich nämlich beide
>> Bedingungen auf dieselbe Variable beziehen. Es ist also aus
>> inhaltlichen Gründen sowieso sichergestellt, dass sich die
>> Fälle gegenseitig ausschließen.
>>
>> Wenn mehrere Variablen mit voneinander abhängigen Bedingungen
>> eine Rolle spielen, ist das aber keineswegs mehr so.
>
> Ja, ab einer gewissen Komplexität ist die Trennung durchaus
> sinnvoll. Aber zwingend ist für mich dann auch wieder, dass
> keine magischen Fallnummern verwendet werden, sondern
> aussagekräftige Bezeichnungen.

Ich bin für alle Ideen offen.

Die erstrebte Vereinfachung kommt ja dadurch zustande, dass
ich mit den Fallnummern rechne. Mir fällt aber nix ein, wie
man das mit Klartext-Bezeichnungen kombinieren könnte.
Bitfrickeln ist auch nicht schön; es kann ja drei oder fünf
Unterklassen je Steuervariable geben, dann würden Lücken in
den Fallnummern entstehen, was die Sache wieder verkompliziert.

Im Prinzip ist Dein Einwand aber gut; man braucht eine
idiotensichere (=für mich taugliche) Methode, die Fallnummern
auf Klartextbezeichnungen abzubilden.

von Karl (Gast)


Lesenswert?

Jobst Q. schrieb:
> if((rtc.wday != 7)||(rtc.day < 25)||(rtc.min != 0)||(rtc.sec !=
> 0))return;
> if((rtc.mon == 3) && (rtc.h == 2)) rtc_set_summer();
> if((rtc.mon == 10) && (rtc.h == 3)) rtc_set_winter();

Macht nur leider nicht das Gleiche wie mein Code.

Tom schrieb:
> bool is_sunday = (rtc.wday == 7);
> bool is_last_week_in_month = (rtc.day > 24); // only for months with 31
> days (e.g. March and October)
> bool is_last_sunday_in_month = is_sunday && is_last_week_in_month;
>
> bool is_march = (rtc.month == 3);
> bool is_october = (rtc.month == 10);
>
> bool do_switch_to_summertime = is_march && is_last_sunday_in_month;
> bool do_switch_to_wintertime = is_october && is_last_sunday_in_month;
>
> if (do_switch_to_summertime)
>    rtc_set_summer();
> if (do_switch_to_wintertime)
>    rtc_set_winter();

Das hätte ich gern mal als ASM-Listing gesehen. Glaube kaum, dass 7 
unnötige Zwischenvariablen effektiver umgesetzt werden als if-Abfragen.

Possetitjel schrieb:
> Karl, das ist kindisches Gezänk, das bringt doch
> niemanden weiter.

Ich empfinde es eher als kindisch, sich absonderliche Konstrukte 
auszudenken, weil man mit der Struktur einer if .. else if.. else 
Abfolge überfordert ist.

Ist das wirklich so schwierig? Bei den meisten der obigen "alternativen" 
Konstrukte sage ich mir: Ja, kann man machen, aber: WARUM?

von Himmel hilf (Gast)


Lesenswert?

Karl schrieb:

> Ja, kann man machen, aber: WARUM?

Warum? Verschleiern, tarnen, täuschen, Finten setzen. Wozu? Um es 
Anderen maximal zu erschweren oder am Besten unmöglich machen, den unter 
Elend und Entbehrungen erzeugten Code zu entziffern.

von Dirk (Gast)


Lesenswert?

Karl schrieb:
> Macht nur leider nicht das Gleiche wie mein Code.
du hast als Betroffener sicherlich keinen direkten Zugang zu Deinem Code 
und konntest den in einem µC testen, ansonsten wäre Dir die verpasste 
Zeitumstellung bei Deinem umfangreichen Projekt aufgefallen.,


> Possetitjel schrieb:
>> Karl, das ist kindisches Gezänk, das bringt doch
>> niemanden weiter.
>
> Ich empfinde es eher als kindisch, sich absonderliche Konstrukte
> auszudenken, weil man mit der Struktur einer if .. else if.. else
> Abfolge überfordert ist.
Solche kindischen Empfindungen passieren wenn Karl überfordert ist 
seinen fehlerhaften Problemcode aus seinem Zeitumstellungsprojekt 
eigenständig zu überprüfen.

> Ist das wirklich so schwierig? Bei den meisten der obigen "alternativen"
> Konstrukte sage ich mir: Ja, kann man machen, aber: WARUM?
Solche Selbstgespräche sind sicherlich nicht hilfreich wenn es darum 
geht WARUM die Zeitumstellung bei Karl auch dieses Jahr nicht geklappt 
hat.

von Egon N. (egon2321)


Lesenswert?

Tom schrieb:
> Lothar M. schrieb:
>> if (a == 10) b = true;
>
> So wäre es noch konsequenter:if ( (a == 10) == true )
>      b = true;

Genfer Konvention sagt dir was? Solche Codekonstrukte wurden im gleichen 
Atemzug mit chemischen Kampfstoffen verboten.

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

Dirk schrieb:
> du hast als Betroffener sicherlich keinen direkten Zugang zu Deinem Code
> und konntest den in einem µC testen, ansonsten wäre Dir die verpasste
> Zeitumstellung bei Deinem umfangreichen Projekt aufgefallen.,

Der Code läuft seit Jahren in meiner Heizung und hat bisher noch jede 
Zeitumstellung mitgemacht.

Wenn Du eine Packed-BCD-Zahl nicht als solche erkennst, solltest Du 
Bäcker werden.

von Jobst Q. (joquis)


Lesenswert?

Possetitjel schrieb:
>> Und ich schreibe Quelltext für mich und den Compiler,
>> nicht für den Kindergarten.
>
> Hier nicht.

Hier halte ich mich an die Vorgaben der Fragesteller und der anderen 
Teilnehmer, soweit es geht.

Das ist aber nur ein winziger Bruchteil der von mir geschriebenen 
Quelltexte. Ich bin eben selbstständig und der einzige, der mit meinen 
Quellen arbeiten muss. Also haben sich durch Erfahrungen von Jahrzehnten 
Regeln herauskristallisiert, die für mich und meine Arbeit optimal 
sind.Ich habe das Privileg, nicht berücksichtigen zu müssen, was andere 
für optimal halten.

> Ich denke, es ist ganz gut, dass wir keine Kollegen sind
> und auch sonst nicht zusammen an einem Projekt arbeiten.
>
Warum? Dass ich nach eigenen Regeln programmiere, heißt ja nicht, dass 
ich mich nicht nach anderen Regeln richten kann. Mit manchen könnte ich 
mich sicher auf gemeinsame Regeln einigen, mit allen natürlich nicht.

>> Je weniger Ballast und Redundanzen, umso schlechter
>> können sich Fehler verstecken.
>
> Aufgrund dieses fundamentalen Zusammenhanges sind Leute
> wie C. E. Shannon, R. W. Hamming, die Herrn Reed und
> Solomon usw. bis heute unbeachtete Spinner geblieben,
> und Paritätsbits haben ihren vedienten Platz im
> Kuriositätenkabinett der Technik gefunden... :)

Das soll wohl Ironie sein, aber in der Nachrichtentechnik hat Redundanz 
eine ganz andere Bedeutung als in der Programmierung und die Fehler sind 
ganz anderer Art.

von Jobst Q. (joquis)


Lesenswert?

Karl schrieb:
> Jobst Q. schrieb:
>> if((rtc.wday != 7)||(rtc.day < 25)||(rtc.min != 0)||(rtc.sec !=
>> 0))return;
>> if((rtc.mon == 3) && (rtc.h == 2)) rtc_set_summer();
>> if((rtc.mon == 10) && (rtc.h == 3)) rtc_set_winter();
>
> Macht nur leider nicht das Gleiche wie mein Code.

Was dein Code macht, weiß leider keiner außer dir. Die Umgebung hast du 
uns nicht mitgeteilt.

von Dirk (Gast)


Lesenswert?

Karl schrieb:
> Dirk schrieb:
>> du hast als Betroffener sicherlich keinen direkten Zugang zu Deinem Code
>> und konntest den in einem µC testen, ansonsten wäre Dir die verpasste
>> Zeitumstellung bei Deinem umfangreichen Projekt aufgefallen.,
>
> Der Code läuft seit Jahren in meiner Heizung und hat bisher noch jede
> Zeitumstellung mitgemacht.
> Wenn Du eine Packed-BCD-Zahl nicht als solche erkennst, solltest Du
> Bäcker werden.
das heisst du hast wirklich keine Möglichkeit eigenständig Deinen 
veröffentlichten Code mit Hilfe einer Texterkennung nach "BCD" zu 
untersuchen und bleibst als Abhängiger darauf beschränkt anderen 
Menschen etwas 'empfehlen' zu müssen.

Du hast den Geschmack der Packed-BCD-Zahl sicherlich beim backen erlebt 
und  deswegen sind bei dir
>Zeile 09:  rtc_setsummer();  // Sommerzeit schreiben
>Zeile 17:  rtc_setsummer();  // Winterzeit schreiben
weiterhin identisch.

von Karl (Gast)


Lesenswert?

Dirk schrieb:
> deswegen sind bei dir
>>Zeile 09:  rtc_setsummer();  // Sommerzeit schreiben
>>Zeile 17:  rtc_setsummer();  // Winterzeit schreiben
> weiterhin identisch.

Ja. Weil da nur die aktuelle Stunde aus rtc.hh und die Flags (Auto und 
Sommerzeit) aus rtc.summ per TWI in die RTC geschrieben werden. Ist die 
gleiche Funktion, warum sollte ich die zweimal unter verschiedenen Namen 
haben?

Das Entscheidende ist die Zeile darüber, in der das Flag gesetzt wird, 
welches dann stromausfallsicher in der RTC abgelegt wird.

von Dirk (Gast)


Lesenswert?

Karl schrieb:
> Dirk schrieb:
>> deswegen sind bei dir
>>>Zeile 09:  rtc_setsummer();  // Sommerzeit schreiben
>>>Zeile 17:  rtc_setsummer();  // Winterzeit schreiben
>> weiterhin identisch.
>
> Ja. Weil da nur die aktuelle Stunde aus rtc.hh und die Flags (Auto und
> Sommerzeit) aus rtc.summ per TWI in die RTC geschrieben werden. Ist die
> gleiche Funktion, warum sollte ich die zweimal unter verschiedenen Namen
> haben?
das kannst du nicht wissen wenn du aus Unerfahrenheit generell fremde 
Menschen wie mich für solche programmtechnischen Kleinigkeiten fragen 
musst, aber auch Kommentare können falsch sein d.h. wenn der Kommentar 
behauptet "Winterzeit schreiben" obwohl im Programm der jeweils aktuelle 
Wert geschrieben wird, dann ist das ein eindeutiger Kommentarfehler.
>Zeile 09:  rtc_setsummer();  // Wert schreiben
>Zeile 17:  rtc_setsummer();  // Wert schreiben
wäre zumindest nicht falsch und falls du einmal leslichen Code 
schreiben möchtest anstatt vieler begin/end, dann wäre
>Zeile 09:  rtc_setsummer();  // stromausfallsicher Flag setzen
>Zeile 17:  rtc_setsummer();  // stromausfallsicher Flag setzen
eine Option.

> Das Entscheidende ist die Zeile darüber, in der das Flag gesetzt wird,
> welches dann stromausfallsicher in der RTC abgelegt wird.
Dein Programm wäre ohne Kommentare sicherlich leichter zu lesen, aber da 
Du auf fremde Menschen angewiesen bist um diese nach einfachsten Sachen 
zu fragen kannst du auch nicht lesen, dass auch das nicht im 
Code/Kommentar steht.

von Karl (Gast)


Lesenswert?

Häh?

von Dirk (Gast)


Lesenswert?

Karl schrieb:
>>> Dirk schrieb:
>> das kannst du nicht wissen wenn du aus Unerfahrenheit generell fremde
>> Menschen wie mich für solche programmtechnischen Kleinigkeiten fragen
>> musst, aber auch Kommentare können falsch sein d.h. wenn der Kommentar
>> behauptet "Winterzeit schreiben" obwohl im Programm der jeweils aktuelle
>> Wert geschrieben wird, dann ist das ein eindeutiger Kommentarfehler.
> Häh?
Menschen die nur hilflos fremde Menschen "Hä?" fragen können und keinen 
Zugang zum Quelltext haben auf den sie reagieren, bleibt die 
Unerfahrenheit mit der sie auf den Bäcker gekommen sind.

von TI:07 (Gast)


Lesenswert?

geht das auch ohne switch case oder if ?

Also Funktionsaufruf über einen struct ?

von Rolf M. (rmagnus)


Lesenswert?

TI:07 schrieb:
> Also Funktionsaufruf über einen struct ?

Was magst du damit meinen?

von Einer K. (Gast)


Lesenswert?

>Zeile 09:  rtc_setsummer();  // Sommerzeit schreiben
>Zeile 17:  rtc_setsummer();  // Winterzeit schreiben

Ich finde das absolut gruselig!

Eine Funktion/Methode, mit "set" im Name ist für mich ein Setter, und 
setSummer() setzt halt auf Sommerzeit. NIE würde ich auf die Idee 
kommen, dass die gleiche Funktion auch die Winterzeit einstellt.

Eine solche Funktion würde ich sofort umbenennen!
z.B. in rtc_togglesummer()
Das kann man ja sonst nach 6 Monaten selber nicht mehr verstehen.
(es sei denn, es ist das einzige Programm, was man in der Zeit anfasst)

von A. S. (Gast)


Lesenswert?

Cyblord -. schrieb:
> Süß. Der Blinde möchte Picasso über Farbe belehren.

Mh, unter welchem Namen zeigst Du denn in diesem Forum mal was von 
Deiner Kunst?

Und wenn Du selber mal ein großes Projekt betreust (nicht nur als Summe 
vieler kleiner), dann wirst Du erfahren, dass einige Regeln für normale 
Projekte nicht skalieren, an die Du (aus Deiner Erfahrung zurecht) noch 
glaubst.

von Tom (Gast)


Lesenswert?

TI:07 schrieb:
> geht das auch ohne switch case oder if ?
> Also Funktionsaufruf über einen struct ?
Ohne if und mit struct :
1
void set_summer(void) {printf("sommer\n");}
2
void set_winter(void) {printf("winter\n");}
3
void do_nothing(void) {;}
4
5
void doit(int mon, int day, int wday){
6
    static struct {void (*a)(void); void (*b)(void);void (*c)(void); } F = {set_summer, do_nothing, set_winter};
7
    static void (**p)(void) = (void(**)(void)) &F + 1;
8
    p[(mon==10 && wday==7 && day>24) - (mon==3 && wday==7 && day>24)]();
9
}
Sehr kompakt mit wenigen Zeilen und deshalb überaus lesbar.

von Possetitjel (Gast)


Lesenswert?

Jobst Q. schrieb:

>> Ich denke, es ist ganz gut, dass wir keine Kollegen sind
>> und auch sonst nicht zusammen an einem Projekt arbeiten.
>>
> Warum? Dass ich nach eigenen Regeln programmiere, heißt
> ja nicht, dass ich mich nicht nach anderen Regeln richten
> kann.

Naja, vor dem Hintergrund, dass Du ein Ein-Mann-Team bist,
wird Deine Bemerkung verständlicher.

Die Formulierung mit dem Kindergarten kam halt so 'rüber,
dass Dir völlig egal ist, ob andere Deine genialen Quell-
texte lesen können (wobei es durchaus sein kann, dass die
wirklich genial sind. Dein Codebeispiel für die Sommerzeit-
umstellung ist auch an Lesbarkeit schwerlich zu übertreffen.)


>>> Je weniger Ballast und Redundanzen, umso schlechter
>>> können sich Fehler verstecken.
>>
>> Aufgrund dieses fundamentalen Zusammenhanges sind Leute
>> wie C. E. Shannon, R. W. Hamming, die Herrn Reed und
>> Solomon usw. bis heute unbeachtete Spinner geblieben,
>> und Paritätsbits haben ihren vedienten Platz im
>> Kuriositätenkabinett der Technik gefunden... :)
>
> Das soll wohl Ironie sein,

Richtig erkannt.


> aber in der Nachrichtentechnik hat Redundanz eine
> ganz andere Bedeutung als in der Programmierung und
> die Fehler sind ganz anderer Art.

Bei "andere Art der Fehler" stimme ich teilweise zu.

Redundanz bewirkt aber immer dasselbe: Aufblähung des
Datenvolumens -- und Möglichkeit zur Erkennung und
Korrektur von Fehlern.

Wenn Menschen für die redundanzfreie Kommunikation
geschaffen wären, würden wir alle immer und überall
Steno schreiben. Tun wir aber nicht.

Klare, kompakten Formulierungen im Quelltext sind
immer erstrebenswert -- aber die Kompaktheit sollte
nur soweit getrieben werden, wie sie der Klarheit
nicht widerspricht.
Dein eigener Dreizeiler oben ist ja ein gutes Beispiel
dafür.

von Rolf M. (rmagnus)


Lesenswert?

Possetitjel schrieb:
> Redundanz bewirkt aber immer dasselbe: Aufblähung des
> Datenvolumens -- und Möglichkeit zur Erkennung und
> Korrektur von Fehlern.

Ich hätte jetzt erwartet, dass da kommt: Möglichkeit zum Einbauen von 
mehr Fehlern…

von Egon N. (egon2321)


Lesenswert?


von Jobst Q. (joquis)


Lesenswert?

Possetitjel schrieb:
> Bei "andere Art der Fehler" stimme ich teilweise zu.
>
> Redundanz bewirkt aber immer dasselbe: Aufblähung des
> Datenvolumens -- und Möglichkeit zur Erkennung und
> Korrektur von Fehlern.

Redundanz ist dann sinnvoll und nützlich, wenn man die Wahl hat zwischen 
redundanten Blöcken und die Fehler vor der Wahl erkennen kann. Wie in 
der Nachrichtentechnik.

In Programmen ist das aber nicht gegeben. Da wird einer der redundanten 
Blöcke aufgerufen und wenn da ein Fehler drin ist, ist das ein Fehler 
des ganzen Progamms, das dann evtl abstürzt.

Redundanzarme Programmierung mit gemeinsamen Funktionen oder Makros für 
ähnliche Operationen bietet Fehlern weniger Möglichkeiten, sich zu 
verstecken.

Die aufrufenden Funktionen werden kürzer und übersichtlicher, da kommt 
man Fehlern schneller auf die Spur. Sind sie in der aufgerufenen 
Funktion, werden sie schneller entdeckt, weil diese häufiger aufgerufen 
wird.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Tom schrieb:
> void doit(int mon, int day, int wday){
>     static struct {void (*a)(void); void (*b)(void);void (*c)(void); } F
> = {set_summer, do_nothing, set_winter};
>     static void (**p)(void) = (void(**)(void)) &F + 1;
>     p[(mon==10 && wday==7 && day>24) - (mon==3 && wday==7 && day>24)]();
> }

Hi,
ich vermisse hier noch die zeit/stunde, weil die uhr wird nicht um 
mitternacht umgestellt.

schönes beispiel, man beachte die dereferenzierung durch eckige klammern 
des functionspointers! daher anstatt *() = []


wieder was gelernt, danke mt!

von Egon N. (egon2321)


Lesenswert?

Tom schrieb:
> TI:07 schrieb:
>> geht das auch ohne switch case oder if ?
>> Also Funktionsaufruf über einen struct ?
> Ohne if und mit struct :void set_summer(void) {printf("sommer\n");}
> void set_winter(void) {printf("winter\n");}
> void do_nothing(void) {;}
>
> void doit(int mon, int day, int wday){
>     static struct {void (*a)(void); void (*b)(void);void (*c)(void); } F
> = {set_summer, do_nothing, set_winter};
>     static void (**p)(void) = (void(**)(void)) &F + 1;
>     p[(mon==10 && wday==7 && day>24) - (mon==3 && wday==7 && day>24)]();
> }
>
> Sehr kompakt mit wenigen Zeilen und deshalb überaus lesbar.

Ich hab keine Ahnung was da passieren soll.

Wieso nicht einfach die Formel vom Gauss benutzen? Dadurch bekommt man 
bequem den letzten Sonntag ermittelt.

https://de.wikipedia.org/wiki/Gau%C3%9Fsche_Wochentagsformel

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Egon N. schrieb:
> Ich hab keine Ahnung was da passieren soll.

Das ist kein gutes Zeichen.

Ich hab sowas schon mal woanders vorgeschlagen, hier isses halt noch ein 
Stueck verhauter...

Beitrag "Re: Mittels Switch Case zwischen Unterprogrammen in der main wechseln"

Gruss
WK

von Jobst Q. (joquis)


Lesenswert?

Tom schrieb:
> TI:07 schrieb:
>> geht das auch ohne switch case oder if ?
>> Also Funktionsaufruf über einen struct ?
> Ohne if und mit struct :
>
1
> void set_summer(void) {printf("sommer\n");}
2
> void set_winter(void) {printf("winter\n");}
3
> void do_nothing(void) {;}
4
> 
5
> void doit(int mon, int day, int wday){
6
>     static struct {void (*a)(void); void (*b)(void);void (*c)(void); } F 
7
> = {set_summer, do_nothing, set_winter};
8
>     static void (**p)(void) = (void(**)(void)) &F + 1;
9
>     p[(mon==10 && wday==7 && day>24) - (mon==3 && wday==7 && day>24)]();
10
> }
11
> 
12
>
> Sehr kompakt mit wenigen Zeilen und deshalb überaus lesbar.

Warum als struct und nicht gleich als Array?

Die Funktionen sind doch alle vom selben Typ.

von Thomas (Gast)


Lesenswert?

Weil TI:07 ein struct wollte. Das ganze war natürlich nicht 
ernstgemeint.

von Jobst Q. (joquis)


Lesenswert?

Tom schrieb:
> p[(mon==10 && wday==7 && day>24) - (mon==3 && wday==7 && day>24)]();

Ist denn sichergestellt, dass eine wahre Bedingung +1 als Ergebnis hat?
Soweit ich mich erinnere, ist nur Null und nicht-null festgelegt.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Jobst Q. schrieb:
> Ist denn sichergestellt, dass eine wahre Bedingung +1 als Ergebnis hat?
> Soweit ich mich erinnere, ist nur Null und nicht-null festgelegt.

passt!

boolische ausdrücke liefern 0=false oder 1=true zurück

UND

als bedingung wird alles ungleich 0 als true interpretiert.


mt

von Karl (Gast)


Lesenswert?

Egon N. schrieb:
> Wieso nicht einfach die Formel vom Gauss benutzen? Dadurch bekommt man
> bequem den letzten Sonntag ermittelt.

Wow! Zwei Modulos durch 100 und 400. Das heisst, mal eben noch 
Ganzzahldivision reinschmeißen.

Der letzte Sonntag im Monat ist im März und Oktober IMMER der zwischen 
25.* und 31. Iss so.

*) In Packed-BCD, wie es eine RTC wie die DS1307 liefert: $25

Egon N. schrieb:
> http://www.instructables.com/id/The-Arduino-and-Daylight-Saving-Time-Europe/

Von da: if (dow == 7 && mo == 10 && d >= 25 && h == 3 && DST==1)

Das hatte ich so ähnlich für C auf dem ATmega. Das wurde bescheiden 
umgesetzt, daraufhin habe ich das in die einzelnen ifs aufgelöst und es 
wurde controllerfreundlich umgesetzt.

Das Problem war wenn ich mich recht erinnere, dass der Compiler bei 
dieser Variante erstmal alle Variablen aus dem SRAM in Register lädt, 
und diese dann vergleicht. Wobei jeder einzelne Vergleich im Controller 
als compare+branch ausgeführt wird, geht ja nicht anders.

In ifs aufgelöst wird genauso mit compare+branch verglichen, nur dass 
der Compiler nur die Variable lädt, die er für den Vergleich braucht, 
und auch nur in ein Register. Was neben der unnötigen zusätzlichen 
Laufzeit für das Laden auch Register spart. Was dazu führt, dass der 
Compiler diese gesparten Register nicht pushen und poppen muss. Was 
wiederum zu gespartem Speicherplatz führt.

Sämtliche anderen obigen Konstrukte benötigen genau die gleichen 
compares+branches, egal ob über Hilfsvariablen oder über eine Structure. 
Denn der Controller kann nunmal nur das: Einen Wert mit einem anderen 
Vergleichen und darauf ein Ergebnisregister auf true oder false setzen.

Zusätzlich benötigen diese Konstrukte aber weiteren Speicherplatz, 
müssen Variablen schreiben und lesen, oder benötigen zuätzliche 
Register, die gepushed und gepoppt werden müssen. Kann mir keiner 
erzählen, dass das effizienter ist. Schlechter lesbar ist es noch dazu.

Deswegen hätte ich ja gern mal die vom Compiler erzeugten 
Assemblerlistings zu obigen Konstrukten gesehen. Aber dafür reichts dann 
wieder nicht.

von Tom (Gast)


Angehängte Dateien:

Lesenswert?

Karl schrieb:
> dass der Compiler bei
> dieser Variante erstmal alle Variablen aus dem SRAM in Register lädt,
> und diese dann vergleicht. Wobei jeder einzelne Vergleich im Controller
> als compare+branch ausgeführt wird, geht ja nicht anders.
So blöd ist gcc nichtmal mit -O0.

von Possetitjel (Gast)


Lesenswert?

Jobst Q. schrieb:

> Redundanz ist dann sinnvoll und nützlich, wenn man
> die Wahl hat zwischen redundanten Blöcken und die
> Fehler vor der Wahl erkennen kann. Wie in der
> Nachrichtentechnik.
>
> In Programmen ist das aber nicht gegeben. [...]

Wir haben unterschiedliche Dinge im Blick.

Dass man auf Block- oder Anweisungsebene keine
Redundanz haben will, ist klar ("DRY").

Quelltexte sind aber nicht nur Mittel zur Mensch-
Maschine-Kommunikation, sondern auch zur Mensch-
Mensch-Kommunikation -- und sei es nur, dass ich
den Quelltext verstehen will, den ich vor drei
Jahren geschrieben habe.

Der redundanzfreie Operatorwahn, den C auslebt, ist
da meiner Meinung nach wahrnehmungspsychologisch nicht
hilfreich.
Wenn die Menschen für redundanzfreie schriftliche
Kommunikation geeignet wären, würde wir alle immer
und überall Steno schreiben. Tun wir aber nicht.

Die normale Schriftsprache enthält reichlich
Redundanz, und das ist auch gut so [TM].

von Herbert P (Gast)


Lesenswert?

Hallo allseits,

obwohl die Diskussion in diesem Thread langsam programmier-esoterisch 
geworden ist, möchte ich gerne nochmals auf den OT zurückkommen (konnte 
leider nicht früher posten). Ich habe den Code mal auf Verdacht mit ein 
paar defines ergänzt, damit er kompilierbar wird, und dann dem 
Compiler-Explorer von Mats Godbolt (https://godbolt.org/) zum Fraß 
vorgeworfen:
1
#include <stdint.h>
2
3
#define ENERGIE_SCHWELLE_OBEN 5
4
#define ENERGIE_SCHWELL_UNTEN 1
5
#define LED_ENERGIE_GN_ON *((uint16_t *)0x5000) = 1
6
#define LED_ENERGIE_RT_ON *((uint16_t *)0x5002) = 1
7
#define LED_ENERGIE_GE_ON *((uint16_t *)0x5004) = 1
8
9
//_1________________________________________
10
void EnergieRestAmpel1(uint16_t RestZeit)
11
{
12
if(RestZeit >= ENERGIE_SCHWELLE_OBEN)
13
{
14
 LED_ENERGIE_GN_ON;              
15
 return;
16
}
17
if(RestZeit <= ENERGIE_SCHWELL_UNTEN)
18
{
19
 LED_ENERGIE_RT_ON;              
20
 return;
21
}
22
 LED_ENERGIE_GE_ON;              
23
}
24
25
//_2_________________________________________
26
void EnergieRestAmpel2(uint16_t RestZeit)
27
{  
28
uint8_t Prio=3;
29
if(RestZeit >= ENERGIE_SCHWELLE_OBEN)  Prio=2;
30
if(RestZeit <= ENERGIE_SCHWELL_UNTEN)  Prio=1;
31
  
32
switch(Prio)
33
{
34
case 1:
35
 LED_ENERGIE_RT_ON;  
36
 break;
37
case 2:
38
 LED_ENERGIE_GN_ON;    
39
 break;
40
default:
41
 LED_ENERGIE_GE_ON;    
42
}
43
}

Was ich jetzt wirklich interessant finde, ist, dass er mit -O3 übersetzt 
für beide Funktionen identischen Code liefert. Hier das Ergebnis für den 
ARM64-Compiler, für AVR waren die beiden Funktionen ebenfalls gleich, 
andere habe ich nicht versucht:
1
EnergieRestAmpel1(unsigned short):
2
  uxth w0, w0
3
  cmp w0, 4
4
  bgt .L6
5
  cmp w0, 1
6
  ble .L7
7
  mov x0, 20484
8
  mov w1, 1
9
  strh w1, [x0]
10
  ret
11
.L6:
12
  mov x0, 20480
13
  mov w1, 1
14
  strh w1, [x0]
15
  ret
16
.L7:
17
  mov x0, 20482
18
  mov w1, 1
19
  strh w1, [x0]
20
  ret
21
EnergieRestAmpel2(unsigned short):
22
  uxth w0, w0
23
  cmp w0, 4
24
  bgt .L9
25
  cmp w0, 1
26
  bgt .L10
27
  mov x0, 20482
28
  mov w1, 1
29
  strh w1, [x0]
30
  ret
31
.L9:
32
  mov x0, 20480
33
  mov w1, 1
34
  strh w1, [x0]
35
  ret
36
.L10:
37
  mov x0, 20484
38
  mov w1, 1
39
  strh w1, [x0]
40
  ret

Das heißt, dass alle Überlegungen sich wirklich ausschließlich auf die 
Lesbarkeit beschränken können, in Puncto Laufzeit ist jegliche 
Diskussion überflüssig. :)

Gruß
Herby

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Herbert P schrieb:
> Das heißt, dass alle Überlegungen sich wirklich ausschließlich auf die
> Lesbarkeit beschränken können, in Puncto Laufzeit ist jegliche
> Diskussion überflüssig. :)

... der beweis geht fehl, weil kein induktiver beweis vorliegt, die 
schnelle verallgemeinerung ist hier eher wunsch als realität.

z.b. meine erfahrung mit gcc und avr ist, das bei umfangreichen 
bedingungen ich zwar regelmäßig switch/case bzgl. lesbarkeit mir wünsche 
aber if/else oft bessere code size liefert.

ich probier deshalb ab einer gefühlten mächtigkeit der vorliegenden 
bedingungen beide varianten bzgl. code size. die laufzeit war nie thema.

ich bin ansonsten ein switch/case kind, weil da mache ich weniger fehler 
...
und habe irgenwie einen besseren überblick was sache ist.


mt

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Apollo M. schrieb:
> die laufzeit war nie thema.
Das ist das Problem mit den Softwerkern. Am Besten vor dem Vergelcih 
noch einen Cast auf einen 64-Bit-Float. So bekommt man jeden GHz-Boliden 
langsam...

von Jobst Q. (joquis)


Lesenswert?

Possetitjel schrieb:
> Quelltexte sind aber nicht nur Mittel zur Mensch-
> Maschine-Kommunikation, sondern auch zur Mensch-
> Mensch-Kommunikation -- und sei es nur, dass ich
> den Quelltext verstehen will, den ich vor drei
> Jahren geschrieben habe.

Das will ich auch.

>
> Der redundanzfreie Operatorwahn, den C auslebt, ist
> da meiner Meinung nach wahrnehmungspsychologisch nicht
> hilfreich.

Da habe ich wohl eine andere Wahrnehmung als du.
(x+1)*y  habe ich schneller und sicherer überblickt als

Addiere 1 zu x und multipliziere das Ganze mit y.

Dass C sparsam mit Schlüsselwörtern umgeht und stattdessen lieber 
einfache Zeichen nimmt, sehe ich als einen seiner größten Vorteile. Über 
die Zeichen nehme ich die Struktur wahr und die Buchstaben bleiben 
größtenteil für den Inhalt (Variablen und Funktionen) reserviert.

Wörter wie begin und end sind weder redundanter noch verständlicher als 
{ und }. Als unbedarfter Leser von Pascal-Quelltexten würde ich mich 
wundern, warum man dem Programm zigmal sagen muss, dass es anfangen soll 
und ebenso oft, dass es aufhören soll.

Solche unnötigen Buchstabenwüsten zähle ich auch nicht unter Redundanz, 
sondern unter Ballast.

Hilfreiche Redundanz kenne ich auch. So habe ich mir angewöhnt, bei 
größeren Blöcken die schließenden Klammern mit den Bedingungen ihres 
Anfangs zu kommentieren.

      }// for(i=0;i<NSets;i++)
    }// while(*s)
  }// else zu if(r != l)

#endif // #ifdef ARM

von Karl (Gast)


Lesenswert?

Jobst Q. schrieb:
> So habe ich mir angewöhnt, bei
> größeren Blöcken die schließenden Klammern mit den Bedingungen ihres
> Anfangs zu kommentieren.
>       }// for(i=0;i<NSets;i++)
>     }// while(*s)
>   }// else zu if(r != l)

Und das ist weniger als ein begin...end?

Es gibt moderne IDE, die haben sowas wie Autovervollständigen oder 
intelligente Klammerung. So wie ein C die } automatisch nach der { 
gesetzt werden kann, geht das in Pascal auch. Nervt manchmal, aber in 
Pascal sehe ich ein irrtümlich gesetztes end; eher als eine irrtümlich 
gesetzte Klammer in C.

Ganz häßlich sind in C Folgen von )})}.

Abgesehen davon kann man sowohl in C begin...end anstatt {} verwenden 
als auch in Pascal {} statt begin...end, wenn man sich das hindefiniert. 
Das ist nicht der entscheidende Unterschied.

von Herbert P. (Gast)


Lesenswert?

Apollo M. schrieb:
> Herbert P schrieb:
>> Das heißt, dass alle Überlegungen sich wirklich ausschließlich auf die
>> Lesbarkeit beschränken können, in Puncto Laufzeit ist jegliche
>> Diskussion überflüssig. :)
>
> ... der beweis geht fehl, weil kein induktiver beweis vorliegt, die
> schnelle verallgemeinerung ist hier eher wunsch als realität.

Mein Post war weder Verallgemeinerung noch der Versuch eines Beweises 
sondern beschränkte sich ausschließlich auf das publizierte Codestück. 
Es ist richtig, dass komplexere Konstrukte nicht ganz so einfach zu 
betrachten sind, aber in der Regel werden bei einer Handvoll Vergleichen 
(ich hab das mal bis zu 10 untersucht) if-else-Ketten und vergleichbare 
Switch-Awnweisungen zu gleichem Maschinenencode übersetzt bei 
Optimierung. Bei mehr Fällen macht switch in der Regel dann 
Sprungtabellen, außer odie Löcher werden zu groß.

Bei Sonderfällen oder extremen Konstrukten treten dann auch schnell 
Unterschiede zwischen den Compilern auf, so dass man hier eigentlich gar 
nicht verallgemeinern kann.

Gruß
Herby

von A. S. (Gast)


Lesenswert?

Jobst Q. schrieb:
> Hilfreiche Redundanz kenne ich auch. So habe ich mir angewöhnt, bei
> größeren Blöcken die schließenden Klammern mit den Bedingungen ihres
> Anfangs zu kommentieren.
>
>       }// for(i=0;i<NSets;i++)
>     }// while(*s)
>   }// else zu if(r != l)

Verwende da lieber einen Editor. (nicht "Editor" von Windows;-). Der 
Kommentar veraltet zu schnell.

Lothar M. schrieb:
> Am Besten vor dem Vergelcih
> noch einen Cast auf einen 64-Bit-Float.
Gut lesbarer Code ist selten Grund für Laufzeitprobleme. Ein solcher 
Cast wäre Gift für beides. Im Gegenteil: Wenn ich einen Code gut lesen 
kann, erkenne ich solchen Unsinn eher und es wird ... nur besser.

von Possetitjel (Gast)


Lesenswert?

Jobst Q. schrieb:

> Da habe ich wohl eine andere Wahrnehmung als du.

Mag sein...


> (x+1)*y  habe ich schneller und sicherer überblickt als
>
> Addiere 1 zu x und multipliziere das Ganze mit y.

Nun ja, das liegt mMn einfach daran, dass die(se) mathe-
matischen Operatoren in C im großen und ganzen dieselbe
Bedeutung haben wie in der Mathematik, und die Arithmetik
hat man schon einige Jahre in der Grundschule trainiert...


> Dass C sparsam mit Schlüsselwörtern umgeht und stattdessen
> lieber einfache Zeichen nimmt, sehe ich als einen seiner
> größten Vorteile.

Hmm. Du machst mich nachdenklich. Vielleicht habe ich mir
einfach die falsche Begründung für meine Beobachtung
zurechtgelegt.

Bescheuert finde ich z.B., dass sowohl "=" als auch "=="
belegt -- und i.d.R. auch im selben Kontext zulässig sind,
so dass automatische Prüfung durch den Compiler schwierig
ist.
Die Verwendung von "*" für Pointer ist auch so ein Beispiel;
wieso muss ich einen "Mal"-Punkt schreiben, wenn ich gar
nicht multiplizieren will?
Von "++" und "--" schweigen wir lieber. Ich gestehe aber
zu, dass das nix mit den Operatoren an sich zu tun hat,
sondern damit, wie man sie in Ausdrücken verwenden darf
(--> Seiteneffekte).

Es gibt noch weitere Beispiele; "&&" etwa, was ein
Etikettenschwindel ist, weil boolesches AND kommutativ
ist, && aber nicht.

> Über die Zeichen nehme ich die Struktur wahr [...]
> Wörter wie begin und end sind weder redundanter noch
> verständlicher als { und }.

...wobei mir in diesem Zusammenhang eine hübsche Ironie
aufgefallen ist: Wenn man die Programmstruktur primär
über "{" und "}" wahrnimmt -- warum schreibt dann niemand
Blocksatz mit 72 Zeichen je Zeile?
Warum wird dann -- teils erbittert -- über die Formatie-
rung von Quelltexten gestritten?
Die Wahrheit ist: Alle "konventionellen" Programmier-
sprachen sind auch "graphische" Programmiersprachen; die
Klammern sind für den Compiler, die Einrückung für den
Menschen. :)

Das nur als Anmerkung; in der Sache gebe ich Dir Recht.


> Hilfreiche Redundanz kenne ich auch. So habe ich mir
> angewöhnt, bei größeren Blöcken die schließenden Klammern
> mit den Bedingungen ihres Anfangs zu kommentieren.
>
>       }// for(i=0;i<NSets;i++)
>     }// while(*s)
>   }// else zu if(r != l)
>
> #endif // #ifdef ARM

Das finde ich witzig, denn das mache ich auch.

Die Gefahr, dass der Kommentar veraltet, besteht zwar, ist
aber meiner Erfahrung nach nicht übermäßig groß, weil ich
bei Änderungen an der Steuerstruktur sowieso die Einrückung
und Klammerung anpassen muss; da fällt das Korrigieren des
Kommentars mit ab.

von Egon N. (egon2321)


Lesenswert?

Possetitjel schrieb:
> Bescheuert finde ich z.B., dass sowohl "=" als auch "=="
> belegt -- und i.d.R. auch im selben Kontext zulässig sind,
> so dass automatische Prüfung durch den Compiler schwierig
> ist.
> Die Verwendung von "*" für Pointer ist auch so ein Beispiel;
> wieso muss ich einen "Mal"-Punkt schreiben, wenn ich gar
> nicht multiplizieren will?
> Von "++" und "--" schweigen wir lieber. Ich gestehe aber
> zu, dass das nix mit den Operatoren an sich zu tun hat,
> sondern damit, wie man sie in Ausdrücken verwenden darf
> (--> Seiteneffekte).

https://de.wikibooks.org/wiki/C-Programmierung:_Liste_der_Operatoren_nach_Priorit%C3%A4t

Hast du bei einer Zeile Code keine Ahnung was der Operator macht auf den 
ersten Blick - richtig klammern! Ist das nicht sofort ersichtlich ist 
der Code als Müll zu betrachten.

von Possetitjel (Gast)


Lesenswert?

Karl schrieb:

> Jobst Q. schrieb:
>> So habe ich mir angewöhnt, bei
>> größeren Blöcken die schließenden Klammern mit den
>> Bedingungen ihres Anfangs zu kommentieren.
>>       }// for(i=0;i<NSets;i++)
>>     }// while(*s)
>>   }// else zu if(r != l)
>
> Und das ist weniger als ein begin...end?

Wieso "weniger"?

Längere Blöcke mit mehreren Schachtelungsebenen übersieht
man selbst auf dem Monitor nicht mehr so einfach. Ich sehe
da NICHT mehr auf einen Blick, welche schließende zu welcher
öffnenden Klammer gehört; da sind diese Kommentare schon
hilfreich.


> Es gibt moderne IDE, die haben sowas wie Autovervollständigen
> oder intelligente Klammerung. So wie ein C die } automatisch
> nach der { gesetzt werden kann, geht das in Pascal auch.

Das hilft gar nix, wenn man bemerkt, dass man NACH einem
bestimmten Anweisungsblock noch eine Anweisung einfügen muss,
und beim Ändern den falschen Block (=die falsche schließende
Klammer) erwischt.
Die Kommentare sind sinnvoll für's Ändern -- nicht für's
Neu-Schreiben.


> Ganz häßlich sind in C Folgen von )})}.

Schließende geschweifte Klammern markieren ein Block-Ende;
das bekommt eine Zeile für sich.

von Jemand (Gast)


Lesenswert?

Possetitjel schrieb:
> Längere Blöcke mit mehreren Schachtelungsebenen übersieht
> man selbst auf dem Monitor nicht mehr so einfach. Ich sehe
> da NICHT mehr auf einen Blick, welche schließende zu welcher
> öffnenden Klammer gehört; da sind diese Kommentare schon
> hilfreich.

Welchen Editor verwendest du? Diese Software muss ich unbedingt meiden, 
scheint ja gar nichts zu können.

von Karl (Gast)


Lesenswert?

Possetitjel schrieb:
> Längere Blöcke mit mehreren Schachtelungsebenen übersieht
> man selbst auf dem Monitor nicht mehr so einfach...

Auch wenn es bei mir abgeschaltet ist, weil ich es nicht nutze: Moderne 
IDE haben Codefaltung auf mehreren Ebenen.

Ebenso markieren diese IDE schließende zusammen mit öffnenden Klammern, 
ebenso das zu einem "end" gehörige "begin" und umgekehrt.

Possetitjel schrieb:
> Schließende geschweifte Klammern markieren ein Block-Ende;
> das bekommt eine Zeile für sich.

Das machst Du vielleicht so, aber es gibt genug Code wo das nicht 
gemacht wird.

von A. S. (Gast)


Lesenswert?

Possetitjel schrieb:
> Wenn man die Programmstruktur primär
> über "{" und "}" wahrnimmt -- warum schreibt dann niemand
> Blocksatz mit 72 Zeichen je Zeile?
> Warum wird dann -- teils erbittert -- über die Formatie-
> rung von Quelltexten gestritten?

Hier gibt es eine Redundanz: Der Blocksatz UND die Klammern bestimmen 
die Struktur, genauso wie bei begin/end.

Bei Python ist es nur der Blocksatz, was m.E. "fragil" ist.

Bei C stört {/} einfach weniger als begin/end, weil es einfach schneller 
erfassbar ist.

In der Mathematik haben wir uns daran gewöhnt, dass die schnelle 
Erfassbarkeit wichtig ist. Wir erkennen es nichtmal. Operatoren, 
Ziffern, Variablen, etc. sind meist nur je ein Zeichen. Daneben noch 
Schreibweisen, die weiter Einkürzen (z.B. 3E7). Eine Formel y=2x wäre 
nacht Wirth wohl sowas wie "FunktionsWERT IST Zwei MAL 
FunktionsARGUMENT". Den Vergleich kann man für witzig oder blöd halten, 
Fakt ist, dass selbst Schulkinder (aus gutem Grund) y=2*x normal finden.

von Possetitjel (Gast)


Lesenswert?

Karl schrieb:

> Possetitjel schrieb:
>> Längere Blöcke mit mehreren Schachtelungsebenen übersieht
>> man selbst auf dem Monitor nicht mehr so einfach...
>
> Auch wenn es bei mir abgeschaltet ist, weil ich es nicht
> nutze: Moderne IDE haben Codefaltung auf mehreren Ebenen.

Ja, stimmt, ... die boshafte Frage des Vorposters zielte
ja auch in diese Richtung.


> Ebenso markieren diese IDE schließende zusammen mit
> öffnenden Klammern, ebenso das zu einem "end" gehörige
> "begin" und umgekehrt.

Das macht selbst der (von mir i.d.R. verwendete) mcedit;
das hilft aber nix, wenn ein Papierausdruck vor mir liegt.
Und -- ja! Ich verwende Papierausdrucke für (informelle)
Code-Reviews.


> Possetitjel schrieb:
>> Schließende geschweifte Klammern markieren ein
>> Block-Ende; das bekommt eine Zeile für sich.
>
> Das machst Du vielleicht so, aber es gibt genug
> Code wo das nicht gemacht wird.

Sicher -- aber man kann ja die Programmiersprache nicht
für JEDE Unsitte verantwortlich machen.

von Sheeva P. (sheevaplug)


Lesenswert?

Possetitjel schrieb:
> Die Wahrheit ist: Alle "konventionellen" Programmier-
> sprachen sind auch "graphische" Programmiersprachen; die
> Klammern sind für den Compiler, die Einrückung für den
> Menschen. :)

Signaturverdächtig. ;-)

von Karl (Gast)


Lesenswert?

Possetitjel schrieb:
> aber man kann ja die Programmiersprache nicht
> für JEDE Unsitte verantwortlich machen.

Bei C? Doch!

von Possetitjel (Gast)


Lesenswert?

Achim S. schrieb:

> Possetitjel schrieb:
>> Wenn man die Programmstruktur primär
>> über "{" und "}" wahrnimmt -- warum schreibt dann niemand
>> Blocksatz mit 72 Zeichen je Zeile?
>> Warum wird dann -- teils erbittert -- über die Formatie-
>> rung von Quelltexten gestritten?
>
> Hier gibt es eine Redundanz: Der Blocksatz UND die Klammern
> bestimmen die Struktur, genauso wie bei begin/end.

Naja, was heisst "bestimmen"?
Wie schon geschrieben: Die Klammern sind für den Compiler,
die Einrückung ist für den Menschen.


> Bei Python ist es nur der Blocksatz, was m.E. "fragil" ist.

Ja, ich halte das auch für keine gute Idee.
Besser eine IDE, die automatisch gemäß der Klammerung einrückt,
als ein Interpreter, der gemäß der Einrückung klammert :)


> Bei C stört {/} einfach weniger als begin/end, weil es
> einfach schneller erfassbar ist.
>
> In der Mathematik haben wir uns daran gewöhnt, dass die
> schnelle Erfassbarkeit wichtig ist. Wir erkennen es nichtmal.
> [...]

Jaja...

Jobst hat mich schon bei meiner ersten Antwort unsicher
gemacht. Wer nach Noten singen oder musizieren kann, der
weiss ja aus eigener Erfahrung, dass man auch einen sehr
speziellen Code mit ziemlich merkwürdigen Zeichen flüssig
lesen lernen kann.

Es können also nicht die Sonderzeichen an sich sein, die
mich an C stören, es muss irgend etwas anderes sein.


> Operatoren, Ziffern, Variablen, etc. sind meist nur je
> ein Zeichen. Daneben noch Schreibweisen, die weiter
> Einkürzen (z.B. 3E7). Eine Formel y=2x wäre nacht Wirth
> wohl sowas wie "FunktionsWERT IST Zwei MAL FunktionsARGUMENT".
> Den Vergleich kann man für witzig oder blöd halten, [...]

Nee, weder -- noch.
Ich denke, der Vergleich ist ungerecht gegenüber Wirth.

Die Grundrechenarten werden in Pascal genauso codiert wie
im normalen Leben; das ist nicht der Punkt. Die Sache mit
der Zuweisung (":=") ist mMn deutlich vernünftiger als in C.
Einzig unrühmliche Ausnahme ist begin/end; das hätte nicht
sein müssen.

Ihr habt mich (teilweise) bekehrt: Das Problem ist offen-
sichtlich NICHT, dass viele Operatoren durch Sonderzeichen
codiert werden -- das funktioniert ja in anderen Programmier-
sprachen und auch gänzlich außerhalb des Computers recht gut.
Also muss das Problem in den Operatoren selbst liegen. Hmm.
Mal überdenken.

von Possetitjel (Gast)


Lesenswert?

Sheeva P. schrieb:
> Possetitjel schrieb:
>> Die Wahrheit ist: Alle "konventionellen" Programmier-
>> sprachen sind auch "graphische" Programmiersprachen; die
>> Klammern sind für den Compiler, die Einrückung für den
>> Menschen. :)
>
> Signaturverdächtig. ;-)

:)

von Jobst Q. (joquis)


Lesenswert?

Karl schrieb:
> Possetitjel schrieb:
>> aber man kann ja die Programmiersprache nicht
>> für JEDE Unsitte verantwortlich machen.
>
> Bei C? Doch!

Man muss nicht alles machen, was nicht verboten ist.

Und man muss auch nicht alles verbieten, was unsinnig ist.

Scharfes Werkzeug ist immer auch gefährlich. Aber es bringt auch nichts, 
deshalb mit stumpfem Werkzeug zu arbeiten.

Und es kommt auch auf die Ebene an. Von einer Fräsmaschine kann man 
einige Sicherheitsvorkehrungen erwarten, von einem einfachen Stechbeitel 
nicht.

von Bernd N (Gast)


Lesenswert?

>       }// for(i=0;i<NSets;i++)
>     }// while(*s)
>   }// else zu if(r != l)

Code mit Code kommentieren :-) auweia, C Legasteniker.

von A. S. (Gast)


Lesenswert?

Possetitjel schrieb:
> Also muss das Problem in den Operatoren selbst liegen. Hmm. Mal
> überdenken.

Da sind deine Argumente ja richtig. * für prt, ++ für +=1 (und das für 
...).

Das lässt sich wohl nur erklären, wenn man auf damaliger Tastaturen 
schaut. Die trigraphen geben einen ersten Hinweis.

Wenn Buchstaben ausscheiden, und möglichst wenige Schlüsselwörter, ...


If(*x+++++y)...

von Jobst Q. (joquis)


Lesenswert?

Bernd N schrieb:
> Code mit Code kommentieren :-) auweia, C Legasteniker.

Peinlich. Bevor man andere als Legastheniker beschimpft, sollte man sich 
erkundigen, wie es geschrieben wird.

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> If(*x+++++y)...

Da geht aber noch min ein Stern mehr!
 If(**x+++++y)...

von Rolf M. (rmagnus)


Lesenswert?

Bernd N schrieb:
>>       }// for(i=0;i<NSets;i++)
>>     }// while(*s)
>>   }// else zu if(r != l)
>
> Code mit Code kommentieren :-) auweia, C Legasteniker.

Den Zweck nicht verstanden? Bei #ifdefs mache ich das immer. Wenn man 
davon mehrere im Code hat, wird das sonst sehr unübersichtlich, vor 
allem, weil man bei denen ja in der Regel keine Einrückung zur 
Gliederung des darin enthaltenen Codes nutzt.
Bei XML ist es sogar vorgeschrieben, beim Schließen des Tags dessen Name 
nochmal zu wiederholen.

Achim S. schrieb:
> Possetitjel schrieb:
>> Also muss das Problem in den Operatoren selbst liegen. Hmm. Mal
>> überdenken.
>
> Da sind deine Argumente ja richtig. * für prt, ++ für +=1 (und das für
> ...).

Bevor ich C genutzt habe, fand ich x = x + 1 irgendwie etwas 
umständlich, aber es gab nichts anderes, also war das eben so. Und es 
ist ja nun auch wirklich kein Hexenwerk, die Bedeutung von ++ und += zu 
lernen.

> If(*x+++++y)...

Manche betätigen sich damit ja geradezu künstlerisch:
1
while ( x --> 0)

von Karl (Gast)


Lesenswert?

Jobst Q. schrieb:
> Von einer Fräsmaschine kann man
> einige Sicherheitsvorkehrungen erwarten, von einem einfachen Stechbeitel
> nicht.

Leider montieren einige den Stechbeitel an einen 10kW-Motor, den sie auf 
einen Handkarren laden, fahren damit in der Gegend rum und sagen: Guck, 
meine Fräsmaschine.

Ich bin ja immer wieder beeindruckt, wenn darauf hingewiesen wird, dass 
man mit C doch AUCH guten Code schreiben könnte.

Warum wird es dann nicht gemacht?

Wenn man sich so die üblichen Einfallstore in Software anschaut: Strings 
schreiben über den definierten Bereich, beim Laden eines Bildes 
schreiben Metadaten über den erlaubten Bereich hinaus, Pointer zeigen 
auf ausführbaren Speicher... das sind so Sachen, da würde Dir ein 
Pascal- oder Ada-Compiler schon beim Kompilieren auf die Finger klopfen 
oder spätestens beim Ausführen eine Exception werfen, aber nicht einfach 
Schadcode ausführen als wäre nix dabei.

von Dirk B. (Gast)


Lesenswert?

*** Vorsicht: im Anschluss folgt ein längerer Text der entscheidbare, 
faktenfähige Inhalte enthalten könnte **
edit: ist wohl noch etwas längerer geworden: besondere Vorsicht
*** bitte nur lesen/reagieren, wenn ganze Sätze im Kontext gelesen und 
bei Reaktionen genannt werden können **

Possetitjel schrieb:
> Ihr habt mich (teilweise) bekehrt: Das Problem ist offen-
> sichtlich NICHT, dass viele Operatoren durch Sonderzeichen
> codiert werden -- das funktioniert ja in anderen Programmier-
> sprachen und auch gänzlich außerhalb des Computers recht gut.
es ist vermutlich schlimmer: Du hast es (nachweisbar durch die Nennung 
eigener Beispiele) selber (aktiv) verstanden und wurdest nicht (passiv) 
bekehrt...
> Also muss das Problem in den Operatoren selbst liegen. Hmm.
> Mal überdenken.
... zumindest fast. Also ich persönlich hab bspw. ein Problem Pilze zu 
essen, aber das Problem muss nicht in den Pilzen sein und ganz häufig 
ist es noch nicht einmal ein Problem d.h. solange Du nicht aus 
Umweltgründen (bspw. finanzielle Engpässe) dazu gezwungen bist die 
Operatoren zu benutzten (C-Programme schreiben)  ist "das Problem" ein 
Nil-Pointer auf eine völlig unstrukturierte Variable.

Dein Beispiel für eine falsche Kodierung des Schlüsselwortes "Redundant" 
dürfte sich damit vom Ergebnis her erledigt haben, aber ich hatte das 
als Konzept für eine Erklärung eingeplant, deswegen nochmal kurz:
Prüfung "Redundanz" Duden: "überflüssige Information": kann weg, muss 
aber nicht d.h. die Information erzeugt selber keinen Fehler UND 
implizit: es existiert auch eine Information, die beim weglassen der 
'redundanten' übrig bleibt.
1
C:
2
 int  i;// das 'Schlüsselsymbol' " " ist redundant und könnte mit:
3
 int i;
vereinfacht werden.
Pascal:
1
Var i:integer;;// ein ";" ist redundant.
2
Var i::integer;;// geht nicht: die aus C bekannte Redundamnz wird von P. nicht unterstützt (und umgekehrt beim
3
";")
Reduntante Blöcke Klammerungen:
1
if bedingung
2
 then begin      // Information: Anweisungen a b werden
3
        begin    // entweder beide oder nicht ausgeführt
4
          anw_a; // ? ist eine Information reduntant
5
          anw_b; // ! mind. eine Information kann wegegelassen
6
        end;     // werden UND wenn alle begin ... end weggelassen werden,
7
      end;       // dann ändert sich die Aneisungsausführung ==> redundant
8
9
 if bedingung
10
  then begin  // kein Block/eine(1) Anweisung
11
       anw_a; // begin ... end kann weg, aber
12
       end;   // wenn alle begin ... end entfernt werden
13
 begin        // ändert sich nichts ==> nicht redundant, 
14
 anw_b;       // sondern nur überflüssig OHNE Information
15
 end;
Praxistest redundante Seilbahn:
a) Kabine hängt an 3 Seilen. 2 fallen aus: Kabine vom Boden entfernt. 
3 Ausfälle: Kabine erreicht Bodenkontakt
b) Kabine ist bereits abgestürzt. 3 Seile sind gespannt. 3 Ausfälle: 
Kabine behält Bodenkontakt: für die
betroffene Kabine waren die 3 Seile vor dem Ausfall nicht einmal 
redundant

im Beispiel aus der Füllstoffindustrie "Aus aktuellem 
Anlass:"(Ausschnitt)
1
 if rtc.month = $03 then begin  // 'fasst' if (rts.sum)... zusammen
2
    if (rtc.summ and Rsumm) = 0 then begin // 'fasst' if (rtc.hh)... zusammen
3
       if rtc.hh = $02 then begin  // Information:
4
          rtc.hh := $03;           // hh / sum sollen 
5
          rtc.summ := Rsauto or Rsumm;//zusammen  ausgeführt werden
6
       end;
7
    end;
8
  end;
9
10
 if rtc.month = $03 then
11
    if (rtc.summ and Rsumm) = 0 then
12
       if rtc.hh = $02 then begin
13
          rtc.hh := $03;
14
          rtc.summ := Rsauto or Rsumm;
15
       end;//keine Änderung
16
17
 1:1 Kopie Pascal (Füllstoff)==> C (Füllstoff):
18
 void rtc_checksummer();
19
 {if (rtc.summ and Rsauto != 0)  {  // prüfen auf Flag Auto
20
    if (rtc.wday == 7)  {  // wenn Sonntag
21
      if (rtc.day >= $25  {  // wenn letzter Sonntag im Monat
22
        if (rtc.month == $03) {  // wenn März, Umschalten auf Sommerzeit
23
          if ((rtc.summ and Rsumm) == 0 ) {  //wenn Flag nicht gesetzt
24
            if (rtc.hh == $02)  {
25
              rtc.hh = $03;
26
              rtc.summ = Rsauto or Rsumm;
27
              rtc_setsummer();  // Sommerzeit schreiben
28
            };
29
          };
30
        } else if (rtc.month == $10)  {  // wenn Oktober, Umschalten auf Winterzeit
31
          if ((rtc.summ and Rsumm) != 0)  {  //wenn Flag gesetzt
32
            if (rtc.hh == $03) {
33
              rtc.hh = $02;
34
              rtc.summ = Rsauto;
35
              rtc_setsummer();  // Winterzeit schreiben
36
            };
37
          };
38
        };
39
      };
40
    };
41
  };
42
};
==> für C Ungewohnte könnte die überflüssige und nicht redundante 
Klammerung noch(!) unleserlicher sein, aber unnötige Nichtinformation 
ist in beiden Sprachen ziemlich sicher unleserlicher

Häufig gibt es für exakt die gleiche Anweisung unterschiedliche 
Schreibweisen:
1
inc(x) <=> x=x+1 kann aber den Zweck verdeutlichen.
2
Bei C ist nach definiertem Standard:
3
 if ( bed_1 && bed_2)  Anweisung;
EXAKT, für die Ausführung, identisch mit
 if (bed_1)
    if (bed_2) Anweisung;
[/code]
Pascal hat keine offizielle Festlegung, aber praktisch alle Compiler 
benutzen SC als Vorgabe.
Mit
1
 If (tag=24)and (monat=24) then heiligabend:
 ist leslich: vom Prinzip könnte monat=24 zuerst geprüft werden, aber 
faktisch wird tag zuerst abgefragt. Falls sich herausstellen sollte, 
dass die Abfrage tag=24 sehr 'teuer' ist, dann lässt sich das leserliche 
Programm sehr einfach an die - in dem speziellen Fall wohl eher 
unwahrscheinlichen - Gegebenheiten anpassen in dem die
 beiden Bedingungen vertauscht werden.
 Beim umgekehrten Fall
1
 if pW<>nil then if pw^=flag_hlg then heiligabend:
 wird deutlich, dass pw<>nil erfüllt sein MUSS und nicht nur aus 
performance Gründen zuerst geprüft wird. Vom
 Prinzip ist ein bekanntes Pascal Konstrukt:
 if (pW<>nil) and ( pw^=flag_hlg) then heiligabend:
 ziemlich unleserlich und nur durch Gewohnheit, weil es vielfach so 
verwendet und beim Kontakt mit Fremdcode wohl unbewusst gelernt wird 
oder weil es kürzer ist, halbwegs lesbar.(genaue Ursache und ob 
überhaupt, ist nicht sicher),


Bei u.U. gewünschten Seiteneffekten ("function SE_toll:boolean") könnte 
es kompliziert werden:
 Pascal:
1
 if se_toll or true then ok; //u.U. könnte ein Compiler se_toll als Voreinstellung weg-optimieren
 C:
1
 if (se_toll or true) ok; //der Compiler darf ohne Optimierungsoption se_toll nicht vergessen, obwohl das Ergebnis mathematisch im Voraus [code]
2
berechnet werden könnte.

 Bei anderen Sprachen u.U. etwas vorsichtig sein: VB kennt zumindest 
and_then als schnellen Vergleich. VBA nicht (stammt aus einem nicht ganz 
freiwilligem  Experiment bzgl. Programmiersprache an dem ich mal 
teilgenommen hab und kann natürlich durch Erinnerungsfehler etwas anders 
sein)

 Tom's Code im Beitrag #5367644:
1
     static void (**p)(void) = (void(**)(void)) &F + 1;
2
     p[(mon==10 && wday==7 && day>24) - (mon==3 && wday==7 && day>24)]();
 > Sehr kompakt mit wenigen Zeilen und deshalb überaus lesbar.
 ist nicht unbedingt wegen der wenigen Zeilen lesbar und ob die 
komischen Zeichen lesbar sind hängt extrem am
 Lesenden, ABER dadurch dass die fehlende Uhrzeit
 Apollo M. schrieb:
 > ich vermisse hier noch die zeit/stunde, weil die uhr wird nicht um
 > mitternacht umgestellt.
nachweislich lesbar war ist ein sicherer Beweis für eine lesbare 
Fehlererkennung erbracht worden.
Der Fehler könnte in der Praxis je nach Implementierung sogar recht 
unterhaltsame Folgen bspw. wenn set_summer: byte hh;hh=hh+1 definiert 
ist und die Uhr am Tag der geplanten Umstellung mit maximaler 
Prozessorgeschwindigkeit die Uhr vorstellt, dann ist durch die 
Begrenzung auf ein Byte eine traditionelle Uhrzeit im Bereich 0..23 nur 
noch mit einer Wahrscheinlichkeit von unter 10% zu erwarten. Bei 
automatischer Tagumstellung nach 23:59 wäre die maximale Länge des 
letzten Sonntags nur durch die Prozessorgeschwindigkeit begrenzt 
gewesen.... :-)
vereinfacht: Fehler können Spass machen und wenn die nicht so bedrohlich 
wirken, dann können die wohl auch einfacher zu lesen sein. ==> Indiz für 
lesbaren Quelltext.

Ein netter möglicher Fehler ergäbe sich noch aus
Jobst Q. schrieb:
> Ist denn sichergestellt, dass eine wahre Bedingung +1 als Ergebnis hat?
> Soweit ich mich erinnere, ist nur Null und nicht-null festgelegt.
neuerdings ist mit C99 =>stdbool.h =>true=1 die Frage für eine seriöse 
Fehlerdarstellung wohl zu definiert, aber rein theoretisch falls Tom 
einen C95 Compiler /64bit mit true=-1 benutzt, dann
ließe sich sicher ein versuchter Sprung aus dem Programmspeicher 
vorhersagen--> praktisch optimaler Fehler

Durch die Analyse von Tom's lesbaren Code ... [gekürzt].... , aber wenn 
das SZ-flag als begründbar sicherer Bestandteil des Datums implementiert 
wird, bspw. bit 7 in hh, dann wären sowohl lesbarer Code als auch
performanterer Code praktisch unvermeidbar.
Begründung:
- lesbar:die zusammenhängenden Ereignisse 2_WZ-=>3_SZ bzw 3_SZ-=> 2_WZ 
ließen sich nur so auffällig trennen, sodass selbst ein unbewusster 
Vorsatz zu offensichtlich würde.
- Prozessorlast: der Spitzenwert an Vergleichen am Anfang der beiden 
Umstellungstage sinkt um %20
Falls das Programm an anderen Stellen ebenfalls Performance kritische 
Stellen hat, dann kann eine u.U.
aufwändige Bitmaskierung natürlich Probleme verursachen, aber ohne 
Kenntnis halbwegs definierter Problemstellen lässt sich keine 
Gesamtbelastungsbeurteilung erstellen.

Die Chance auf Realisierung für den Fall, dass der Betroffene eine 
Verbesserung eigentlich gern gesehen hätte
lässt sich mit
> Deswegen hätte ich ja gern mal die vom Compiler erzeugten
> Assemblerlistings zu obigen Konstrukten gesehen. Aber dafür reichts dann
> wieder nicht.
ziemlich sicher auszuschließen, da wenn es schon für die 
Anschaffung/Bedienung eines Compilers nicht reicht obwohl der 
realisierbare Wunsch besteht die von einem Compiler erzeugten 
Assemblerlistings zu obigen Konstrukten zu sehen, dann dürften weitere 
Barrieren bei der Umsetzung von Wünschen vorhanden sein.


Zwischenbilanz: der aktuelle Text ist ziemlich sicher zu lang und 
eigentlich wollte ich nur auf:
Jobst Q. schrieb:
> Redundanzarme Programmierung mit gemeinsamen Funktionen oder Makros für
> ähnliche Operationen bietet Fehlern weniger Möglichkeiten, sich zu
> verstecken.
>
> Die aufrufenden Funktionen werden kürzer und übersichtlicher, da kommt
> man Fehlern schneller auf die Spur. Sind sie in der aufgerufenen
> Funktion, werden sie schneller entdeckt, weil diese häufiger aufgerufen
> wird.
antworten, aber es gab da ein paar Zwischentexte.
Also die Kombination Aufrufhäufigkeit mit Parametern die eine 
automatische Fehlerentdeckung verursachen hat mit Sicherheit zu viele 
Seiteneffekte d.h. u.a. geplantes häufiges Aufrufen hat eine mögliche 
Performancerelevanz zur Folge, damit steigt die 
Untersuchungswahrscheinlichkeit und die Fehlerwahrscheinlichkeit sinkt, 
aber für zwei andere Hypothesen habe ich Indizien
a) ein nicht überprüfbares Experiment:  Kurzfassung in Stichpunkten
- Teilnahme an einer Fortbildung B.Eng u.a. Datenverarbeitung
- Versuchsteilnehmer: überwiegend Studenten die DV (in der Fortbildung 
nur eines von sehr unterschiedlichen
Modulen) eher kritisch distanziert verstehen
- ein TN der auch aus Unterhaltungsgründen ruhig in 3 Gruppen (einmal 
offiziell, 2*IM) teilnimmt und die Verwaltung des Programmcodes für alle 
3 Gruppen übernommen hat, aber - und das war das Interessante an dem 
Versuch - zweimal den persönlichen Programmierstil für den 
Prüfungsbeauftragten unleserlich im Sinne einer persönlichen 
Handschrifterkennung im Computerprogramm gestalten musste.
Resultat 1:
 - offizielle Gruppe hatte ca. 5 Seiten Programmcode (passte grob mit 
der Erwartungshaltung, keine Überraschung)
 - die beiden IM-Gruppen ca. 20 Seiten (leichte Überraschung: Zielgröße 
langes Listing ohne wirklich auffälligen Leerraum kann überraschend 
schwierig werden)
 - die nicht genau untersuchten Vergleichsgruppen müssen von einem 
Papierhersteller gesponsert gewesen sein (subjektiv gemessen)
Resultat 2: ein Ausfall in einer IM Gruppe (..manchmal gehen halt 
bestimmte Sachen nicht), aber ansonsten korrelierte sogar bei den 
individuellen Feedbackergebnissen vom unabhängigen Prüfungsbeauftragten 
der Performanceindikator mit der Papiermenge (weniger war in dem Fall 
bessere Note)
Für mich einerseits ein  guter Indikator, dass zumindest in Grenzen (gar 
kein Code ist sicher falsch ...bis ... deutlich unterdurchschnittlich 
lang) ein gewisses Optimum für unbekannt viele Möglichkeiten liegen 
könnte,
andererseits kenne ich natürlich den klassischen Messfehler:
Apollo M. schrieb:
> z.b. meine erfahrung mit gcc und avr ist, das bei umfangreichen
> bedingungen ich zwar regelmäßig switch/case bzgl. lesbarkeit mir wünsche
> aber if/else oft bessere code size liefert.
> ich bin ansonsten ein switch/case kind, weil da mache ich weniger fehler
> ...
> und habe irgendwie einen besseren überblick was sache ist.
auf deutsch: mit geeigneten Wahrnehmungen lassen sich sehr einfach die 
passenden Wünsche/Ergebnisse messen
ohne dass es auffällt.
Versuchsgruppen zu klein + undokumentiert + viele mögliche Messfehler 
==> eigentlich allenfalls als nette Story oder für interne Zwecke 
brauchbar, aber durch den zufälligen Fund eines mutmaßlich 
unveröffentlichten Freischaltcodes aktuell plausibler geworden (s.u.)

Bis hier bis auf den langen Text nichts wirklich belastbar 
interessantes, aber letztes WE ist mir eine Überraschung passiert, die 
mutmaßlich begründbar auch andere überraschen könnte:
- hobbymäßige µC Basteleien u.a. Lichtdeko.
- meine 'Standard' µC für alles Schaltbare waren 2313tiny 8k-14bit-pwm + 
8K digital
- geplantes Update 4312, weil sich rgb-kanäle als dekorativ 
herausgestellt haben und durch den verdoppelten Speicher 15PWM Kanäle 
relativ problemlos möglich sind bzw. sein sollten
- anderseits wenn schon so viel Speicher vorhanden ist, dann sollten 
mehrere lut uvm.  in den Speicher und dann wurde es wg. Interpolation 
etc. knapp mit Zeit. Sehr interessante Zusammenhänge.
vereinfacht: Situation in der viele Schritte viele kleine Verbesserungen 
bringen und alles komplizierter machen bis an anderen Stellen 
versehentlich Randbedingungen verletzt werden.

Eine Versuchsmöglichkeit: teilweise Problemübertragung auf Unbeteiligte 
d.h. eine Spekulation wenn das Problem bei einem simulierten Mega 
ähnlich ist, dann wurde entweder der problematische Code mit simuliert 
und lässt sich evtl. dort finden, ansonsten in der konkreten 
Implementation auf dem Ziel-Tiny (so etwas kann klappen, aber es ist 
keinerlei Wahrscheinlichkeit annähernd schätzbar)
Resultat: 16bit PWM mit 32Kanälen==>ca. 40% Auslastung, bei sauber 
strukturiertem hübsch sortierten Code, zig Registern etc.,--> sehr 
uneindeutig.

Nächster Versuch: aus Spass eine vom Prinzip nicht performance kritische 
Zielgröße probiert: Dateigröße bzw. Leserlichkeit: max. EINE Datei,EINE 
Textseite, keine Einzeloptimierungen
Resultat==>10%: irgendwie überraschend gut und extrem überraschend 
simpel. hmm.
Prüfliste für eine mögliche Verallgemeinerung:
Anz 8bit timer =1 : erfüllen alle mir bekannten AVR
Anz Register= 4 'hohe' d.h ein Indexregister wird 'verbraucht' + 2 
'vollwertige' aus  R16..31 + r0 r15 (tw. lässt sich das zu lasten 
anderer Kriterien optimieren) )
Speicher: 24byte sram/port
Flash=600b
Interrupts= 1, aber keine sonstigen erlaubt
ok
==> sicher induktiv beweisbar, dass für alle mir bekannten AVR eine 
Freischaltung aller 16bit-PWM Kanäle mit maximaler (untere Bits) bzw. 
F/4000 Frequenz (höhere bits) mit vertretbarem Aufwand möglich ist.
Extremfall Atmega (??) mit 5 Ports  ca. 15% Auslastung.
Max. F/2000 geht auch mit grob 3x% beim 5-port mega.
Also mit 20 MHZ *AtMega*: 34 *PWM-Kanäle* / *16*-*Bit* / 10KHz / 
ca.30% Auslastung* mEn. interessant.

Anhand einiger Beiträge aus dem Forum (bspw. einfache 12bit 16k pwm für 
3euro als Tipp bei einem vorhandenen 32K - praktisch wohl 31 - 
16bit-PWMM Mega mit deutlich reduzierter Flackerleistung) lässt sich 
plausibel begründen, dass der einfache Freischaltcode (Textdatatei 50*80 
Zeichen mit Zielgröße Lesbarkeit, also max. 3 Befehle/Zeile, sofern 
nicht bspw. nop nop nop nop o.ä. einfach lesbar wiederholt werden) 
ziemlich unbekannt ist.

Noch ein paar kurze Checks:
- ist eine absichtliche Geheimhaltung des Freischaltcodes wahrscheinlich 
plausibel?
Konzerne die 12pwm vermarkten: mutmaßlich genug anderen Spielkram im 
Portfolio--> eher nicht
Micochip bzw. Atmel (hätte genug Zeit zur Veröffentlichung gehabt): 
könnten u.U. mehr Chips insgesamt, aber weniger mit mehreren 
Hardware-PWM verkaufen.
==> albern
- kommerzielle Vermarktungsmöglichkeit?
==> eher Deko
kurz: ich glaube, dass es a) sehr wenige Menschen gibt die den 
Freischaltcode kennen, aber auch dass
b) dieses nur aus reinem Zufall so ist.

Da der Code vermutlich noch nicht öffentlich ist bietet sich mit diesem 
Beitrag bis in den April zur geplanten Veröffentlichung eine sehr 
seltene Gelegenheit sich ohne die Gefahr eines Selbstbetruges zu testen, 
was bei anderen unkontrollierten Situationen praktisch unvermeidbar ist.
Jeder Interessierte der etwas (AVR) Assembler kann und damit überhaupt 
die 'Codeanalysen' in den Beiträgen verstehen kann , kann daran 
teilnehmen. ALLE Versuche können ohne Hilfe mit eigenem heimischen PC am 
Simulator überprüft werden. ASM ist nicht so gefährlich wie C und nicht 
so geschwätzig wie Pascal, kann aber beliebig macrodiert werden, sodass 
keine Verzerrungen zu erwarten sind. Vermutlich (interessante Hypothese) 
könnten alle die den Zugang gefunden haben verschlüsselt miteinander 
kommunizieren, wüssten aber nicht wie und warum (etwas Spass, bestimmte 
Aussagen lassen sich vermutlich wirklich öffentlich austauschen, sodass 
die Beteiligten sich gegenseitig über die Kenntnis vergewissern könnten 
ohne dass 'Unwissende', also Späteinsteiger, Informationen zum 
Freischaltcode erhalten)

Im folgenden meine ich mit "die" Lösung nicht eine wirklich spezifische 
"die" Lösung, sondern eine die ungefähr mit dem Freischaltcode 
vergleichbar ist oder die aktuell am Freischaltcode ablesbar ist, formal 
ist eine Lösung ohne passendes Problem natürlich keine Lösung, aber ugs. 
wird es so verwendet und im Kontext sollte die etwas ungenaue Definition 
auch genug lesbar sein, um entscheidbare Kriterien zu haben.

An der Textversion lassen sich viele tw. mutmaßliche Eigenschaften 
ablesen:
- es ist sicher, dass es nicht die optimale Lösung ist, da im 
Freischaltcode sehr einfach Änderungsmöglichkeiten zu sehen sind, die 
aber sicher die Leserlichkeit stark beeinträchtigen würden und damit 
zumindest per Umfrage eine Situation 'beweisen' könnten die (zumindest 
tw. von diesen Beiträgen gelesen) eher ungewöhnlich ist: einfache 
Optimierung nur zu lasten der Leserlichkeit? zumindest interessant
- an anderen Stellen lässt sich ablesen, dass eine Verringerung der 
Latenz (max. Zyklenzahl im Interrupt) auf die Gesamtlast geht (u.U. eine 
Zielgröße die ansonsten gerne vergessen wird)
generell müssen bei der Lösung natürlich (?) andere Interrupts 
ausgeschlossen sein, aber max. Latenzen von <100T könnten in vielen 
Fällen das Performance-Problem relativeren.

nette Vorhersagen:
- Menschen die eine 14+bit BAM PWM implementiert haben, werden 
begründbar wahrscheinlich eine klassische Informatiker Problemsituation 
erlebt haben, aber das mutmaßliche Problem ist wahrscheinlich ein Teil 
der Lösung (getestet mit n=1)
- die Anzahl der Informationen im Sinne von  ... schwierig zu definieren 
praktisch Konzept für eine einfache  Änderung... damit die meisten ASM 
Programmieren den Freischaltcode selber schreiben könnte, dürfte ca. 4 
sein.
Vom Prinzip sehr einfach sobald  Punkte klar sind, nur vorher mutmaßlich 
schwierig.


Ich hoffe das ist ein interessantes Ostersuch Problem mit guter 
Unterhaltung, auch wenn der Text wohl seine zulässige Gesamtlänge 
maximal überschritten hat.
Viel Spass

Beitrag #5371336 wurde von einem Moderator gelöscht.
von Jobst Q. (joquis)


Lesenswert?

Karl schrieb:
> Ich bin ja immer wieder beeindruckt, wenn darauf hingewiesen wird, dass
> man mit C doch AUCH guten Code schreiben könnte.
>
> Warum wird es dann nicht gemacht?

Natürlich wird es gemacht. Der Anteil schlechten Codes an der gesamten 
Programmierung in C ist minimal, auch wenn du dich darauf spezialisiert 
hast, nur diese wahrzunehmen.

Aus der Tatsache, dass es Verkehrsunfälle gibt, kann nicht geschlossen 
werden, dass Unfälle generell nicht vermieden werden. Erst wenn die 
Anzahl Unfälle in Beziehung gesetzt wird zu den unfallfrei gefahrenen 
km, kann man eine realistische Aussage dazu treffen.

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

Dirk B. schrieb:
> Pascal hat keine offizielle Festlegung, aber praktisch alle Compiler
> benutzen SC als Vorgabe.
> Mit If (tag=24)and (monat=24) then heiligabend:
>  ist leslich

Mit der richtigen Typedef von monat würde Dir Pascal für die folgende 
Zeile sagen: Warning: unreachable code

Liebe Kinder, leider fällt die Bescherung für die nächsten Jahre aus.

Dirk B. schrieb:
> für C Ungewohnte könnte die überflüssige und nicht redundante
> Klammerung noch(!) unleserlicher sein, aber unnötige Nichtinformation
> ist in beiden Sprachen ziemlich sicher unleserlicher

Die Klammerung mag Dir überflüssig erscheinen, aber mit richtiger 
Klammerung wäre das hier: 
http://cdn3.spiegel.de/images/image-662536-860_poster_16x9-erjl-662536.jpg 
nicht passiert.

von Karl (Gast)


Lesenswert?

Jobst Q. schrieb:
> Der Anteil schlechten Codes an der gesamten
> Programmierung in C ist minimal, auch wenn du dich darauf spezialisiert
> hast, nur diese wahrzunehmen.

Nur weil Code größtenteils funktioniert heisst das noch nicht dass er 
nicht schlecht ist.

von A. S. (Gast)


Lesenswert?

Karl schrieb:
> Die Klammerung mag Dir überflüssig erscheinen, aber mit richtiger
> Klammerung wäre das hier:

so ein Knausern an Zeilen oder Zeichen ist echt nur von 1 oder 2 
Leerzeichen Einrückung zu toppen.

Bei uns hätte lint gemeckert.

Und wenn man so kleine Monitore hat, dass man den Scheiß nicht im 
Blocksatz machen kann (der dann auch viel schneller prüfbar ist), dann 
sind die selber schuld.

von Jobst Q. (joquis)


Lesenswert?

Achim S. schrieb:
> so ein Knausern an Zeilen oder Zeichen ist echt nur von 1 oder 2
> Leerzeichen Einrückung zu toppen.

Zwei Zeichen Einrückung ist doch optimal. Nicht zu übersehen, aber doch 
noch zu überblicken.

Ich stell mir gerade Karls Treppenmonstercode mit 4 oder 8 Zeichen 
Einrückung vor. Gruselig. Da bräuchte man einen halbrunden Bildschirm 
und Fischaugen, um es zu überblicken.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Ich werfe dazu einfach mal einen Buchtitel ein:

Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. 
Martin)
(gibt es meines Wissens nach auch als PDF)

Sehr lesenswert. Gerade wegen diesen riesen if-Monstern über mehr als 
fünf Ebenen. Dann erübrigt sich auch die Eingangsfrage.

Mit freundlichen Grüßen,
N.G.

von Jemand (Gast)


Lesenswert?

Sind hier auch Anhänger der umgekehrten Quadrateinrückung?
Am Beispiel des bereits geposteten Codeschnipsels:
1
                                                  void rtc_checksummer();
2
                                                  {
3
                                     if (rtc.summ and Rsauto != 0) {  // prüfen auf Flag Auto
4
                          if (rtc.wday == 7) {  // wenn Sonntag
5
                 if (rtc.day >= $25) {  // wenn letzter Sonntag im Monat
6
          if (rtc.month == $03) {  // wenn März, Umschalten auf Sommerzeit
7
     if ((rtc.summ and Rsumm) == 0 ) {  //wenn Flag nicht gesetzt
8
  if (rtc.hh == $02) {
9
 rtc.hh = $03;
10
 rtc.summ = Rsauto or Rsumm;
11
 rtc_setsummer();  // Sommerzeit schreiben
12
  };
13
     };
14
          } else if (rtc.month == $10) {  // wenn Oktober, Umschalten auf Winterzeit
15
     if ((rtc.summ and Rsumm) != 0) {  //wenn Flag gesetzt
16
  if (rtc.hh == $03) {
17
 rtc.hh = $02;
18
 rtc.summ = Rsauto;
19
 rtc_setsummer();  // Winterzeit schreiben
20
  };
21
     };
22
          };
23
                 };
24
                          };
25
                                     };
26
                                                  };

von Karl (Gast)


Lesenswert?

N. G. schrieb:
> Clean Code: A Handbook of Agile Software Craftsmanship (Robert C.
> Martin)
> (gibt es meines Wissens nach auch als PDF)
> Sehr lesenswert.

Echt jetzt? Ich hab mal die als pdf verfügbaren "free sample chapters" 
überflogen: Ein Haufen Geschwätz, witzige Bildchen und zusammengetragene 
Zitate von diversen "Software-Gurus".

Nicht ein einziges Beispiel, wo man mal sieht worum es dem Typen geht. 
Wenn ich Computer-Belletristik will, hole ich mir ein Buch von Elsberg 
oder Suarez.

von Drrrtrr (Gast)


Lesenswert?

Karl schrieb:
> N. G. schrieb:
> Clean Code: A Handbook of Agile Software Craftsmanship (Robert C.
> Martin)
> (gibt es meines Wissens nach auch als PDF)
> Sehr lesenswert.
>
> Echt jetzt? Ich hab mal die als pdf verfügbaren "free sample chapters"
> überflogen: Ein Haufen Geschwätz, witzige Bildchen und zusammengetragene
> Zitate von diversen "Software-Gurus".
>
> Nicht ein einziges Beispiel, wo man mal sieht worum es dem Typen geht.
> Wenn ich Computer-Belletristik will, hole ich mir ein Buch von Elsberg
> oder Suarez.

Signalwort agile sollte da doch schon alles sagen, spätestens bei 
Craftsmanship hättest das Lesen aufhören können.

von Jay W. (jayway)


Lesenswert?

Jemand schrieb:
> Sind hier auch Anhänger der umgekehrten Quadrateinrückung?

Das nicht, aber Code sollte schon ästhetischen Ansprüchen genügen. ;-)
1
#!/usr/bin/perl -w                                      
2
use strict;
3
4
5
                                           $_='ev
6
                                       al("seek\040D
7
           ATA,0,                  0;");foreach(1..3)
8
       {<DATA>;}my               @camel1hump;my$camel;
9
  my$Camel  ;while(             <DATA>){$_=sprintf("%-6
10
9s",$_);my@dromedary           1=split(//);if(defined($
11
_=<DATA>)){@camel1hum        p=split(//);}while(@dromeda
12
 ry1){my$camel1hump=0      ;my$CAMEL=3;if(defined($_=shif
13
        t(@dromedary1    ))&&/\S/){$camel1hump+=1<<$CAMEL;}
14
       $CAMEL--;if(d   efined($_=shift(@dromedary1))&&/\S/){
15
      $camel1hump+=1  <<$CAMEL;}$CAMEL--;if(defined($_=shift(
16
     @camel1hump))&&/\S/){$camel1hump+=1<<$CAMEL;}$CAMEL--;if(
17
     defined($_=shift(@camel1hump))&&/\S/){$camel1hump+=1<<$CAME
18
     L;;}$camel.=(split(//,"\040..m`{/J\047\134}L^7FX"))[$camel1h
19
      ump];}$camel.="\n";}@camel1hump=split(/\n/,$camel);foreach(@
20
      camel1hump){chomp;$Camel=$_;y/LJF7\173\175`\047/\061\062\063\
21
      064\065\066\067\070/;y/12345678/JL7F\175\173\047`/;$_=reverse;
22
       print"$_\040$Camel\n";}foreach(@camel1hump){chomp;$Camel=$_;y
23
        /LJF7\173\175`\047/12345678/;y/12345678/JL7F\175\173\0 47`/;
24
         $_=reverse;print"\040$_$Camel\n";}';;s/\s*//g;;eval;   eval
25
           ("seek\040DATA,0,0;");undef$/;$_=<DATA>;s/\s*//g;(   );;s
26
             ;^.*_;;;map{eval"print\"$_\"";}/.{4}/g; __DATA__   \124
27
               \1   50\145\040\165\163\145\040\157\1 46\040\1  41\0
28
                    40\143\141  \155\145\1 54\040\1   51\155\  141
29
                    \147\145\0  40\151\156 \040\141    \163\16 3\
30
                     157\143\   151\141\16  4\151\1     57\156
31
                     \040\167  \151\164\1   50\040\      120\1
32
                     45\162\   154\040\15    1\163\      040\14
33
                     1\040\1   64\162\1      41\144       \145\
34
                     155\14    1\162\       153\04        0\157
35
                      \146\     040\11     7\047\         122\1
36
                      45\15      1\154\1  54\171          \040
37
                      \046\         012\101\16            3\16
38
                      3\15           7\143\15             1\14
39
                      1\16            4\145\163           \054
40
                     \040            \111\156\14         3\056
41
                    \040\         125\163\145\14         4\040\
42
                    167\1        51\164\1  50\0         40\160\
43
                  145\162                              \155\151
44
                \163\163                                \151\1
45
              57\156\056

Beitrag #5371859 wurde von einem Moderator gelöscht.
Beitrag #5371866 wurde von einem Moderator gelöscht.
Beitrag #5371886 wurde von einem Moderator gelöscht.
von Possetitjel (Gast)


Lesenswert?

Karl schrieb:

> Ich hab mal die als pdf verfügbaren "free sample chapters"
> überflogen: Ein Haufen Geschwätz, witzige Bildchen und
> zusammengetragene Zitate von diversen "Software-Gurus".

Vielleicht hättest Du mehr als das Vorwort lesen sollen.

Wobei: Niemand soll gezwungen werden dazuzulernen, auch Du
nicht.

Beitrag #5371912 wurde von einem Moderator gelöscht.
Beitrag #5371985 wurde von einem Moderator gelöscht.
Beitrag #5372033 wurde von einem Moderator gelöscht.
von Großer Zeh (Gast)


Lesenswert?

Possetitjel schrieb:

> Wobei: Niemand soll gezwungen werden dazuzulernen, auch Du
> nicht.


Die Frage ist: WILL man sich mit einer Sprache und einer solch häßlichen 
Syntax und Regeln für diese, die einem Würfelspiel gleichen, wirklich 
den Kopf vollstopfen? Normalerweise will man doch einen Algorithmus in 
einen Quelltext überseztzen und sich nicht mit einer Diva von 
Programmiersprache um jedes Sonderzeichen streiten.

Beitrag #5372148 wurde von einem Moderator gelöscht.
Beitrag #5372248 wurde von einem Moderator gelöscht.
Beitrag #5372304 wurde von einem Moderator gelöscht.
von Possetitjel (Gast)


Lesenswert?

Großer Zeh schrieb:

> Possetitjel schrieb:
>
>> Wobei: Niemand soll gezwungen werden dazuzulernen,
>> auch Du nicht.
>
> Die Frage ist: WILL man sich mit einer Sprache und
> einer solch häßlichen Syntax und Regeln für diese,
> die einem Würfelspiel gleichen, wirklich den Kopf
> vollstopfen?

Nun ja, was heisst "wollen"?

C hat ein paar Alleinstellungsmerkmale, und wenn man
die benötigt, hat man keine Wahl. Das ist ja inzwischen
oft genug durchdiskutiert worden.

Ich akzeptiere das auch ohne Groll, denn ich lerne
allmählich unterscheiden, was echte Ausdruckskraft
ist und was unnützer syntaktischer Zucker (wobei die
Zuschreibung "unnütz" natürlich subjektiv ist.)


> Normalerweise will man doch einen Algorithmus in
> einen Quelltext überseztzen und sich nicht mit einer
> Diva von Programmiersprache um jedes Sonderzeichen
> streiten.

Sicher -- nur wenn man das Können der Diva braucht,
muss man die Gage halt bezahlen.
Wenn nicht, dann nicht.

von Karl (Gast)


Lesenswert?

Großer Zeh schrieb im Beitrag #5372248:
> Soll man wirklich eine Programmiersprache erlernen, die die Fähigkeit,
> sich normal auszudrücken, so sehr zerstört?

Wieso gehst Da davon aus, dass er überhaupt eine Programmiersprache 
kann? Das ist ein Philosophiestudent im 20. Semester, der aus Versehen* 
über die Feiertage in der Unibibliothek eingeschlossen wurde.

*) über das "aus Versehen" können wir noch diskutieren.

von Karl (Gast)


Lesenswert?

Possetitjel schrieb:
> C hat ein paar Alleinstellungsmerkmale, und wenn man
> die benötigt, hat man keine Wahl.

Als da wären?

Typecast geht sogar unter Ada, wenn auch nicht so locker flockig ohne 
Prüfung aus der Hand.

von Teo D. (teoderix)


Lesenswert?

Sorry Leute,
hätt ich gewusst das mein Post ein Lawine von Geschwafel lostritt, hätt 
ichs gelassen. :D

von Possetitjel (Gast)


Lesenswert?

Karl schrieb:

> Possetitjel schrieb:
>> C hat ein paar Alleinstellungsmerkmale, und wenn man
>> die benötigt, hat man keine Wahl.
>
> Als da wären?

Das Zusammentreffen von
- Normung,
- Trennung von Sprachkern und Standardbibliothek,
- "kleinem" Sprachkern und
- "unvollständiger" Abstraktion.

Das prädestiniert C für den unübersehbaren Zoo von
mittelgroßen, kleinen und kleinsten Maschinen.

All das wurde hier aber schon x Mal durchgekaut.

Beitrag #5372644 wurde von einem Moderator gelöscht.
von Carl D. (jcw2)


Lesenswert?

Wichtig ist, Programme so zu schreiben, daß der Leser versteht, was man 
dem Compiler sagen wollte.
Das gilt auch für Texte, deren Inhalt nicht an Compiler übergeben werden 
soll. Manche "Schriftsteller" schreiben aber so, daß es keiner lesen 
will/kann und sollten sich dann nicht wundern, wenn ihre Gedanken nicht 
verstanden werden.
Kurz: wer klare Programmiersprachen fordert, sollte keine "Dirk"-Texte 
schreiben.

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

Possetitjel schrieb:
> Das Zusammentreffen von...

Ja und? Ist doch in anderen Sprachen auch möglich. Das ist kein 
Alleinstellungsmerkmal.

Du glaubst nur, dass das nur in C geht, weil Du es nur in C kennst.

von (prx) A. K. (prx)


Lesenswert?

Die Syntax einer Programmiersprache prägt das Denken m.E. nicht so sehr. 
Das wird erkennbar, wenn man sich von Details löst und einen etwas 
breiteren Hintergrund sucht. Ob man Sonderzeichen schüttelt oder 
Keywords ist wenig relevant, solange das Paradigma der Sprache sich 
nicht ändert. Und da fallen imperative Sprachen wie C, Pascal und auch 
Fortran alle in die gleiche Kategorie.

Diese Ähnlichkeit von Sprachen, über deren Unterschiede sich viele Leute 
streiten wie die Kesselflicker, fällt besonders dann auf, wenn man in 
Sprachen reinschnuppert, die nicht dazu gehören. Ein krasser Fall aus 
der Vorzeit ist beispielsweise Prolog. Da kommt man mit prozeduralem 
Denken nicht weit, weil gibts nicht, der Quelltext beschreibt keine 
Abläufe. Erfahrungen mit imperativen Sprachen nützen hier nichts.

Wer es weniger krass und etwas aktueller haben will, der schaue sich 
funktionale Sprachen an.

Beitrag #5372737 wurde von einem Moderator gelöscht.
Beitrag #5372755 wurde von einem Moderator gelöscht.
von W.S. (Gast)


Lesenswert?

A. K. schrieb:
> Die Syntax einer Programmiersprache prägt das Denken m.E. nicht so sehr.
> Das wird erkennbar, wenn man..

..alles in einen so großen Rahmen stellt, daß sämtliche Details verloren 
gehen.

Nee, wie sehr gerade C das Denken und die Denkfähigkeit beeinträchtigt, 
kann man hier in diesem Forum sehr gut beobachten.

Das eigentlich Erstaunliche dabei ist, wie sehr sich gerade C 
ausgebreitet hat. Ausgerechnet diese Krücke, und das bei Anwesenheit von 
besseren Alternativen.

Jetzt könnte man darüber räsonnieren, ob es der Drang nach der Heldentat 
ist, der die Programmierer zu C getrieben hat, oder ob es der Wunsch 
war, etwas möglichst kryptisches zu betreiben, wo der Chef und alle 
anderen möglichst wie das berühmte Schwein ins Uhrwerk schauen. 
Schlichtweg der Drang nach Geheimniskrämerei zwecks persönlicher 
Vorteile.

W.S.

Beitrag #5372806 wurde von einem Moderator gelöscht.
von W.S. (Gast)


Lesenswert?

Possetitjel schrieb:
> Was ist upn?

97
3+
4*
ergibt 400

Zu jung, um einen HP-Taschenrechner gekannt zu haben?

Ich benutze sowas in leicht abgeänderter Weise gern für Steuersequenzen 
zwischen PC und µC per seriell oder USB, weil man damit atomare 
Operationen hat, die sich gut erweitern lassen und weil das Ganze im µC 
leicht dekodierbar ist. Zum Beispiel beim Wobbler:

3500000A1000S300N2W
Das wobbelt das 80M Band mit 1kHz Schritten 2x durch.

klaro?

W.S.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> ..alles in einen so großen Rahmen stellt, daß sämtliche Details verloren
> gehen.

Das Prinzip dahinter nennt sich Abstraktion. Liegt nicht jedem.

Mir ist es für die Denkweise in einer Sprache ziemlich egal, ob
 if (...) { ... }
oder
 if ... then ... endif
verwendet wird.

Zur Erinnerung: Ich schrieb ausdrücklich über die Syntax.

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

A. K. schrieb:
> if ... then ... endif

Das UPN Forth if geht in etwa so:
1
true / flag auf den Stack legen
2
3
if
4
  / tue dieses hier, wenn flag = true
5
else
6
  / tue dieses hier, wenn flag = false
7
then
8
/ hier gehts normal weiter
Hat auch seinen Reiz, finde ich....

von (prx) A. K. (prx)


Lesenswert?

Arduino F. schrieb:
> Hat auch seinen Reiz, finde ich....

Ist aber in diesem Fall genauso imperativ, sieht also nur anders aus, 
arbeitet aber gleich. Interessant wird es bei FORTH, wenn man die 
Dynamik der Sprache in Rechnung stellt, d.h. sich damit inkrementell 
eine eigene Sprache schafft.

Immerhin können FORTH Worte bereits zur Zeitpunkt der Übersetzung aktiv 
werden, nicht erst mit der Ausführung, was von Worten wie IF/THEN zur 
Umsetzung in den internen Code genutzt wird. Dann schafft sich das 
Programm quasi eine eigene anwendungsbezogene Syntax.

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

W.S. schrieb:

> Possetitjel schrieb:
>> Was ist upn?
>
> 97
> 3+
> 4*
> ergibt 400

Klar. Kann mich nur nicht entsinnen, mal mit Karl über
"Umgekehrte polnische Notation" diskutiert zu haben;
seine Referenz auf "goto" dagegen war mir verständlich.


> Zu jung, um einen HP-Taschenrechner gekannt zu haben?

Nein -- auf der falschen Seite der Mauer gelebt.

von Einer K. (Gast)


Lesenswert?

A. K. schrieb:
> , d.h. sich damit inkrementell
> quasi eine eigene Sprache schafft.

In C muss man das Problem solange durchkauen, bis man es in der Sprache 
abhandeln kann.

In Forth wird die Sprache solange modifiziert, bis sie das Problem 
optimal widerspiegelt.

Meinst du das so, in etwa?

Beitrag #5372848 wurde von einem Moderator gelöscht.
von (prx) A. K. (prx)


Lesenswert?

Arduino F. schrieb:
> Meinst du das so, in etwa?

Schau dir beispielsweise mal an, wie Strings in FORTH übersetzt werden. 
Da steht beispielsweise
 ." Text"
im Quelltext. Aber es gibt keine zentral in einem Übersetzer fixierte 
Syntax dazu, denn das Word
 ."
wird bei der Übersetzung sofort ausgeführt, liest den Quelltext bis zum 
" ein, und macht daraus die interne Darstellung. Es wird also Teil des 
Übersetzungsprozesses.

Da der Quelltext hinter ." ausschliesslich vom Code in diesem ." 
bestimmt wird, und ein Programm beliebig andere solcher Worte definieren 
kann, kann also die Syntax des Quelltextes in hohem Mass von Programm 
selbst definiert werden.

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

W.S. schrieb:
> Das eigentlich Erstaunliche dabei ist, wie sehr sich gerade C
> ausgebreitet hat. Ausgerechnet diese Krücke, und das bei Anwesenheit von
> besseren Alternativen.

Dann zeige doch mal eine einzige, die auf µC, hardwarenah oder einfach 
(Beschreibung/Umsetzung/zuverlässigkeit) auch nur annähernd heranreicht. 
Bis dahin fürchte ich, hat Frau Merkel recht mit ihrem Alternativlos.


Ein gutes Argument wäre z.B., wenn die Sprache in ihrem Kern sich im 
Wesentlichen selber übersetzt, und nicht per C-Compiler Assembler-Code 
erzeugt.

von (prx) A. K. (prx)


Lesenswert?

Dirk B. schrieb im Beitrag #5372848:
> Programmierte die noch nicht so
> eine eigene Denkfähigkeit haben die Denkfähigkeit beeinträchtigt,

Zwar sind Parser natürlicher Sprachen wesentlich flexibler als die von 
Programmiersprachen, kommen aber trotzdem manchmal an ihre Grenzen.

von (prx) A. K. (prx)


Lesenswert?

Achim S. schrieb:
> Ein gutes Argument wäre z.B., wenn die Sprache in ihrem Kern sich im
> Wesentlichen selber übersetzt, und nicht per C-Compiler Assembler-Code
> erzeugt.

Womit wir wieder bei FORTH wären. Denn genau das geschieht da.

von Rolf M. (rmagnus)


Lesenswert?

Jobst Q. schrieb:
> Achim S. schrieb:
>> so ein Knausern an Zeilen oder Zeichen ist echt nur von 1 oder 2
>> Leerzeichen Einrückung zu toppen.
>
> Zwei Zeichen Einrückung ist doch optimal. Nicht zu übersehen, aber doch
> noch zu überblicken.
>
> Ich stell mir gerade Karls Treppenmonstercode mit 4 oder 8 Zeichen
> Einrückung vor. Gruselig. Da bräuchte man einen halbrunden Bildschirm
> und Fischaugen, um es zu überblicken.

Wenn du das Problem hast, sind deine Funktionen zu kompliziert. Wobei 8 
Zeichen wirklich übertrieben ist. Zwei sind mir aber dann doch zu wenig. 
Ich hab für mich 4 als Optimum gefunden.

Beitrag #5372885 wurde von einem Moderator gelöscht.
von Einer K. (Gast)


Lesenswert?

A. K. schrieb:
> Aber es gibt keine fixierte Syntax dazu,

Naja, es ist schon etwas vermessen, bei Forth von einer Syntax zu reden.

Mit fallen da nur wenige Regeln ein...
1. Forth Worte werden durch WhiteSpaces voneinander getrennt.
2. Es können nur Worte genutzt werden welche vorher definiert wurden.

Zu 2 gibt es die 1/2 Ausnahme, z.B. dass das Wort RECURSIVE, üblicher 
weise, das Attribut IMMEDIATE hat, also zur Kompilezeit ausgeführt wird. 
RECURSIVE kompiliert einen Aufruf auf das Wort, welches gerade 
kompiliert wird in den Code.

A. K. schrieb:
> Schau dir beispielsweise mal an, wie Strings in FORTH übersetzt
> werden.

." ist ein kompilierendes Wort.
Es hat auch das Attribut IMMEDIATE

Mein Decompiler sagt, dass ." bei mir so definiert ist:
1
: ."    COMPILE (.") ," ; IMMEDIATE


Mein Decompiler sagt zu if:
1
: IF    ?COMP HERE 2 CELLS - @ DUP lit COMPILE = SWAP lit LIT 
2
                = OR 0= HERE CELL - @ lit DUP = AND 
3
                IF      CELL NEGATE ALLOT COMPILE -?BRANCH 
4
                        
5
                ELSE    COMPILE ?BRANCH 
6
                THEN    >MARK 2 ; IMMEDIATE


Ich sage es gerne so....
Forth Worte haben Attribute:
1. Sie haben einen Namen (darüber werden sie im Vocabulary gefunden)
2. Sie haben ein Laufzeitverhalten
3. Sie haben ein Kompilezeitverhalten.
4. Sie tragen Werte/Parameter in sich

1 ist immer der Fall
2 bis 4 muss nicht unbedingt zum tragen kommen

-------

A. K. schrieb:
> Achim S. schrieb:
>> Ein gutes Argument wäre z.B., wenn die Sprache in ihrem Kern sich im
>> Wesentlichen selber übersetzt, und nicht per C-Compiler Assembler-Code
>> erzeugt.
>
> Womit wir wieder bei FORTH wären. Denn genau das geschieht da.
Sehe ich auch so!

von Jobst Q. (joquis)


Lesenswert?

Rolf M. schrieb:
> Wenn du das Problem hast, sind deine Funktionen zu kompliziert. Wobei 8
> Zeichen wirklich übertrieben ist. Zwei sind mir aber dann doch zu wenig.


Ich bin kein Freund von langen Treppen und weiß auch wie sie zu 
vermeiden sind. Siehe: 
Beitrag "Re: Art der if-Auswahl nur Geschmackssache?"

Aber manchmal hab ich längere Funktionen, die nur mit großem Aufwand 
aufzuteilen wären. In denen sind dann bis zu 6 Einrückungen, da wär mir 
mit 4 Zeichen Einrückung der Text schon manchmal unangenehm breit,zumal 
ich in dem Alter bin, wo man große Schriften bevorzugt.

> Ich hab für mich 4 als Optimum gefunden.
Ist ja auch ok.Ich will mein Optimum ja auch nicht anderen vorschreiben.

von Dirk B. (Gast)


Lesenswert?

Possetitjel schrieb:
>Warum wird dann -- teils erbittert -- über die Formatie-
>rung von Quelltexten gestritten?
eine plausible Erklärung wäre: weil es für Formatierungen keine (in 
Grenzen) keine entscheidbar besser/schlechter/richtig/falsch geben kann 
und somit jeder Recht hat und alle anderen die falsche Formatierung 
benutzen (ungefähr) und vor allem ist das Risiko erkennbar falsch zu 
liegen sicher 0.

Mein Beitrag mit dem Vorschlag 32 16bit zum Suchspiel zu nutzen wurde 
wohl völlig anders verstanden als es gemeint war (und ist wohl auch sehr 
unglücklich formuliert) aber wenn die Erbitterung es verbietet einfach 
den Autor in ganzen Sätzen anzuschreiben, dann fallen solche Fehler 
nicht auf und erzeugen wohl zig Geschwafel Lawinen.

von W.S. (Gast)


Lesenswert?

Dirk B. schrieb im Beitrag #5372848:
> In diesem Forum können...
..schwafel...schwafel...
> beeinträchtigt,

Mein lieber Junge, es kommt nicht drauf an, wieviele sinnlose Wörter man 
aneinanderreihen kann, um irgend etwas zu ignorieren.

Ich bevorzuge klare und prägnante Sätze.

Aber um sowas zu können, mußt du noch sehr üben.

Da fällt mir der gute Herbert ein (Wehner), über den sich mal ein 
Kabarettist etwa so ausgelassen hat:

"Meine Damen und Herren,

mir wird hier des Öfteren vorgeworfen, ich übte Polemik.

Nein.

ICH habe das nicht nötig.

Sie, meine Damen und Herren, müssen das noch üben."

W.S.

von W.S. (Gast)


Lesenswert?

Achim S. schrieb:
> Dann zeige doch mal eine einzige, die auf µC, hardwarenah oder einfach
> (Beschreibung/Umsetzung/zuverlässigkeit) auch nur annähernd heranreicht.

Dazu ist es so etwa 30 Jahre zu spät. Man hätte Pascal oder noch früher 
Algol nehmen können. Aber dafür ist es JETZT zu spät.

Vergleiche doch mal sowas:
1
#define FIOPIN (*((volatile unsigned long *) 0x3FFFC014))
2
3
var
4
 FIOPIN : dword absolute $3FFFC014;

Merkst du, was für eine elende Cast-Hampelei das in C ist?
Aber mir ist hier nicht danach, wieder das alte Gezänk 
heraufzubeschwören. Also merken wir uns eines: Daß nämlich 
Fehlentscheidungen irgendwann nicht mehr korrigierbar sind.

W.S.

von A. S. (Gast)


Lesenswert?

W.S. schrieb:
> Fehlentscheidungen

Ja, ne, is klar.

von Karl (Gast)


Lesenswert?

W.S. schrieb:
> Man hätte Pascal oder noch früher
> Algol nehmen können. Aber dafür ist es JETZT zu spät.

Warum? Mit Ada ging und geht das durchaus. Aber in Ada kann man halt 
nicht so schön wild rumcasten und rumpointern.

Und für Pascal gibt es durchaus brauchbare Compiler für Mikrocontroller.

Hab gerade ein komplettes Projekt für AVR von C nach Pascal 
transferiert. Das macht richtig Spass.

Und auf ARM und ARM Embedded läuft zur Zeit auch Einiges in Pascal. Das 
muss sich hinter C keineswegs verstecken.

Das Einzige, was die Leute an C bindet ist ihr eigener begrenzter 
Horizont.

von Karl (Gast)


Lesenswert?

Achim S. schrieb:
> Ja, ne, is klar.

Jap, oder wie mein Info-Prof zu sagen pflegte: Millionen Fliegen können 
nicht irren...

Beitrag #5375036 wurde von einem Moderator gelöscht.
Beitrag #5375047 wurde von einem Moderator gelöscht.
von W.S. (Gast)


Lesenswert?

Karl schrieb:
> Und für Pascal gibt es durchaus brauchbare Compiler für Mikrocontroller.

Meinst du Mikroe oder was anderes?

W.S.

Beitrag #5375161 wurde von einem Moderator gelöscht.
Beitrag #5375167 wurde von einem Moderator gelöscht.
von Teo D. (teoderix)


Lesenswert?

Könnt Ihr Bitte damit aufhören, Danke!
Ich dachte nämlich, ich lerne hier noch ein paar Eigenheiten von C 
kennen. :(

von Dirk B. (Gast)


Lesenswert?

Teo D. schrieb:
> Ich dachte nämlich, ich lerne hier noch ein paar Eigenheiten von C
> kennen. :(
Die paar Eigenheiten von C die du schon kennst wären da für einige 
Menschen eine  interessante Information, da C häufig zur Programmierung 
genutzt wird und etwas mit eigenen Eigenheiten sich nicht dafür eignet.

von Karl (Gast)


Lesenswert?

Teo D. schrieb:
> Ich dachte nämlich, ich lerne hier noch ein paar Eigenheiten von C
> kennen.

Du meinst so lustige Sachen wie:
1
char c1;
2
c1 = ~0x80;
3
if (c1 == ~0x80)
4
// True oder False?

Na, wie gehts nach dem if weiter? Ist der Vergleich True oder False?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Karl schrieb:
> Du meinst so lustige Sachen wie:

Du meinst so falsche Sachen wie...

Karl schrieb:
> Na, wie gehts nach dem if weiter? Ist der Vergleich True oder False?

Die Frage stellt sich nicht, eben weil der Code fehlerhaft ist. Und 
jeder Compiler wird dir das sagen. Hör doch auf mit den konstruierten 
beispielen...

von Karl (Gast)


Lesenswert?

Michael R. schrieb:
> Die Frage stellt sich nicht, eben weil der Code fehlerhaft ist. Und
> jeder Compiler wird dir das sagen.

Der Compiler-Explorer meldet keinen Fehler, der bringt nur eine Warnung. 
Und witzigerweise bringt der die Warnung nur bei char, uint8_t oder 
int8_t. Und nur bei der Zuweisung, nicht beim Vergleich.

int16_t c2; c2 = ~0x8000; wird klaglos akzeptiert, obwohl es genauso 
einen Overflow erzeugen würde.

> Hör doch auf mit den konstruierten
> beispielen...

Wenn Du C auf AVR programmieren würdest, wüsstest Du, dass eine 
Zuweisung mit ~(1 << 7) zum Setzen aller Bits ausser Bit 7, oder zum 
Löschen von Bit 7 per AND völlig normal und gängige Praxis ist. Und 
genau das ist ~0x80.

von Sepp (Gast)


Lesenswert?

Karl schrieb:
> Der Compiler-Explorer meldet keinen Fehler, der bringt nur eine Warnung.
> Und witzigerweise bringt der die Warnung nur bei char, uint8_t oder
> int8_t. Und nur bei der Zuweisung, nicht beim Vergleich.
>
> int16_t c2; c2 = ~0x8000; wird klaglos akzeptiert, obwohl es genauso
> einen Overflow erzeugen würde.

Das was du Zuweisung nennst ist eine Operation mit nachfolgender 
Zuweisung. Da du den type von 0x80 nicht definiert hast nimmt der 
Compiler einfach eine Standardeinstellung her (in deinem Fall uint16_t).

Somit ist dein ~0x80 nicht 0x7F sondern 0xFF7F, und das parst der 
compiler dir nicht sauber in uint8_t, deswegen die Warnung.

Karl schrieb:
> Wenn Du C auf AVR programmieren würdest, wüsstest Du, dass eine
> Zuweisung mit ~(1 << 7) zum Setzen aller Bits ausser Bit 7, oder zum
> Löschen von Bit 7 per AND völlig normal und gängige Praxis ist. Und
> genau das ist ~0x80.

Dein Bitshift wird anders behandelt als die Zahl, der bekommt vom 
compiler den minimal möglichen Datentyp, und das ist nun mal uint8_t in 
deinem Fall, würdest du um 9 bits shiften, dann wäre es ein uint16_t.

von Karl (Gast)


Lesenswert?

Sepp schrieb:
> Das was du Zuweisung nennst ist eine Operation mit nachfolgender
> Zuweisung.

Ach,
  ldi r24,lo8(127)
  std Y+1,r24
ist keine Zuweisung?

Sepp schrieb:
> Dein Bitshift wird anders behandelt als die Zahl, der bekommt vom
> compiler den minimal möglichen Datentyp

Wird er nicht: c1 = ~(1<<7); liefert genau die gleiche Warnung und im 
Compilat genau das gleiche falsche Ergebnis.

Bei
1
  uint16_t c1;
2
  c1 = ~(1<<15);
3
  if (c1 == ~(1<<15)) {
4
    is_true();
5
  } else {
6
    is_false(); 
7
  }
8
  uint8_t c2;
9
  c2 = ~(1<<7);
10
  if (c2 == ~(1<<7)) {
11
    is_true();
12
  } else {
13
    is_false(); 
14
  }

im GCC liefert der erste Fall true, der zweite Fall false.

von Sepp (Gast)


Lesenswert?

Karl schrieb:
> Ach,
>   ldi r24,lo8(127)
>   std Y+1,r24
> ist keine Zuweisung?

>lo8(x)
ist die Operation (das Parsen) vor der Zuweisung und entspricht 
((x)&0xff)
>lo8(127)
zeigt aber, dass das nicht alles ist, denn
>~0x80
ergibt in dem von dir erwähnten Fall nie
>127
sondern 65407.

Ich denke du mischt 8 und 16-Bit AVRs.
Denn den Fehler bekommst du so bei einem 16bit AVR und dein Compilat in 
der Form bei einem 8bit AVR.

Karl schrieb:
> Wenn Du C auf AVR programmieren würdest, wüsstest Du, dass eine
> Zuweisung mit ~(1 << 7) zum Setzen aller Bits ausser Bit 7, oder zum
> Löschen von Bit 7 per AND völlig normal und gängige Praxis ist. Und
> genau das ist ~0x80.

Karl schrieb:
> Wird er nicht: c1 = ~(1<<7); liefert genau die gleiche Warnung und im
> Compilat genau das gleiche falsche Ergebnis.

Also ist ~(1<<7) doch nicht ~0x80 wie vorher behauptet?

von (prx) A. K. (prx)


Lesenswert?

Sepp schrieb:
> Dein Bitshift wird anders behandelt als die Zahl

Nein. (1<<7) ist vom Type her stets identisch mit 0x80. Aber (1<<15) ist 
nicht notwendigerweise identisch mit 0x8000.

Sepp schrieb:
> Also ist ~(1<<7) doch nicht ~0x80 wie vorher behauptet?

Doch. Aber (int)(uint8_t)~0x80 ist nicht gleich ~0x80.

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.