Forum: Mikrocontroller und Digitale Elektronik logischer Ausdruck in c mit und :


von einbaer_klein (Gast)


Lesenswert?

Hallo Ihr Lieben,

könnt Ihr mir sagen, was dieser logische Ausdruck in C bedeutet:

adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000)

mit ? und : ist mir das unbekannt.

Vielen Dank für Eure Hilfe und bleibt gesund

von Zugvogel (Gast)


Lesenswert?

Das ist eine andere Schreibweise für die If-Abfrage: 
https://www.peacesoftware.de/ckurs6.html

von EAF (Gast)


Lesenswert?

Das ist der "Ternary Operator"

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Die Eingabe von "c fragezeichen operator" bei Google hilft weiter.

Konkret hier muss hier auf die Klammernsetzung geachtet werden, 
übersetzt heisst das:

Wenn RECORD_EIGHT_BITS != 0, wird adcFrequency mit 20000 verglichen, 
sonst mit 10000.

von EAF (Gast)


Lesenswert?

Zugvogel schrieb:
> Das ist eine andere Schreibweise für die If-Abfrage:
Das ist falsch!

Die if abfrage ist Kontrollfluss orientiert, und hat darum auch keine 
Probleme mit "Sequence Points".
Der "Ternäre Operator" ist Datenfluss orientiert.

Es sind also gänzlich andere Anwendungsgebiete.

von Erwin D. (Gast)


Lesenswert?

einbaer_klein schrieb:
> Hallo Ihr Lieben,
>
> könnt Ihr mir sagen, was dieser logische Ausdruck in C bedeutet:
>
> adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000)
>
> mit ? und : ist mir das unbekannt.
>
> Vielen Dank für Eure Hilfe und bleibt gesund

Das ist der sog. ternäre Operator (Suchbegriff)

Er wertet einen boolschen Ausdruck aus und gibt als Ergebnis einen von 
zwei durch Doppelpunkt getrennte Ausdrücken zurück, je nach dem, ob der 
boolsche Ausdruck true oder false ergibt.

von Pott (Gast)


Lesenswert?

EAF schrieb:
> Zugvogel schrieb:
>> Das ist eine andere Schreibweise für die If-Abfrage:
> Das ist falsch!
>
> Die if abfrage ist Kontrollfluss orientiert, und hat darum auch keine
> Probleme mit "Sequence Points".
> Der "Ternäre Operator" ist Datenfluss orientiert.
>
> Es sind also gänzlich andere Anwendungsgebiete.

Richtig. Der Ternäre Operator wird daher auch oft als "cmov" 
(conditional move, x86) übersetzt.

von Franz (Gast)


Lesenswert?

1
adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000)

Das ist extrem schlechter Programmierstil.

Programmtext soll immer einfach und verständlich sein:
1
bool RECORD_EIGHT_BITS=false;
2
bool result_flag;
3
4
if (RECORD_EIGHT_BITS) result = adcFrequency > 20000;
5
else result_flag = adcFrequency > 10000;

Und selbst das ist noch schlecht, weil ein groß geschriebenes 
"RECORD_EIGHT_BITS" auf ein "define" hindeutet.

von MaWin (Gast)


Lesenswert?

Franz schrieb:
> Das ist extrem schlechter Programmierstil.

Nein.
Es ist deutlich lesbarer als deine Spaghettialternative.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Franz schrieb:
> Das ist extrem schlechter Programmierstil.

Das ist Ansichtssache. Der ursprüngliche Ausdruck gibt den Sachverhalt 
kurz und knackig an. Lesbar ist es überdies auch noch, da der boolsche 
Ausdruck auch nicht gerade kompliziert ist.

Also wen das schon überfordert, sollte sich eine andere 
Programmiersprache suchen.

von (prx) A. K. (prx)


Lesenswert?

Pott schrieb:
> Richtig. Der Ternäre Operator wird daher auch oft als "cmov"
> (conditional move, x86) übersetzt.

Das kann dir bei if auch passieren.

von Johannes S. (Gast)


Lesenswert?

Franz schrieb:
> Und selbst das ist noch schlecht, weil ein groß geschriebenes
> "RECORD_EIGHT_BITS" auf ein "define" hindeutet.

Warum sollte es kein define sein dürfen? Es kann auch statisch sein und 
von einer Konfiguration zur Kompilierzeit abhängen.

von EAF (Gast)


Lesenswert?

Franz schrieb:
> Das ist extrem schlechter Programmierstil.

Das sehe ich anders.

von (prx) A. K. (prx)


Lesenswert?

Frank M. schrieb:
> Franz schrieb:
>> Das ist extrem schlechter Programmierstil.
>
> Das ist Ansichtssache.

Wenn man C auf alles reduziert, was Anfängern zu kompliziert aussieht, 
sind auch die meisten Typdeklarationen draussen.

Das Motiv für den ?: Operator waren Funktionen wie getc, die früher ohne 
Inline-Funktionen auskommen mussten und daher zwecks Performance 
teilweise als Makros implementiert wurden. Und in denen gehts nicht 
anders. Sinngemäss
   (index < limit ? buffer[index++] : the_real_getc(..))

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

(prx) A. K. schrieb:
> (index < limit ? buffer[index++] : the_real_getc(..))

Sehr schön. Im Zusammenhang mit dem berühmten K&R Copy-Programm ...
1
   while ((c = getchar()) != EOF)
2
   {
3
       putchar (c);
4
   }
... unter Berücksichtigung des Macros wirkt das richtig elegant. Mir 
gefällt das einfach: Es sieht einfach aus und verarbeitet einen 
komplizierten Sachverhalt sehr effektiv, nämlich gepufferten I/O.

Glücklicherweise nimmt uns hier der Preprocessor die Arbeit ab, dem 
Compiler das mundgerecht zu servieren.

P.S.

getchar() war/ist natürlich ein auf das getc-Macro basierendes Macro - 
ebenso wie putchar() auch nur ein Macro ist, welches auf das Macro 
putc() zurückgreift. Die simpel aussehende while-Schleife führt daher zu 
einer regelrechten Macro-Orgie ;-)

von Franz (Gast)


Lesenswert?

Mavin schrieb:
>Nein.
>Es ist deutlich lesbarer als deine Spaghettialternative.

Doch.
Weil mit meiner Variante die Fragestellung gar nicht entstanden wäre.

von BesserWisser! (Gast)


Lesenswert?

Frank M. schrieb:
> while ((c = getchar()) != EOF)

besser lesbar wäre
while (c = getchar(), c != EOF)

von (prx) A. K. (prx)


Lesenswert?

BesserWisser! schrieb:
> Frank M. schrieb:
>> while ((c = getchar()) != EOF)
>
> besser lesbar wäre
> while (c = getchar(), c != EOF)

Frevel! Franks Version war ein K&R-Original!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

(prx) A. K. schrieb:
> Frevel! Franks Version war ein K&R-Original!

So ist es. :-)

Obwohl ... dem Komma-Operator wird noch viel weniger Beachtung geschenkt 
als dem ?-Operator. ;-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Franz schrieb:
> Weil mit meiner Variante die Fragestellung gar nicht entstanden wäre.

Das ist keine Begründung. Mit dieser Argumentation kannst Du so ziemlich 
alles kaputtschlagen, was Operatoren in C betrifft. Am Ende bleibt ein 
degeneriertes Etwas, von dem man dann glaubt, jeder Idiot könne es 
beherrschen. Das ist aber ein Trugschluss.

von EAF (Gast)


Lesenswert?

Franz schrieb:
> Doch.
> Weil mit meiner Variante die Fragestellung gar nicht entstanden wäre.

Diese Frage ist nur entstanden, weil hier jemand, sich bisher nicht mal 
die Operatoren Liste seiner Sprache, welche er verwendet, "AUFMERKSAM" 
angesehen hatte.

Merke:
Auch diesmal ist das Sprachmittel, an sich, völlig unschuldig. Auch der 
ursprüngliche Verwender (der kennt die Sprache besser).


Tipp:
Die Lesbarkeit, ist u.A. ein Produkt aus Disziplin und Wissen. Auch 
gerne mal "Können" genannt. Das gilt für den Schreiber, als auch für den 
Leser.

von EAF (Gast)


Lesenswert?

Frank M. schrieb:
> Obwohl ... dem Komma-Operator wird noch viel weniger Beachtung geschenkt
> als dem ?-Operator. ;-)

Ach das ist auch gut so.....

In Schleifenköpfen macht er schon mal Sinn.
Aber sonst...

von (prx) A. K. (prx)


Lesenswert?

EAF schrieb:
> In Schleifenköpfen macht er schon mal Sinn.

Ich habe die Ur-Makros von getc/putc aus dieser Zeit nicht parat, aber 
auch der Komma-Operator kam darin vor.

von Dieter H. (kyblord)


Lesenswert?

Das ist doch sowieso falsch oder?

müsste doch so sein. die klammern verwirren doch nur

variable = adcFrequency > RECORD_EIGHT_BITS ? 20000 : 10000

von (prx) A. K. (prx)


Lesenswert?

Dieter H. schrieb:
> die klammern verwirren doch nur

Manche Klammern sind zwar redundant, verbessern aber die Lesbarkeit. Und 
die hier waren nicht einmal redundant.

von Dieter H. (kyblord)


Lesenswert?

(prx) A. K. schrieb:
> Dieter H. schrieb:
>> die klammern verwirren doch nur
>
> Manche Klammern sind zwar redundant, verbessern aber die Lesbarkeit. Und
> die hier waren nicht einmal redundant.

aber in welche variable wird da überhaupt gespeichert? da fehlt doch die 
zuweisung an eine variable

von (prx) A. K. (prx)


Lesenswert?

Dieter H. schrieb:
> aber in welche variable wird da überhaupt gespeichert? da fehlt doch die
> zuweisung an eine variable

Syntaktisch ist das sogar ein vollständiges aber sinnloses Statement, 
wenn man ein Semikolon dranhängt (was bei dir fehlte ;-). Aber er nannte 
es einen Ausdruck, und das ist korrekt. Nicht jede Diskussion über 
Aspekte einer Programmiersprache müssen als Klorolle daherkommen. Oft 
reicht es, den Kern der Frage zu zeigen. Wie hier.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

(prx) A. K. schrieb:
> Aber er nannte es einen Ausdruck, und das ist korrekt.

Eben, es könnte auch sein, dass der TO den Ausdruck
1
adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000)
tatsächlich aus einem if-Statement rauskopiert hat, nämlich:
1
if (adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000))
2
{
3
}
Und hier sind die Klammern durchaus ernst zu nehmen. Wenn 
RECORD_EIGHT_BITS  ungleich 0 ist, dann reduziert sich das zu:
1
if (adcFrequency > 20000)
2
{
3
}
anderenfalls zu:
1
if (adcFrequency > 10000)
2
{
3
}

Und das ist etwas ganz anderes, als wenn man die Klammern weglässt.

Beispiel:
1
#include <stdio.h>
2
3
#define RECORD_EIGHT_BITS 1
4
5
int main ()
6
{
7
    int adcFrequency = 5000;
8
9
    printf ("%d\n", adcFrequency > RECORD_EIGHT_BITS ? 20000 : 10000);
10
    printf ("%d\n", adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000));
11
}
Ausgabe:
1
20000
2
0

von Egon D. (Gast)


Lesenswert?

Frank M. schrieb:

> Mit dieser Argumentation kannst Du so ziemlich alles
> kaputtschlagen, was Operatoren in C betrifft.

[x] . . . Dafür


> Am Ende bleibt ein degeneriertes Etwas, von dem man dann
> glaubt, jeder Idiot könne es beherrschen. Das ist aber
> ein Trugschluss.

Echt jetzt?! DARÜBER machst Du Dir Sorgen?!

Ganz nebenbei: Was wäre dann anders als heute?

Vom Ohmschen Gesetz glaubt "man" auch, dass jeder Depp
es beherrscht -- so kompliziert ist das ja nicht. Die
langjährige Erfahrung beweist aber genau das Gegenteil...

von DrittesBuch (Gast)


Lesenswert?

adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000)
                        |              |       |
       ----------------              |       \-----\
       |                               |             |
       |                               |             |
(Wenn dieser Ausdruck != 0 ist ? gilt dies : sonst jenes)

Das ist klar leserliche, unverblümte Kernighan-Ritchie C-Sprache.
Reasonable persons love it!!!

von A. S. (Gast)


Lesenswert?

einbaer_klein schrieb:
> adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000)

Franz schrieb:
> Programmtext soll immer einfach und verständlich sein:

Dann noch zwei Beispiele, die auch nicht einfacher sind:
1
adcFrequency > 10000 * (1 + !!RECORD_EIGHT_BITS)
2
3
10000 < adcFrequency || adcFrequency > 20000 && RECORD_EIGHT_BITS

von Rolf M. (rmagnus)


Lesenswert?

EAF schrieb:
> Zugvogel schrieb:
>> Das ist eine andere Schreibweise für die If-Abfrage:
> Das ist falsch!
>
> Die if abfrage ist Kontrollfluss orientiert, und hat darum auch keine
> Probleme mit "Sequence Points".

Welche Probleme soll der ternäre Operator denn damit haben?

> Es sind also gänzlich andere Anwendungsgebiete.

Naja, es gibt gewisse Überlappungen.

Franz schrieb:
> Mavin schrieb:
>>Nein.
>>Es ist deutlich lesbarer als deine Spaghettialternative.
>
> Doch.
> Weil mit meiner Variante die Fragestellung gar nicht entstanden wäre.

Die Fragestellung ist entstanden, weil der TO den ternären Operator noch 
nicht kannte, nicht weil das "extrem schlechter Stil" gewesen wäre.

A. S. schrieb:
> adcFrequency > 10000 * (1 + !!RECORD_EIGHT_BITS)

Das kann man doch viel einfacher schreiben ;-)
1
adcFrequency > 20000 >> !RECORD_EIGHT_BITS)

von Franz (Gast)


Lesenswert?

>von (prx) A. K. (prx)
>12.08.2021 16:53
>Frank M. schrieb:
>> Franz schrieb:
>>> Das ist extrem schlechter Programmierstil.
>>
>> Das ist Ansichtssache.
>Wenn man C auf alles reduziert, was Anfängern zu kompliziert aussieht,
>sind auch die meisten Typdeklarationen draussen.
>Das Motiv für den ?: Operator waren Funktionen wie getc, die früher ohne
>Inline-Funktionen auskommen mussten und daher zwecks Performance
>teilweise als Makros implementiert wurden. Und in denen gehts nicht
>anders. Sinngemäss
>   (index < limit ? buffer[index++] : the_real_getc(..))

Ah, danke. Es ist immer wieder interessant, mehr über die historischen 
Wurzeln zu erfahren.
Mittlerweile legt man bei der Softwareentwicklung mehr Wert auf 
Verständlichkeit als in den 70ger Jahren, wo Kommentare und lange 
Dateinahmen aufgrund von Speichermangel nicht möglich waren.
Nicht umsonst wird im Buch "weniger schlecht programmieren" das Ziel 
propagiert, dass Code wie ein Buch fließend einfach lesbar geschrieben 
sein soll. Den Coding-Style alla BrainFuck, den hier noch einige aus den 
vorigen Jahrzehnten beibehalten haben ist obsolet. Deshalb verbieten 
größere Firmen, die etwas auf sich halten mit ihren "Coding-Rules" die 
Verwendung von ternären Operatoren. Das macht ja offensichtlich Sinn, 
wie dieser Thread hier zeigt.
Sicherlich gibt es die ein- oder andere Bastelbude, die das erlaubt. 
Sinnvoll ist das aber nicht.

von (prx) A. K. (prx)


Lesenswert?

Franz schrieb:
> Das macht ja offensichtlich Sinn, wie dieser Thread hier zeigt.

Ich sehe in Präprozessor-Makros, die wesentlich über die Definition von 
Konstanten hinausgehen, das grössere Risiko, als im ternären Operator. 
Besonders in solchen:
1
# define fread_unlocked(ptr, size, n, stream) \
2
  (__extension__ ((__builtin_constant_p (size) && __builtin_constant_p (n)    \
3
                   && (size_t) (size) * (size_t) (n) <= 8                     \
4
                   && (size_t) (size) != 0)                                   \
5
                  ? ({ char *__ptr = (char *) (ptr);                          \
6
                       FILE *__stream = (stream);                             \
7
                       size_t __cnt;                                          \
8
                       for (__cnt = (size_t) (size) * (size_t) (n);           \
9
                            __cnt > 0; --__cnt)                               \
10
                         {                                                    \
11
                           int __c = _IO_getc_unlocked (__stream);            \
12
                           if (__c == EOF)                                    \
13
                             break;                                           \
14
                           *__ptr++ = __c;                                    \
15
                         }                                                    \
16
                       ((size_t) (size) * (size_t) (n) - __cnt)               \
17
                        / (size_t) (size); })                                 \
18
                  : (((__builtin_constant_p (size) && (size_t) (size) == 0)   \
19
                      || (__builtin_constant_p (n) && (size_t) (n) == 0))     \
20
                        /* Evaluate all parameters once.  */                  \
21
                     ? ((void) (ptr), (void) (stream), (void) (size),         \
22
                        (void) (n), (size_t) 0)                               \
23
                     : fread_unlocked (ptr, size, n, stream))))
(aus /usr/include/bits/stdio.h)

von (prx) A. K. (prx)


Lesenswert?

(prx) A. K. schrieb:
> Das Motiv für den ?: Operator waren Funktionen wie getc, die früher ohne
> Inline-Funktionen auskommen mussten und daher zwecks Performance
> teilweise als Makros implementiert wurden.

In einem schon etwas arg angestaubten Unix-System fand ich es:
1
#define getc(__p)       (((!((__p)->_flag & 0xC000)) && \
2
                        ((__p)->_flag = ((__p)->_flag  & 0x3FFF) | 0x8000)),\
3
                        (--(__p)->_cnt < 0 ? __filbuf(__p) : (int) *(__p)->_ptr++))

von Walter K. (walter_k488)


Lesenswert?

Franz schrieb:
> Ah, danke. Es ist immer wieder interessant, mehr über die historischen
> Wurzeln zu erfahren.
> Mittlerweile legt man bei der Softwareentwicklung mehr Wert auf
> Verständlichkeit als in den 70ger Jahren, wo Kommentare und lange
> Dateinahmen aufgrund von Speichermangel nicht möglich waren.

Vielleicht brauchen auch c-Programmierer keine Prosa?

von (prx) A. K. (prx)


Lesenswert?

Walter K. schrieb:
> Vielleicht brauchen auch c-Programmierer keine Prosa?

Gewohnheit. Wenn man mit sowas anfing, sind C-Makros reine Prosa. ;-)
1
    Z←fft X;N;R;M;L;P;Q;S;T;O
2
3
⍝ Apl Congress 1973, p 267. Robert J. Korsan.
4
5
⍝ Restructure as an array of primitive 2×2 FFT Butterflies
6
X←(2,R←(M←⌊2⍟N←¯1↑⍴X)⍴2)⍴⍉X
7
⍝ Build sin and cosine table :
8
Z←R⍴⍉2 1∘.○○(-(O←?1)-⍳P)÷P←N÷2
9
10
Q←⍳P←M-1+L←0
11
T←M-~O
12
loop:→(M≤L←L+1)⍴done
13
X←(+⌿X),[O+¯0.5+S←M-L](-/Z×-⌿X),[O+P-0.5]+/Z×⌽-⌿X
14
Z←(((-L)⌽Q),T)⍉R⍴((1+P↑(S-1)⍴1),2)↑Z
15
→loop
16
done:Z←⍉(N,2)⍴(+⌿X),[O-0.5]-⌿X

von Carsten (Gast)


Lesenswert?

Extrem schlecht finde ich ihn jetzt nicht, trotzdem geht's auch mit 
ternary lesbarer:
1
uint freqcuencyToCompare;
2
/*
3
 ...
4
 */
5
frequencyToCompare = RECORD_EIGHT_BITS ? 20000 : 10000;
6
/*
7
 ...
8
 */
9
if (adcFrequency > freqcuencyToCompare)
10
{
11
/* ... */
12
}

Der Compiler optimiert das weg, aber beim Debuggen freut man sich.

von Carsten (Gast)


Lesenswert?

Walter K. schrieb:
> Vielleicht brauchen auch c-Programmierer keine Prosa?

So eine Aussage wäre für mich ein Ausschlusskriterium bei der 
Einstellung neuer Mitarbeiter:innen oder bei ner Projektvergabe, weil es 
von mangelnder Teamfähigkeit zeugt.

Man codet schon Jahrzehnte nicht mehr für den Compiler, sondern für die 
Kolleg:innen.

von Johannes S. (Gast)


Lesenswert?

Wenn ein C Programmierer diesen Ausdruck nicht kennt, dann wäre das eher 
ein nicht Einstellungsgrund für mich.

von Rolf M. (rmagnus)


Lesenswert?

Carsten schrieb:
> Walter K. schrieb:
>> Vielleicht brauchen auch c-Programmierer keine Prosa?
>
> So eine Aussage wäre für mich ein Ausschlusskriterium bei der
> Einstellung neuer Mitarbeiter:innen oder bei ner Projektvergabe, weil es
> von mangelnder Teamfähigkeit zeugt.

Länger ist nicht immer besser ;)
Also den Code mit möglichst viel Text zu formulieren, bedeutet nicht 
automatisch, dass er dadurch lesbarer wird. Und Teile der Sprache zu 
meiden, weil ein Anfänger sie ggf. nicht kennen könnte, ist auch nicht 
unbedingt förderlich.

> Man codet schon Jahrzehnte nicht mehr für den Compiler, sondern für die
> Kolleg:innen.

Dabei darf man aber meiner Ansicht nach trotzdem davon ausgehen, dass 
der Leser die Sprache auch einigermaßen versteht.

von Einer (Gast)


Lesenswert?

Franz schrieb:
> Programmtext soll immer einfach und verständlich sein:

Was soll "immer einfach" sein? Verzicht auf Sprachmittel? Welche 
Sprachmittel sind "einfach"? Welche nicht? Wer definiert das? Nach 
welchen Kriterien?

Das Original ist sehr deutlich und sauber formuliert:
1
adcFrequency > (RECORD_EIGHT_BITS ? 20000 : 10000)

Was evtl. zu Diskutieren wäre, ob man den Klammer-Term extrahiert und 
separat benennt. Z.B.: (Name und Datentyp geraten)
1
const int upper_limit = RECORD_EIGHT_BITS ? 20000 : 10000;
2
3
// ...
4
adcFrequency > upper_limit

Mit der Benennung des Teilausdrucks ermöglicht man dem Leser, schnell 
den Code zu erfassen:

  "...ah, obere Grenze berechnen... "
  "... wenn obere grenze verletzt, dann..."

Der Leser kann die zwei Teile direkt abstrahieren. Er muss nicht erst 
analysieren, was in "upper_limit = ..." gemacht wird. Er kann sich 
erstmal auf den Namen verlassen.
Später, wenn er sich für mehr Details interessiert, kann er dann genau 
erfassen, was es denn mit diesem Limit auf sich hat.

Aber der Kontext bzw. das Fachgebiet (Domain) ist wichtig: Was ist es 
für ein Limit? Ist es ein Compile-Time-Limit, dann könnte das sogar auch 
wieder ein Makro sein. Der konkrete Name ergibt sich aus der konkreten 
Bedeutung dieser Grenze.

Programmieren tut man für den Leser des Programmtextes, nicht für den 
Compiler. Oft liest man seinen Mist ein halbes Jahr später selbst und 
wird für jede verwirrungstiftende Formulierung bestraft...

Dein Beispiel ist (übrigens mit Fehler), wie hier zurecht schon mehrfach 
geschrieben, eine deutliche Verschlechterung:
1
  if (RECORD_EIGHT_BITS) result = adcFrequency > 20000;
2
  else result_flag = adcFrequency > 10000;

Es ist nichtmal so sehr die Verwendung von if-then-else und die 
Zuweisung an eine (vorher undefinierten) Variable.

Sondern: Der Blickwinkel/Fokus wird völlig verschoben!

Plötzlich ist es nämlich wichtig, ob RECORD_EIGHT_BITS wahr wird oder 
nicht, und abhängig davon wird irgendwas gemacht.

Vorher wurde aber "adcFrequency" gegen irgendein Limit verglichen.

D.h. Du hast den Sinn der Berechnung völlig verdreht. Und das ist eben 
genau nicht verständlich. Die eigentliche Intention, nämlich die Prüfung 
gegen ein Limit, wird verschleiert.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Franz schrieb:
> Mittlerweile legt man bei der Softwareentwicklung mehr Wert auf
> Verständlichkeit ...
>
> Deshalb verbieten größere Firmen, die etwas auf sich halten mit ihren
> "Coding-Rules" die Verwendung von ternären Operatoren.

Ob der ternäre Operator und andere "spezielle" C-Operatoren lesbarer
sind als ihre Umschreibung mit alternativen Mitteln, hängt stark von
ihrer Anwendung ab und liegt bis zu einem gewissen Grad auch im Auge des
Betrachters.

Ich finde bspw. so etwas gruselig, da hier viermal der gleiche
Teilausdruck vorkommt, dessen Gleichheit ich aber erst einmal mit dem
Auge erfassen muss:
1
if (bedingung)
2
  irgendwas.nochwas[3*index+1] = irgendwas.nochwas[3*index+1] + 1;
3
else
4
  irgendwas.nochwas[3*index+1] = irgendwas.nochwas[3*index+1] + 2;

Mit folgender Schreibweise hingegen sehe ich auf einen Blick, was
abgeht:
1
irgendwas.nochwas[3*index+1] += bedingung ? 1 : 2;

Deswegen finde ich ein Verbot von Sprachelementen (dazu gehören auch
Dinge wie bspw. goto) grundsätzlich falsch. Auf der anderen Seite wäre
es natürlich genauso falsch, jedes if-else-Konstrukt auf Biegen und
Brechen mit dem ternären Operator ausdrücken zu wollen, nur um anderen
zu zeigen, was für ein toller Hecht man ist.

von Rolf M. (rmagnus)


Lesenswert?

Einer schrieb:
> Dein Beispiel ist (übrigens mit Fehler), wie hier zurecht schon mehrfach
> geschrieben, eine deutliche Verschlechterung:

Der Fehler ist ein direktes Ergebnis der Codeduplizierung, die hier 
stattfindet, weil jetzt die Zuweisung zweimal da steht statt nur einmal.

> const int upper_limit = RECORD_EIGHT_BITS ? 20000 : 10000;

Das const hier finde ich sehr gut. Ich nutze const inzwischen auch 
innerhalb von Funktionen für alles, was sich im Laufe der Ausführung 
nicht mehr ändert. Es ist schade, dass in C++ der Default nicht const 
ist, so dass man explizit alles, was nicht const sein soll, markieren 
muss. Mit if müsste man das const allerdings aufgeben.

Yalu X. schrieb:
> Ich finde bspw. so etwas gruselig, da hier viermal der gleiche
> Teilausdruck vorkommt, dessen Gleichheit ich aber erst einmal mit dem
> Auge erfassen muss:
> if (bedingung)
>   irgendwas.nochwas[3*index+1] = irgendwas.nochwas[3*index+1] + 1;
> else
>   irgendwas.nochwas[3*index+1] = irgendwas.nochwas[3*index+1] + 2;

Für alles, was mehrfach vorkommt, erzeuge ich mir einen Pointer (oder in 
C++ ggf. eine Referenz) darauf und benutze den statt so einen Bandwurm 
wie irgendwas.nochwas[3*index+1] mehrfach zu wiederholen. Das macht es 
meistens schon deutlich übersichtlicher.

von (prx) A. K. (prx)


Lesenswert?

Rolf M. schrieb:
> Also den Code mit möglichst viel Text zu formulieren, bedeutet nicht
> automatisch, dass er dadurch lesbarer wird.

Es bedeutet aber, dass die Bildschirme der Entwickler immer grösser 
werden. Man fing mit 1x10" 25x80 an und ist heute bei 2x34" 4K. ;-)

von Einer (Gast)


Lesenswert?

Rolf M. schrieb:
> Der Fehler ist ein direktes Ergebnis der Codeduplizierung, die hier
> stattfindet, weil jetzt die Zuweisung zweimal da steht statt nur einmal.

Exakt. 100% Ack.

Und es sind problemlos Konstellation möglich, wo der Compiler keinen 
Fehler finden kann (beide Variablen existieren, kein const, werden 
mehrfach beschrieben).

Uninitialisierte Variablen und beschreiben mit if-then-else ist ein 
großer Schritt in Richtung Verderben.

von A. S. (Gast)


Lesenswert?

Einer schrieb:
> Was evtl. zu Diskutieren wäre, ob man den Klammer-Term extrahiert und
> separat benennt. Z.B.: (Name und Datentyp geraten)
> const int upper_limit = RECORD_EIGHT_BITS ? 20000 : 10000;
> // ...
> adcFrequency > upper_limit

Und selbst da kann die Lesbarkeit drunter leiden.

Ein (guter) Code wird öfter und von mehr Leuten gelesen als geschrieben. 
Daher hat (subjektive) Lesbarkeit höchste Priorität.

Wenn ein Nachfolger einen Aspekt in 100.000 Zeilen Code untersuchen 
muss, so hängt die Lesbarkeit (=Zeit, in der der Code in diesem 
Teilaspekten erfasst werden kann) neben der Klarheit der Zeilen auch 
davon ab, wie oft er Dinge "nachschlagen" oder "übersetzen" muss. Wenn 
er einen Effekt mit adcFrequency hat und per Suche 20 Treffer dazu hat, 
dann sieht er in der Originalzeile schon im Suchfenster, was da 
passiert, während er bei "Code nach Vorschrift" mehrmals nachschlagen 
muss.
1
#define ADC_FREQUENZ 1000
2
...
3
#define ADC_FREQUENZ_LIMIT (10*ADC_FREQUENZ)
4
#define ADC_FREQUENZ_LIMIT_8 (2*ADC_FREQUENZ_LIMIT) 
5
...
6
const int upper_limit ....
7
...
8
   adcFrequency > upper_limit

Und da ist es müßig zu sagen, dass es "mit der richtigen IDE doch ganz 
schnell geht".

von Andreas (Gast)


Lesenswert?

MaWin schrieb:
> Franz schrieb:
>> Das ist extrem schlechter Programmierstil.
>
> Nein.
> Es ist deutlich lesbarer als deine Spaghettialternative.

Mach es bitte mit deinem eigenen Beispiel besser!

von Franz (Gast)


Lesenswert?

>Mach es bitte mit deinem eigenen Beispiel besser!

Wenn man's schön ausformuliert, sieht man, dass schon das 
Eingangsbeispiel ziemliche Unklarheiten zulässt:
1
#define RECORD_EIGHT_BITS // only 8 bits instead of 10? 
2
..
3
#define ADC_FREQUENZ 1000
4
...
5
#ifdef RECORD_EIGHT_BITS
6
 #define ADC_FREQUENZ_LIMIT (10*ADC_FREQUENZ)
7
#else
8
 #define ADC_FREQUENZ_LIMIT (20*ADC_FREQUENZ) 
9
#endif  
10
11
..
12
if( adcFreqency > ADC_FREQUENZ_LIMIT ) errorHandler("adc limit exceeded");
13
..

von Franz (Gast)


Lesenswert?

oder so:
1
#define RECORD_EIGHT_BITS 
2
..
3
#define ADC_FREQUENCY_16BIT 10000
4
#define ADC_FREQUENCY_8BIT  20000
5
...
6
7
#ifdef RECORD_EIGHT_BITS
8
 #define ADC_FREQUENZ_LIMIT ADC_FREQUENCY_8BIT
9
#else
10
 #define ADC_FREQUENZ_LIMIT ADC_FREQUENCY_16BIT 
11
#endif
12
13
...
14
15
   if(adcFreqency>ADC_FREQUENZ_LIMIT) errorHandler("adc limit exceeded")
16
..

von Franz (Gast)


Lesenswert?

und damit sind vielleicht die letzten Unklarheiten beseitigt:
1
#define RECORD_EIGHT_BITS // disable if you wish 16bit
2
..
3
#define ADC_FREQUENCY_16BIT_HZ 10000
4
#define ADC_FREQUENCY_8BIT_HZ  20000
5
...
6
7
#ifdef RECORD_EIGHT_BITS
8
 #define ADC_FREQUENZ_LIMIT ADC_FREQUENCY_8BIT_HZ
9
#else
10
 #define ADC_FREQUENZ_LIMIT ADC_FREQUENCY_16BIT_HZ 
11
#endif
12
13
...
14
15
if(adcFreqency>ADC_FREQUENZ_LIMIT) errorHandler("adc limit exceeded");
16
..

von Egon D. (Gast)


Lesenswert?

Yalu X. schrieb:

> Ich finde bspw. so etwas gruselig, da hier viermal der
> gleiche Teilausdruck vorkommt, dessen Gleichheit ich
> aber erst einmal mit dem Auge erfassen muss:
>
>
1
> if (bedingung)
2
>   irgendwas.nochwas[3*index+1] = irgendwas.nochwas[3*index+1] + 1;
3
> else
4
>   irgendwas.nochwas[3*index+1] = irgendwas.nochwas[3*index+1] + 2;
5
>
>
> Mit folgender Schreibweise hingegen sehe ich auf einen Blick,
> was abgeht:
>
>
1
> irgendwas.nochwas[3*index+1] += bedingung ? 1 : 2;
2
>

In der Praxis würde ich
1
curindex = 3*index+1; 
2
if (bedingung) { 
3
  incr(irgendwas.nochwas[curindex],1) 
4
} else { 
5
  incr(irgendwas.nochwas[curindex],2) 
6
}
bevorzugen.

Alternativ ginge auch
1
if (bedingung) { 
2
  incval=1 
3
} else { 
4
  incval=2 
5
} 
6
incr(irgendwas.nochwas[3*index+1],incval);

Hmm. Eigentlich finde ich die zweite Variante noch besser
als die erste.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Egon D. schrieb:
> incr(irgendwas.nochwas[3*index+1],incval);

Du solltest nur noch in einem Kommentar dazuschreiben, was incr tut.

Denn jeder langjährige C-Programmierer, der das liest, denkt:

"Dem Namen nach wird hier wohl das zweite Argument zum ersten addiert.

Aber halt, das erste Argument wird ja als Wert übergeben und kann
deswegen in der Funktion gar nicht verändert werden.

Hmm, oder ist incr vielleicht ein Makro? Dann wäre die Veränderung des
ersten Arguments möglich. Aber Makros schreibt man doch üblicherweise in
Großbuchstaben?

Und warum nimmt der Programmierer statt incr nicht einfach +=, das
wäre doch viel einfacher zu schreiben, man müsste keine Funktion bzw.
kein Makro dafür definieren, und jeder wüsste sofort, was hier
geschieht.

Nein, dieses incr muss etwas ganz Besonderes sein. Da muss ich erst
einmal nachschauen, wie das implementiert ist ..."

...

Fünf Minuten später hört man einen dumpfen Knall, der sich anhört wie
der Aufschlag eines Schädels auf die hölzerne Tischplatte :)

von Franz (Gast)


Lesenswert?

1
idx = 3*index+1; 
2
3
if (bedingung) irgendwas.nochwas[idx]+=1;
4
else           irgendwas.nochwas[idx]+=2;

von Carsten (Gast)


Lesenswert?

Rolf M. schrieb:
> Dabei darf man aber meiner Ansicht nach trotzdem davon ausgehen, dass
> der Leser die Sprache auch einigermaßen versteht.

Hallo Rolf,

ja natürlich. Und klar sollte jemand, der in der Vita "Große Erfahrung 
in C" stehen hat, den Term vom OP verstehen und damit keine Probleme 
haben.

Andererseits habe ich auch selbst in C#-basierten Projekten erlebt, dass 
angeblich in C erfahrene Entwickler an einem einfachen Konzept wie... na 
ja, sie haben zig Namen: Funktionszeiger, anonyme Funktionen, Delegaten, 
Funktoren, Action<T>, Tralala... scheitern. Dann kommt der Kunde und 
hätte auf seinem ESP32 bitte FreeRTOS.

Dieses ganze Old-School Getue, wer das sinnloseste typedef schreibt, hat 
für mich was von "Keine Ahnung, was ein Buch ist, aber meine "A"s haben 
mehr Schnörkel als deine!" Vorteil von C# übrigens, keine typedefs mehr, 
#defines bis auf ein paar wenige Ausnahmen gelten als pfui, no more 
#include. Allein dafür gehört C# schon gefeiert.

Programmieren ist das eine, wirklich Software entwickeln ist das andere. 
Das hat dann nämlich nicht mehr sehr viel mit ner Programmiersprache zu 
tun, sondern mit Konzepten, Struktur, all dem eben, was man aus der 
Abteilung "Clean Coding" kennt, und für mich jedenfalls ist der 
allerwichtigste Kern dieser ganzen Veranstaltungen schlicht: 
Selbstdisziplin. Der heutige Wow-Effekt beim Lesen von Code sollte 
nämlich der "wow, ich verstehe es direkt!" sein.

Aber die mit dem Dicksten sterben halt nicht aus.

von Carsten (Gast)


Lesenswert?

Nachtrag...

Wie lernen "Leute heute" (ja, man könnte meinen, die Zuschauer:innen 
dieser sinnfreien Sendung) C? Auf dem Arduino, und die würden jetzt 
Stein und Bein schwören, dass ein C-Programm aus setup() und loop() 
besteht, sogar wenn sie schon erfolgreich was mit bit-banging, dem 
ternary und dem comma hin gezaubert haben.

Deswegen können sie weder C noch programmieren noch Software entwickeln.

"Bohrt ein Software-Entwickler ein Loch in die Wand und fällt tot um..." 
;)

von Carsten (Gast)


Lesenswert?

Franz schrieb:
1
> #define RECORD_EIGHT_BITS // disable if you wish 16bit
2
> ..
3
> #define ADC_FREQUENCY_16BIT_HZ 10000
4
> #define ADC_FREQUENCY_8BIT_HZ  20000
5
> ...
6
> #ifdef RECORD_EIGHT_BITS
7
>  #define ADC_FREQUENZ_LIMIT ADC_FREQUENCY_8BIT_HZ
8
> #else
9
>  #define ADC_FREQUENZ_LIMIT ADC_FREQUENCY_16BIT_HZ
10
> #endif
11
> ...
12
> if(adcFreqency>ADC_FREQUENZ_LIMIT) errorHandler("adc limit exceeded");

Welche oberste Instanz von Unfähigkeit hat bitte diesen Mist 
geschrieben?

Ich liste mal nur die Fehler in Sachen Konsistenz und Lesbarkeit auf...
- Wenn ADC_FREQUENCY_8BIT_HZ, dann auch RECORD_8BIT (und ja, in solchen 
Fällen immer Ziffer vor Wort, also nicht EIGHT)
- Wenn ADC_FREQUENCY_8BIT_HZ (richtig, Einheit mit angeben), dann auch 
ADC_FREQUENCY_LIMIT_HZ (Sprache beibehalten, Einheiten beibehalten)

Das war Syntax. Auf zur Semantik:

(Was ADC bedeutet, nehme ich mal als domain-spezifisch hin und nicke es 
ab.)

- Was heißt ADC_FREQUENCY_8BIT_HZ? Sowas wie 
ADC_FREQUENCY_IN_HZ_IF_SELECTED_DATA_WIDTH_IS_8BIT?

Das ganze Getue um "Code wird immer länger" ist falsch. Wenn 
AAAAAAAAAAAAAAAAA präziser im Code ist als A, dann schreib 
AAAAAAAAAAAAAAAAA! Ich hab das auch lernen müssen, für mich war
1
for (var i = 0; i < A.Length; i++)
2
for (var j = 0; j < A[i].Length; j++)

total offensichtlich, weil es um eine Matrix Aij ging. Für wen mit 
mathematischer Denke halt offensichtlich. Da es aber eigentlich um eine 
Abbildung auf 2D ging, kam prompt die Frage, wo denn x und y hin sind...

von A. S. (Gast)


Lesenswert?

Egon D. schrieb:
> Eigentlich finde ich die zweite Variante noch besser
> als die erste.

Aber nur, wenn Du dieses Stück Code auf dem Bildschirm vor Dir hast und 
es erforschen willst. Das ist der usecase für eigene Programme, kleine 
Projekte oder defizile Programmteile.

Mit der Erfahrung wächst aber auch das Vermögen, die originale Zeile 
schnell zu erfassen. Das ist wie in der deutschen Sprache, die auch 
prägnantere kurze Sätze ermöglicht, wenn der Leser alle 4 Fälle kennt. 
Die Formulierung in leicht verständlicher Sprache lässt dann manche 
Nuancen weg oder wird länger und nur scheinbar einfacher.

von Franz (Gast)


Lesenswert?

Carsten (Gast)
13.08.2021 21:33

>Welche oberste Instanz von Unfähigkeit hat bitte diesen Mist
>geschrieben?

Bevor du weiter blubberst: Zeig mal deine Lösung.

von Egon D. (Gast)


Lesenswert?

Yalu X. schrieb:

> Egon D. schrieb:
>> incr(irgendwas.nochwas[3*index+1],incval);
>
> Du solltest nur noch in einem Kommentar dazuschreiben,
> was incr tut.

Ach, das wäre doch unsportlich :)

Ich dachte mir so: Wenn C-Programmierer dauernd Dinge
schreiben, die nur vage Ähnlichkeit mit booleschen
Ausdrücken haben, und das mit kühner Stirne, stolzer
Brust als boolesche Ausdrücke verkaufen, dann kann ich
auch ein Tcl-Kommando hernehmen und das als C-Code
verkaufen... :)


Es ging mir eigentlich um einen anderen Aspekt: Man
kann Dein Beispiel inhaltlich auffassen als: "Abhängig
von einer Bedingung sind zwei verschiedene Berechnungen
auszuführen." Das ist m.E. die umständlichere Sichtweise.

Man kann aber auch sagen: "Es ist eine Berechnung durch-
zuführen; zuvor ist aber ein Parameter für diese Rechnung
abhängig von einer Bedingung zu wählen." Hier ist das,
was kompliziert werden kann -- die Berechnung -- von
vornherein nur einmal aufzuschreiben, und nur das, was
einfach ist -- die Auswahl des Incrementes -- kommt in
die Fallunterscheidung.

Nach meinem Eindruck wird zu oft darüber diskutiert,
einen komplizierten Ablauf mit möglichst wenig Zeichen
aufschreiben zu können, statt einen einfacheren Ablauf
mit demselben Ergebnis zu finden.

von Egon D. (Gast)


Lesenswert?

A. S. schrieb:

> Egon D. schrieb:
>> Eigentlich finde ich die zweite Variante noch besser
>> als die erste.
>
> Aber nur, wenn Du dieses Stück Code auf dem Bildschirm
> vor Dir hast und es erforschen willst. Das ist der
> usecase für eigene Programme, kleine Projekte oder
> defizile Programmteile.

???

Ich verstehe den Zielpunkt der Aussage nicht. Das ist doch
der Normalfall, dass ich Quelltext deshalb lese, um zu
verstehen, was er macht -- nicht auf dem Niveau "Ahh...
i wird um eins erhöht", sondern um zu verstehen, was dieser
Teil des Programms zum Gesamtproblem beiträgt.


> Mit der Erfahrung wächst aber auch das Vermögen, die
> originale Zeile schnell zu erfassen.

Ja, zweifellos.

Du lässt aber m.E. außer Acht, dass manche Leute prinzipiell
nicht so viel Erfahrung erwerben können wie andere -- z.B.
weil sie keine hauptberuflichen Programmierer sind, sondern
Gelegenheitsprogrammierer.

Das ist in der Mathematik nicht anders: Es gibt viele
Nichtmathematiker, die ab und zu mal eine Formel herleiten,
ein Integral bestimmen oder eine Ableitung berechnen müssen.
Deren Herleitung ist vielleicht länger und sieht unbeholfener
aus als die eines Mathematikers, der das jedes Semester in
der Vorlesung vorführen muss -- aber ist das ein Grund?


> Das ist wie in der deutschen Sprache, die auch prägnantere
> kurze Sätze ermöglicht, wenn der Leser alle 4 Fälle kennt.
> Die Formulierung in leicht verständlicher Sprache lässt
> dann manche Nuancen weg oder wird länger und nur scheinbar
> einfacher.

Hmm. Naja. Letztlich streiten wir um Nuancen.

Der "?"-Operator ermöglicht ja keine prinzipiell neuartigen
Konstrukte, sondern nur eine verkürzte Schreibweise, insofern
finde ich den Vergleich mit den vier Fällen nicht gerecht-
fertigt.

Andererseits habe ich, wenn ich Fachtexte verfassen, eine
fatale Neigung zu komplizierten Satzkonstruktionen. Meine
Erfahrung aus 30 Jahren Tipperei: "Wenn es mit einem lange
Satz nicht geht -- nimm mehrere kurze." Zu lange zu
komplizierte Sätze sind meiner Erfahrung nach ein Anzeichen
dafür, dass das Bild im Kopf noch nicht stimmt und man mit
dem Erklären des Sachverhaltes in der falschen Ecke beginnt.

Ich glaube, dass es beim Programmieren ähnlich ist :)

von Franz (Gast)


Lesenswert?

1
  
2
bool natuerliche_Sprache = true;

Ziemlich eindeutig dürfte folgend Formulierung sein:
1
  if (natuerliche_Sprache) schreibe("ist gut lesbar");
2
  else                     schreibe("kaum zu verstehen");

hieroglyphische Form, zu viel Interpretation notwendig:
1
  schreibe(natuerliche_Sprache ? "ist gut lesbar" : "kaum zu verstehen");

von Carl D. (jcw2)


Lesenswert?

Für die des Lesens mächtigen alten Ägypter waren Hieroglyphen einfach 
nur Text.

Ich empfehle COBOL. Da läst sich Code und Kommentar kaum unterscheiden.

von (prx) A. K. (prx)


Lesenswert?

Franz schrieb:
> zu viel Interpretation notwendig

Um genau diese Aussage geht es: Es ist dann "zu viel Interpretation", 
wenn man in der visuellen Erfassung von Programmen in dieser Sprache 
nicht flüssig ist. Das kann auf Mangel an Erfahrung basieren.

Nun sind die Menschen freilich etwas verschieden gewickelt. Die 
Effektivität solcher visuellen Erfassung fällt ebenso darunter, 
kindliche und später nicht mehr wiederholbare Lernprozesse 
eingeschlossen. Manche erkennen die gleiche Art mehr oder weniger 
abstrakter Muster leichter als andere.

Wenn man dies nicht beachtet, und seinen eigenen Massstab unreflektiert 
anlegt, kann eine Diskussion wie hier rauskommen. In beiden Richtungen, 
von "kaum lesbar" bis "sieht doch ein Blinder mit dem Krückstock".

Man kann (und sollte) diese Betrachtung individueller Unterschiede 
natürlich auch auf andere Aspekte von Programmierung ausdehnen. Es gibt 
nicht nur visuelle Muster. Ebenso beispielsweise, wie sehr und wie 
abstrakt die Strukturen von Programm und Daten im Kopf vorher abgebildet 
werden. In APL Programmen (s.o.) gehts nicht ohne mehrdimensionale 
Datenmodellierung im Kopf ab - wer damit Probleme hat, hat keine Chance.

von Norbert (Gast)


Lesenswert?

Franz schrieb:
> bool natuerliche_Sprache = true;
>
> Ziemlich eindeutig dürfte folgend Formulierung sein:
>   if (natuerliche_Sprache) schreibe("ist gut lesbar");
>   else                     schreibe("kaum zu verstehen");
>
> hieroglyphische Form, zu viel Interpretation notwendig:
>   schreibe(natuerliche_Sprache ? "ist gut lesbar" : "kaum zu
> verstehen");

Kryptisch:
A = B + C

Natürlich:
Nimm den Inhalt von B und addiere den Inhalt von C. Speichere das 
Ergebnis in A

Natürlich & Höflich:^H^H^H^H^H^H
Natürlich und Höflich:
Bitte sei doch so freundlich und nimm den Inhalt von B.
Dann, nur wenn es deine Zeit erlaubt, addiere netterweise den Inhalt von 
C.
Sollte es sich einrichten lassen und dir nicht all zu viel Arbeit 
machen, so speichere doch bitte das Ergebnis in A.

Natürlich und Höflich und korrekt geschlechtert:
…

von Einer (Gast)


Lesenswert?

Franz schrieb:
> Ziemlich eindeutig dürfte folgend Formulierung sein:

Durch ständiges wiederholen wird's auch nicht besser:
1
   if (natuerliche_Sprache) schreibe("ist gut lesbar");
2
   else                     schreibe("kaum zu verstehen");

...Argumente dagegen kannst Du alle oben nachlesen. Hier kommt noch 
malen mit Leerzeichen dazu.

Nochmals in Kurzform:
1
  if (p) f(); else g();

...sinnvoll, da unterschiedliche Code-Pfade.

Dagegen:
1
  if (p) f(a); else f(b);

...nicht sinnvoll, da keine unterschiedlichen Code-Pfade, sondern nur 
unterschiedlicher Parameter. Intention wird verschleiert.

Daher:
1
  f(p ? a : b);

...besser, da Kodierung der Information: Das Argument von f() ist 
abhängig von "p".

Oder:
1
  x = p ? a : b;
2
  f(x);

...anderer Fokus: f() wird mit x aufgerufen. x ist abhängig von p.

von (prx) A. K. (prx)


Lesenswert?

Einer schrieb:
> ...besser, da Kodierung der Information: Das Argument von f() ist
> abhängig von "p".

Wobei es Programmiersprachen gibt, die dafür die gleiche Syntax 
verwenden. Sinngemäss wäre das beispielsweise so denkbar:
   f( if(p) a else b )

GCC und evtl auch LLVM/clang dehnen dieses Prinzip noch weiter aus, 
indem {} Statements generell in Ausdrücken verwendet werden können. 
Gefällt sicher nicht jedem.
https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs

von (prx) A. K. (prx)


Lesenswert?

Einer schrieb:
> ...nicht sinnvoll, da keine unterschiedlichen Code-Pfade, sondern nur
> unterschiedlicher Parameter.

Codepfad vs Datenpfad.

von (prx) A. K. (prx)


Lesenswert?

(prx) A. K. schrieb:
> Sinngemäss wäre das beispielsweise so denkbar:
>    f( if(p) a else b )

#define IF(c) (c)?
#define ELSE  :
  =>
f( IF(p) a ELSE b )

von W.S. (Gast)


Lesenswert?

Yalu X. schrieb:
> Deswegen finde ich ein Verbot von Sprachelementen (dazu gehören auch
> Dinge wie bspw. goto) grundsätzlich falsch. Auf der anderen Seite wäre
> es natürlich genauso falsch, jedes if-else-Konstrukt auf Biegen und
> Brechen mit dem ternären Operator ausdrücken zu wollen, nur um anderen
> zu zeigen, was für ein toller Hecht man ist.

Im Grunde stimme ich dir zu. Aber mMn ist es genau so schädlich für die 
Lesbarkeit, wenn es für Sprachelemente mehrere zu merkende 
Ausdrucksweisen gibt. "if cond then anweisung" noch um eine zweite 
Variante mit ? und : zu ergänzen verkompliziert das Ganze nur unnötig. 
Dort auf "gründliches Lesen des Manuals" hinzuweisen (wie Frank es getan 
hat), heißt im Klartext Obfuscation zu rechtfertigen.

Meine Variante deines Beispiels wäre:
1
 meineVariable:= MeinKomplizierterAusdruck;
2
 if cond then inc(meineVariable);

Ansonsten sehe ich für Diskussionen um Unterschiede zwischen 
"datenflußorientiert" und "kontrollflußorientiert" als reine 
Scharlatanerie. Da wollen sich Leute wichtig machen, indem sie 
kompliziert klingende Begriffe einstreuen.

Und was schlechten Programmierstil betrifft: da sehe ich es als schlecht 
an, wenn im Programm einerseits symbolische Flags wie 
"RECORD_EIGHT_BITS" definiert werden und andererseits davon abhängige 
Limits wie "10000" nicht ebenfalls per #define festgelegt werden. Ist 
was anderes als Bitnamen, weil es in C das Bit als eigenständigen 
Datentyp nicht gibt.

W.S.

von A. S. (Gast)


Lesenswert?

Egon D. schrieb:
> Das ist doch
> der Normalfall, dass ich Quelltext deshalb lese, [...]
> um zu verstehen, was dieser
> Teil des Programms zum Gesamtproblem beiträgt.

Teilweise. Das gilt sicher für abgeschlossene Funktionen wie sin() oder 
draw_circle(), die wenige  Parameter bekommen und einen definierten 
Output liefern. Für diese ist es einfach (und geboten) Unit-Tests zu 
schreiben, sie haben keine Seiteneffekte und ändern nichts am Kontext.

In der Regel sind diese Funktionen gut Dokumentierbar und ich muss nur 
zur Fehlersuche oder aus Interesse in ihnen herumwühlen.

Weit häufiger und intensiver (bei Embedded und dort, wo C noch üblich 
ist) sind Bereiche, wo ich etwas mit dem Systemkontext mache. Etwas 
schalte, Daten hinzufüge, einen Zustand verändere. Hier ist meist die 
größere Herausforderung, die richtige Stelle zu finden. Und das geht 
umso einfacher, je schneller ich erfassen kann, was an den vielen 
Stellen passiert (und nein, die Paradigmen der Uni-Vorlesung 1.Semester 
Programmieren helfen da nur bedingt, wie man in anderen Diskussionen 
hier ja immer wieder feststellt)

Egon D. schrieb:
> Deren Herleitung ist vielleicht länger und sieht unbeholfener
> aus als die eines Mathematikers, der das jedes Semester in
> der Vorlesung vorführen muss -- aber ist das ein Grund?

Das ist ein gutes Beispiel: Jeder erste Code ist "unbeholfen", auch von 
Super-Experten. Aber wenn der Code bleibt, wenn die Herleitung in eine 
Fachzeitschrift soll, um von 100 anderen gelesen zu werden, dann ist die 
Frage nach der Best-Practice zur Refakturierung. Und da ist prägnante, 
kurze, wenig Redundante Schreibweise in der Mathematik Konsens. Das soll 
nicht heißen kryptisch. Aber z.B. übertragen: Laufvariablen "i" und 
nicht "Laufvariable".
"*d++=*s++" und nicht "*Destination_Ptr=Source...."

Egon D. schrieb:
> Der "?"-Operator ermöglicht ja keine prinzipiell neuartigen
> Konstrukte, sondern nur eine verkürzte Schreibweise
Hier wurde bereits ein perfektes Beispiel gebracht von
Einer schrieb:
> Daher:
>   f(p ? a : b);
>
> ...besser [...]: Das Argument von f() ist abhängig von "p".

> Zu lange zu komplizierte Sätze sind meiner Erfahrung nach ein Anzeichen
> dafür, dass das Bild im Kopf noch nicht stimmt und man mit
> dem Erklären des Sachverhaltes in der falschen Ecke beginnt.
Das ist auch beim Programmieren so. Schachtelsätze sind selten sinnvoll.

von EAF (Gast)


Lesenswert?

W.S. schrieb:
> Ansonsten sehe ich für Diskussionen um Unterschiede zwischen
> "datenflußorientiert" und "kontrollflußorientiert" als reine
> Scharlatanerie.

Alles klar...
Keine Fragen mehr....

Aber typisch die Ansage:
Wenn man eine Abstraktion nicht kapiert, weil man es nicht geübt ist in 
solchen Abstraktionen zu denken, oder gar zu *** dafür ist, dann wird 
der Bote mit Häme überschüttet.

Alles klar...
Keine Fragen mehr....

https://www.youtube.com/watch?v=DrG2c0_EyDE

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.