Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Schleifen und Kommata

1 view
Skip to first unread message

Rainer Weikusat

unread,
Nov 4, 2022, 4:36:29 PM11/4/22
to
bl = first_block();
while (bl && (now = time(NULL), next = bl->created + tmout, next <= now))
do {
/* do something which takes time */
} while (bl = first_block(), bl && bl->created + tmout <= now);

Sowohl bl als auch now und next werden nach der Doppelschleife noch
benötig. Ursprünglich hatte ich da ein goto drin, was mir aber gar nicht
gefiel und wie oa ersetzt werden konnte.

Bonita Montero

unread,
Nov 5, 2022, 1:42:47 AM11/5/22
to
Du hasn Knall.
Ich schreibe ja auch gern kompakt, aber das ist total nerdig.

Thomas Koenig

unread,
Nov 5, 2022, 5:42:13 AM11/5/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
Hm, das zweite while hätte man auch mit

while ((bl = first_block()) && bl->created + timeout <= now

ohne Komma schreiben können, oder das bl in die Schleife reinziehen,
aber das ist eine Frage des Stils.

Aber das mit dem goto aus der äußeren Schleife stimmt natürlich.
C hat keinen eleganteren Weg. Andere Sprachen haben da von C
gelernt; Perl z.B. hat

LINE: while(<>) {
(irgendwo tief unten)
last LINE if ...

und Fortran

outer: DO
! wieder ganz tief unten
if (...) exit outer

Bonita Montero

unread,
Nov 5, 2022, 6:01:42 AM11/5/22
to
Am 05.11.2022 um 10:42 schrieb Thomas Koenig:

> LINE: while(<>) {
> (irgendwo tief unten)
> last LINE if ...
>
> und Fortran
>
> outer: DO
> ! wieder ganz tief unten
> if (...) exit outer

Labelled break wie in Java wäre nett.
Ich hab aber auch an der Stelle keine Probleme mit einem goto.

Helmut Schellong

unread,
Nov 5, 2022, 7:31:21 AM11/5/22
to

Bonita Montero

unread,
Nov 5, 2022, 11:29:34 AM11/5/22
to
Am 05.11.2022 um 12:31 schrieb Helmut Schellong:

> Ich programmiere so (mit Kommalisten) seit etwa 1990.
> Oft können so Instruktionen eingespart werden.

Äh, was ? Welches Komma-Konstrukt macht bitte den Code effizienter
als man das anders erreichen könnte ?

Rainer Weikusat

unread,
Nov 6, 2022, 5:17:08 AM11/6/22
to
Thomas Koenig <tko...@netcologne.de> writes:
> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>> bl = first_block();
>> while (bl && (now = time(NULL), next = bl->created + tmout, next <= now))
>> do {
>> /* do something which takes time */
>> } while (bl = first_block(), bl && bl->created + tmout <= now);
>>
>> Sowohl bl als auch now und next werden nach der Doppelschleife noch
>> benötig. Ursprünglich hatte ich da ein goto drin, was mir aber gar nicht
>> gefiel und wie oa ersetzt werden konnte.
>
> Hm, das zweite while hätte man auch mit
>
> while ((bl = first_block()) && bl->created + timeout <= now
>
> ohne Komma schreiben können, oder das bl in die Schleife reinziehen,
> aber das ist eine Frage des Stils.

Das würde ich jetzt in Perl machen, aber nicht in C, weil ich diese
redundante verklammerung, die jemand sich als inoffizielle
Nikolaus-Wirth-Gedächtnis-Syntax ausgedacht hat, nicht mag. Die Idee,
daß eine Schleifenbedingung aus n durch Kommata getrennten Ausdrücken,
die etwas berechnen, sowie der eigentlichen Bedingung, die die
berechneten Werte benutzt, gefällt mir auch einfach. Das drückt genau
das aus, was ich an dieser Stelle tun will.

> Aber das mit dem goto aus der äußeren Schleife stimmt natürlich.
> C hat keinen eleganteren Weg. Andere Sprachen haben da von C
> gelernt; Perl z.B. hat
>
> LINE: while(<>) {
> (irgendwo tief unten)
> last LINE if ...
>
> und Fortran
>
> outer: DO
> ! wieder ganz tief unten
> if (...) exit outer

In PL/Pgsql gibt es ein Schleifenkonstrukt

loop
.
.
.
end loop

ohne jegliche Bedingungskonstruktion. Geht in Perl auch, aber dafür muß
man einen Block haben, den man mit redo beendet. Wenn man eine Schleife
hat, die sich absolut gar nicht in eine klare Bedingungsform bringen
läßt, finde ich sowas sinnvoller, als

while (1) {
}

oder

for (;;;) {
}

zu benutzen.

Rainer Weikusat

unread,
Nov 6, 2022, 5:19:21 AM11/6/22
to
Helmut Schellong <r...@schellong.biz> writes:
> On 11/04/2022 21:36, Rainer Weikusat wrote:
>> bl = first_block();
>> while (bl && (now = time(NULL), next = bl->created + tmout, next <= now))
>> do {
>> /* do something which takes time */
>> } while (bl = first_block(), bl && bl->created + tmout <= now);
>>
>> Sowohl bl als auch now und next werden nach der Doppelschleife noch
>> benötig. Ursprünglich hatte ich da ein goto drin, was mir aber gar nicht
>> gefiel und wie oa ersetzt werden konnte.
>>
>
> Ich programmiere so (mit Kommalisten) seit etwa 1990.
> Oft können so Instruktionen eingespart werden.

Ob das Instruktionen spart (bei zeitgenössischen Compilern keinesfalls
sicher) ist eigentlich eher egal. Darauf kommt es heutzutage nicht mehr
an bzw wenn es tatsächlich darauf ankommt, muß man in Maschinensprache
programmieren.

Thomas Koenig

unread,
Nov 6, 2022, 6:03:47 AM11/6/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
> Helmut Schellong <r...@schellong.biz> writes:
>> On 11/04/2022 21:36, Rainer Weikusat wrote:
>>> bl = first_block();
>>> while (bl && (now = time(NULL), next = bl->created + tmout, next <= now))
>>> do {
>>> /* do something which takes time */
>>> } while (bl = first_block(), bl && bl->created + tmout <= now);
>>>
>>> Sowohl bl als auch now und next werden nach der Doppelschleife noch
>>> benötig. Ursprünglich hatte ich da ein goto drin, was mir aber gar nicht
>>> gefiel und wie oa ersetzt werden konnte.
>>>
>>
>> Ich programmiere so (mit Kommalisten) seit etwa 1990.
>> Oft können so Instruktionen eingespart werden.
>
> Ob das Instruktionen spart (bei zeitgenössischen Compilern keinesfalls
> sicher)

Bei gegenwärtigen Compilern, wenn man irgendwelche Optimierungen
angeschaltet hat, eher ausgeschlossen.

So ziemlich das erste, was ein moderner Compiler tut, ist eine
Transformation in SSA (single static assignment)-Form, und da gibt
es keinen Unterschied mehr, welche der verschiedenen Alternativen
aus der C-Syntax man sich da rausgepickt hat.

Nur mal ein Beispiel, hier mal mit dem ++-Operator, der vor 30
Jahren vielleicht Unterschiede zu der alternativen Schreibeweise
var = var + 1 gehabt haben mag:

$ cat inc.c
unsigned long glob;

void inc_1()
{
glob ++;
}

void inc_2()
{
glob = glob + 1;
}
$ gcc -S -fdump-tree-gimple inc.c
$ cat inc.c.005t.gimple
inc_1 ()
{
glob.0_1 = glob;
_2 = glob.0_1 + 1;
glob = _2;
}


inc_2 ()
{
glob.1_1 = glob;
_2 = glob.1_1 + 1;
glob = _2;
}

>ist eigentlich eher egal. Darauf kommt es heutzutage nicht mehr
> an bzw wenn es tatsächlich darauf ankommt, muß man in Maschinensprache
> programmieren.

Es kann sich durchaus lohnen, den Assembler, der vom Compiler
generiert wird, mal zu lesen und in kritischen Fällen zu schauen,
ob der noch verbessert werden kann, z.B. mit anderen Optionen.
Und sei es nur, um einen Bug Report an den Compiler zu schicken.

Aber Vorsicht: Das einfache Modell eines Prozessors, der sequentiell
die Instruktionen abarbeitet, stimmt heute typischerweie nicht mehr.
Man irrt sich schnell in der Beurteilung, was schnell ist und was
nicht. Prozessoren arbeiten heute viele Befehle parallel ab und
ordnen sie auch gerne um, wenn es geht (out of order execution).
Und die Sprungvorhersage ist heutzutage richtig gut, was auch
nötig ist, weil die Pipelines ziemlich tief und eine falsche
Sprungvorhersage eine ganze Menge Arbeit zunicht macht (die
Pipelines sind mittlerweile recht tief geworden).

In Spezialfällen (SIMD-Register, bignum-Arithmetik) kann man mit
Assembler allerdings durchaus noch Faktoren von 2 rausholen, deshalb
ist z.B. der Kern von GMP tatsächlich in Assembler geschrieben.

Claus Reibenstein

unread,
Nov 6, 2022, 8:07:56 AM11/6/22
to
Rainer Weikusat schrieb am 06.11.2022 um 11:17:

> In PL/Pgsql gibt es ein Schleifenkonstrukt
>
> loop
> .
> .
> .
> end loop
>
> ohne jegliche Bedingungskonstruktion.

Gibt's in C auch. Hast Du auch genannt:

> while (1) {
> }
>
> oder
>
> for (;;;) {
> }

Wobei Letzteres einen Syntaxfehler enthält ;-)

Wie wäre es damit:

#define forever for(;;)

Gruß
Claus

Thomas Koenig

unread,
Nov 6, 2022, 10:40:50 AM11/6/22
to
Claus Reibenstein <crei...@gmail.com> schrieb:
Wenn schon, denn schon:

#define DIAMONDS for(;;)

Rainer Weikusat

unread,
Nov 6, 2022, 2:23:20 PM11/6/22
to
Claus Reibenstein <crei...@gmail.com> writes:
> Rainer Weikusat schrieb am 06.11.2022 um 11:17:
>
>> In PL/Pgsql gibt es ein Schleifenkonstrukt
>>
>> loop
>> .
>> .
>> .
>> end loop
>>
>> ohne jegliche Bedingungskonstruktion.
>
> Gibt's in C auch. Hast Du auch genannt:
>
>> while (1) {
>> }
>>
>> oder
>>
>> for (;;;) {
>> }
>
> Wobei Letzteres einen Syntaxfehler enthält ;-)

Ja. Aber ich habe noch nie in meinem Leben in C eine for-Schleife
benutzt :-). Es ist auch nicht ganz dasselbe: Beide C-Konstrukte sind
Schleifen mit einer degenerierten Abbruchbedingung, nämlich einer, die
nie einen Abbruch verursacht. Das PL/Pgsql-Konstrukt hat gar keine. Es
definiert nur einen Block, dessen Ausführung solange wiederholt wird,
bis er durch eine exit-Anweisung im Block ausdrücklich verlassen wird
(falls eine solche jemals ausgeführt wird).

Thomas Koenig

unread,
Nov 6, 2022, 5:01:36 PM11/6/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
Ist in Fortran das gleiche.

myloop: do
...
end do

definiert eine Endlosschleife, die nur durch exit (endweder "exit"
ohne Angabe des Labels aus der äußersten Ebene oder "exit myloop"
irgendwo aus der Schleife) oder durch Programmende verlassen wird.

Man kann auch

do i=1,n
...
end do

schreiben, dann hat man als zusätzliche Abbruchbeingung noch die
Iteration der Schleife.

Es gibt allerdings einen wichtigen Unterschied zu C. Dort kann
man ja problemlos sowas wie

for (int i=0; i<n; i++) {
...
i++;
n--;
}

schreiben, die Bedingung wird jedesmal neu ausgewertet; eigentlich
ist die for-Schleife nur syntaktischer Zucker für while.

Bei Fortran wird die Anzahl der Iterationen am Anfange der Schleife
bestimmt, und die Schleifenvariable darf man nicht ändern.

n = 5
do i=1,n
n = n - 1
print *,n
end do

gibt die Zahlen von 4 bis 0 aus, anders als das oberflächlich
ähnlich erscheinende

int n = 5;
for (int i=1; i<=n; i++) {
n = n - 1;
printf ("%d\n", n);
}

Andere Programmiersprachen, andere Konzepte...

Bonita Montero

unread,
Nov 7, 2022, 12:16:05 AM11/7/22
to
Am 06.11.2022 um 20:23 schrieb Rainer Weikusat:

> Ja. Aber ich habe noch nie in meinem Leben in C eine for-Schleife
> benutzt :-). ...

Bist halt nicht wirklich Entwickler.

Claus Reibenstein

unread,
Nov 7, 2022, 7:29:14 AM11/7/22
to
Rainer Weikusat schrieb am 06.11.2022 um 20:23:

> Aber ich habe noch nie in meinem Leben in C eine for-Schleife
> benutzt :-).

Echt nicht? Ich welchen Bereichen programmierst Du, dass Du die noch nie
verwendet hast?

Oder programmierst Du Zählschleifen ausschließlich mit while? Warum?

Gruß
Claus

Helmut Schellong

unread,
Nov 7, 2022, 10:27:51 AM11/7/22
to
Es kommt vor, daß Programmierende irgendwelche Merkmale/Mittel der verwendeten Sprache
für unelegant/ungefällig/entbehrlich halten.
Diese werden dann - manchmal bis zum Lebensende - konsequent vermieden.

Ich bevorzuge beispielsweise:
open(), close(), read(), write(), truncate(), fstat(), fcntl(), dup(), dup2(), ...,
gegenüber <stdio.h>.
Also (partiell) POSIX- gegenüber C-Standard-Funktionen (in größeren Programmen).

Weiterhin verwende ich im großen Stil Komma-Listen.

Rainer Weikusat

unread,
Nov 7, 2022, 3:41:40 PM11/7/22
to
Ich halte das C for (;;) für ein mißlungenes, halbstrukturiertes
Konstrukt. Wenn man mal von den Flußkontrolloperatoren absieht, ist

for (<expr 1>;<expr 2>; <expr 3>) {
<body>;
}

identisch zu

<expr 1>;
while (<expr 2>) {
<body>;
<expr 3>;
}

Erster und dritte Ausdruck haben keine bestimmte Semantik sondern bloß
eine bestimmte logische Position im restlichen Text. Reinschreiben kann
man da, was man möchte. ZB ist

---
void prseq0(int start, int end)
{
int i;
for (i = start; i <= end; ++i)
printf("%d\n", i);
}
---

eine Funktion, die die Zahlen von start bis end ausgibt. Genausogut
könnte man aber auch

---
void prseq1(int start, int end)
{
int i;
for (i = start - 1; i <= end; printf("%d\n", i))
++i;
}
---

oder

---
void prseq2(int start, int end)
{
int i;
for (i = start; i <= end; printf("%d\n", i++));
}
---

benutzen. Ich finde sowas unordentlich.

Thomas Koenig

unread,
Nov 8, 2022, 1:21:08 AM11/8/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
> Claus Reibenstein <crei...@gmail.com> writes:
>> Rainer Weikusat schrieb am 06.11.2022 um 20:23:
>>
>>> Aber ich habe noch nie in meinem Leben in C eine for-Schleife
>>> benutzt :-).
>>
>> Echt nicht? Ich welchen Bereichen programmierst Du, dass Du die noch nie
>> verwendet hast?
>>
>> Oder programmierst Du Zählschleifen ausschließlich mit while? Warum?
>
> Ich halte das C for (;;) für ein mißlungenes, halbstrukturiertes
> Konstrukt.

Wie so manche Dinge in C, ist es "syntactic sugar", aber du scheinst
es eher unter "syntactic cyanide" einzusortieren :-)

Das gleiche gilt für a[i] statt *(a+i).

>Wenn man mal von den Flußkontrolloperatoren absieht, ist
>
> for (<expr 1>;<expr 2>; <expr 3>) {
> <body>;
> }
>
> identisch zu
>
><expr 1>;
> while (<expr 2>) {
> <body>;
> <expr 3>;
> }

Korrekt.

[...]

Das "abgesehen von Fließcontrollopertoren (schönes Wort, du
meinst \"continue\", nehme ich an)" kann aber durchaus begquem sein,
wenn ich z.B. genau in die nächste Iteration springen möchte.

for (i=0; i<n; i++) {
....
if (some_condition) continue;
...
}

müsste man z.B. mit

i = 0;
while (i<n) {
...
i++;
if (some_condition) {
i++;
continue;
}
...
}

oder mit

i = 0;
while (i<n) {
...
i++;
if (!some_condition) {
/* Rest der Schleife/
}

ausdrücken, beides wäre unschön.

Die Möglichkeit, die Iterationsvariable in der Schleife zu
deklarieren, die dazugekommen ist, ist auch nicht verkehrt,
weil sie einen zusätzlichen Block spart:

int i;
{
i = 0;
while (i<n) {
}
}
frisst einen Block, eine Einrückung und mehrere Zeilen mehr als

for (int i=0; i<n; i++) {
}

Insofern: Man kann mit for tatsächlich komische Dinge tun, wie du
weiter unten geschrieben hat, aber das kann man mit vielen anderen
Features von C auch (siehe den IOCCC).

> Erster und dritte Ausdruck haben keine bestimmte Semantik sondern bloß
> eine bestimmte logische Position im restlichen Text. Reinschreiben kann
> man da, was man möchte.

[...]

Bonita Montero

unread,
Nov 8, 2022, 11:42:41 AM11/8/22
to
Am 07.11.2022 um 16:28 schrieb Helmut Schellong:

> Ich bevorzuge beispielsweise:
> open(), close(), read(), write(), truncate(), fstat(), fcntl(), dup(),
> dup2(), ...,
> gegenüber <stdio.h>.
> Also (partiell) POSIX- gegenüber C-Standard-Funktionen (in größeren
> Programmen).

Ich seh da selten einen Vorteil ggü. Streams die binär geöffnet wurden.

> Weiterhin verwende ich im großen Stil Komma-Listen.

Du meinst den Komma-Operator ? Den verwend ich auch regelmäßig weil
das angenehmer zu lesen ist und vertikalen Platz auf dem Monitor spart.
Seltsamerweise ist der in C++ sogar überladbar. Ich glaub das hat noch
keiner praktisch genutzt, außer vielleicht so:

template<typename T1, typename T2>
T2 &operator ,( T1 &left, T2 &right )
{
static_assert( false, "I'm your boss, don't use the comma-operator !" );
return right;
}

Rainer Weikusat

unread,
Nov 8, 2022, 12:09:03 PM11/8/22
to
Thomas Koenig <tko...@netcologne.de> writes:
> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>> Claus Reibenstein <crei...@gmail.com> writes:
>>> Rainer Weikusat schrieb am 06.11.2022 um 20:23:
>>>
>>>> Aber ich habe noch nie in meinem Leben in C eine for-Schleife
>>>> benutzt :-).
>>>
>>> Echt nicht? Ich welchen Bereichen programmierst Du, dass Du die noch nie
>>> verwendet hast?
>>>
>>> Oder programmierst Du Zählschleifen ausschließlich mit while? Warum?
>>
>> Ich halte das C for (;;) für ein mißlungenes, halbstrukturiertes
>> Konstrukt.
>
> Wie so manche Dinge in C, ist es "syntactic sugar", aber du scheinst
> es eher unter "syntactic cyanide" einzusortieren :-)
>
> Das gleiche gilt für a[i] statt *(a+i).

[...]

> Das "abgesehen von Fließcontrollopertoren (schönes Wort, du
> meinst \"continue\", nehme ich an)" kann aber durchaus begquem sein,
> wenn ich z.B. genau in die nächste Iteration springen möchte.
>
> for (i=0; i<n; i++) {
> ....
> if (some_condition) continue;
> ...
> }
>
> müsste man z.B. mit
>
> i = 0;
> while (i<n) {
> ...
> i++;
> if (some_condition) {
> i++;
> continue;
> }
> ...
> }

Wäre mir bislang noch nicht störend aufgefallen. ZB würde ich für obiges
immer

i = 0;
do {
} while (++i < n);

benutzen, wodurch dieses Problem gar nicht erst aufträte.

Hauptsächlich kommt mir diese Teleportationsyntax aber einfach nur
bizarr vor: Was vor die Schleife gehört, schreibe ich davor. Und was am
Ende des Schleifenkörpers stehen soll, an dessen Ende und nicht vor das
Ende. Es ist vollkommen im Rahmen des Möglichen, daß es einen guten
Grund für diese seltsame Konstruktion gibt, der mir bloß noch nicht
eingefallen ist. Aber solange, bis das passiert ist, werde ich das
jedenfalls nicht benutzen.

Stefan Kanthak

unread,
Nov 8, 2022, 1:16:04 PM11/8/22
to
"Rainer Weikusat" <rwei...@talktalk.net> schrieb:
> Thomas Koenig <tko...@netcologne.de> writes:
>> Rainer Weikusat <rwei...@talktalk.net> schrieb:

>>> Ich halte das C for (;;) für ein mißlungenes, halbstrukturiertes
>>> Konstrukt.

Die Schoenheit liegt im Auge des Betrachters!

>> Das "abgesehen von Fließcontrollopertoren (schönes Wort, du
>> meinst \"continue\", nehme ich an)" kann aber durchaus begquem sein,
>> wenn ich z.B. genau in die nächste Iteration springen möchte.
>>
>> for (i=0; i<n; i++) {
>> ....
>> if (some_condition) continue;
>> ...
>> }
>>
>> müsste man z.B. mit
>>
>> i = 0;
>> while (i<n) {
>> ...
>> i++;
>> if (some_condition) {
>> i++;
>> continue;
>> }
>> ...
>> }
>
> Wäre mir bislang noch nicht störend aufgefallen. ZB würde ich für obiges
> immer
>
> i = 0;
> do {
> } while (++i < n);
>
> benutzen, wodurch dieses Problem gar nicht erst aufträte.

Dummerweise hast Du damit den Fehler eingebaut, den Schleifenkoerper
fuer n=0 auszufuehren!

> Hauptsächlich kommt mir diese Teleportationsyntax aber einfach nur
> bizarr vor: Was vor die Schleife gehört, schreibe ich davor. Und was am
> Ende des Schleifenkörpers stehen soll, an dessen Ende und nicht vor das
> Ende. Es ist vollkommen im Rahmen des Möglichen, daß es einen guten
> Grund für diese seltsame Konstruktion gibt, der mir bloß noch nicht
> eingefallen ist. Aber solange, bis das passiert ist, werde ich das
> jedenfalls nicht benutzen.

Bei

for (<Initialisierung der Schleifenvariablen, ggf. als komma-getrennte Liste>;
#ifdef ENTARTET
[ggf. vor jeder Schleifenbedingung auszufuehrende Anweisungen],
#endif
<Schleifenbedingung>;
#ifdef ENTARTET
[ggf. nach jeder Schleifenbedingung auszufuehrende Anweisungen],
#endif
<Iteration der Schleifenvariablen, ggf. als komma-getrennte Liste>)
#ifdef ENTARTET
continue;
#else
{ <Schleifenkoerper> }
#endif

stehen alle die Schleife[nvariablen] kontrollierenden Anweisungen beieinander
und sind in ihrer Funktion auf einen Blick erkennbar, auch fuer jemanden,
der diesen Code nicht verbrochen hat.

Stefan
--
<https://www.duden.de/rechtschreibung/Kanthaken>

Thomas Koenig

unread,
Nov 8, 2022, 2:19:38 PM11/8/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
Und was passiert, wenn n<0 ist?

Das ist eine andere Semantik, die Schleife ist dann nicht mehr
abweisend.

Rainer Weikusat

unread,
Nov 8, 2022, 2:33:42 PM11/8/22
to
Thomas Koenig <tko...@netcologne.de> writes:
> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>> Thomas Koenig <tko...@netcologne.de> writes:

[...]

>>> i = 0;
>>> while (i<n) {
>>> ...
>>> i++;
>>> if (some_condition) {
>>> i++;
>>> continue;
>>> }
>>> ...
>>> }
>>
>> Wäre mir bislang noch nicht störend aufgefallen. ZB würde ich für obiges
>> immer
>>
>> i = 0;
>> do {
>> } while (++i < n);
>>
>> benutzen, wodurch dieses Problem gar nicht erst aufträte.
>
> Und was passiert, wenn n<0 ist?

Dann hat das Beispiel keinen Sinn, weil der Code in der Schleife
ohnehin nicht ausgefüht wird.

Claus Reibenstein

unread,
Nov 8, 2022, 2:45:09 PM11/8/22
to
Rainer Weikusat schrieb am 08.11.2022 um 20:33:

> Thomas Koenig <tko...@netcologne.de> writes:
>
>> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>>
>>> Wäre mir bislang noch nicht störend aufgefallen. ZB würde ich für obiges
>>> immer
>>>
>>> i = 0;
>>> do {
>>> } while (++i < n);
>>>
>>> benutzen, wodurch dieses Problem gar nicht erst aufträte.
>>
>> Und was passiert, wenn n<0 ist?
>
> Dann hat das Beispiel keinen Sinn, weil der Code in der Schleife
> ohnehin nicht ausgefüht wird.

FALSCH!

Der Code im Body des o.b. Konstrukts wird _immer_ mindestens 1x
ausgeführt, auch bei n<0.

Gruß
Claus

Rainer Weikusat

unread,
Nov 8, 2022, 2:49:31 PM11/8/22
to
Das ist mir (und vermutlich jedem anderen) bekannt. Es ist aber müßig,
Aussagen über den Code in Schleifen, die ohnehin nicht ausgeführt
werden, zu machen und Zählschleifen werden normalerweise ausgeführt,
obwohl sie in C normalerweise eigentlich unrichtig als abweisende Schleifen
formuliert werden. Wenn man das Gegenteil für ein spezifisches Beispiel
für wesentlich hält, sollte man das dazuschreiben, denn sowas verhindert
vermeidbare Mißverständnisse.

Claus Reibenstein

unread,
Nov 8, 2022, 3:02:38 PM11/8/22
to
Rainer Weikusat schrieb am 08.11.2022 um 20:49:

> Claus Reibenstein <crei...@gmail.com> writes:
>
>> Rainer Weikusat schrieb am 08.11.2022 um 20:33:
>>
>>> Thomas Koenig <tko...@netcologne.de> writes:
>>>
>>>> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>>>>
>>>>> Wäre mir bislang noch nicht störend aufgefallen. ZB würde ich für obiges
>>>>> immer
>>>>>
>>>>> i = 0;
>>>>> do {
>>>>> } while (++i < n);
>>>>>
>>>>> benutzen, wodurch dieses Problem gar nicht erst aufträte.
>>>>
>>>> Und was passiert, wenn n<0 ist?
>>>
>>> Dann hat das Beispiel keinen Sinn, weil der Code in der Schleife
>>> ohnehin nicht ausgefüht wird.
>>
>> FALSCH!
>>
>> Der Code im Body des o.b. Konstrukts wird _immer_ mindestens 1x
>> ausgeführt, auch bei n<0.
>
> Das ist mir (und vermutlich jedem anderen) bekannt. Es ist aber müßig,
> Aussagen über den Code in Schleifen, die ohnehin nicht ausgeführt
> werden, zu machen und Zählschleifen werden normalerweise ausgeführt,
> obwohl sie in C normalerweise eigentlich unrichtig als abweisende Schleifen
> formuliert werden.

Du schreibst wirres Zeug.

Die obige Schleife wird _immer_ ausgeführt, auch dann, wenn die
Schleifenbedingung bereits zu Beginn nicht erfüllt ist. Im Gegensatz
dazu werden Zählschleifen in solchen Fällen eben _nicht_ ausgeführt.

Gruß
Claus

Rainer Weikusat

unread,
Nov 8, 2022, 3:30:05 PM11/8/22
to
Claus Reibenstein <crei...@gmail.com> writes:
> Rainer Weikusat schrieb am 08.11.2022 um 20:49:

[...]

>>>>>> i = 0;
>>>>>> do {
>>>>>> } while (++i < n);
>>>>>>
>>>>>> benutzen, wodurch dieses Problem gar nicht erst aufträte.
>>>>>
>>>>> Und was passiert, wenn n<0 ist?
>>>>
>>>> Dann hat das Beispiel keinen Sinn, weil der Code in der Schleife
>>>> ohnehin nicht ausgefüht wird.
>>>
>>> FALSCH!
>>>
>>> Der Code im Body des o.b. Konstrukts wird _immer_ mindestens 1x
>>> ausgeführt, auch bei n<0.
>>
>> Das ist mir (und vermutlich jedem anderen) bekannt. Es ist aber müßig,
>> Aussagen über den Code in Schleifen, die ohnehin nicht ausgeführt
>> werden, zu machen und Zählschleifen werden normalerweise ausgeführt,
>> obwohl sie in C normalerweise eigentlich unrichtig als abweisende Schleifen
>> formuliert werden.
>
> Du schreibst wirres Zeug.

Das ist eine sachlich irrelevante Beleidigung.

> Die obige Schleife wird _immer_ ausgeführt, auch dann, wenn die
> Schleifenbedingung bereits zu Beginn nicht erfüllt ist. Im Gegensatz
> dazu werden Zählschleifen in solchen Fällen eben _nicht_ ausgeführt.

Und das eine überflüssige Wiederholung.

Wie bereits geschrieben, wer Mißverständnisse wie das meinige vermeiden
möchte, sollte sich klarer ausdrücken. Wenn er sie denn vermeiden
möchte.

Helmut Schellong

unread,
Nov 8, 2022, 8:53:07 PM11/8/22
to
Es stimmt, daß es mittlerweile auf dieses Sparen nicht mehr ankommt.

Heute sind mir dadurch ermöglichte Syntaxvariationen wichtiger.
Beispielsweise hasse ich 'if (!(s=gksen-14))'.
Was mir stattdessen besser gefällt, ist nachfolgend oft zu sehen.

======================================================================================
/u/bsh/bsh.c: if (!O['i']||(O['n']=0, tty<7)) O['E']=0;
/u/bsh/bsh.c: if (c1=GET, c==c1||c1=='|'&&(c=ADD-1, 1)) f|=1;
/u/bsh/bsh.c: if (rch=0, tsti&&!MskT[c]) continue;
/u/bsh/bsh.c: if (Abuf[ap]=0, (ap-=ap0)||f&Fs0 /*&&!(f&Fuok)*/ ) ++ap;
/u/bsh/bsh.c: if (v_typ='U', !G.globl&&(G.ityp&(ITYP_D|ITYP_F))) v_typ='u';
/u/bsh/bsh.c: if (m&2&&(*p=b, r=='T')) break;
/u/bsh/bsh.c: if (r=='O'&&(cto||(Exit=0,0))&&(Exit=1, p0+nck>=pe)) Exit=2;
/u/bsh/bsh.c: if (co&&(Exit=cnt>0?0:1, 1)) Offs[0]=cnt, Offi=0;
/u/bsh/bsh.c: if (opt=0, C==3&&(--C,++A,1)&&A[-1][1]=='i') opt=1;
/u/bsh/bsh.c: if (pn=0, C>0&&A[0][0]=='+') pn=A[0]+1, --C,++A;
/u/bsh/bsh.c: if (fn=A[0], fn[0]!='-'&&fn[0]!='+') break;
/u/bsh/bsh.c: if (vpp=&V , nck=0, !G.globl&&(G.ityp&(ITYP_D|ITYP_F)))
/u/bsh/bsh.c: if (np=*++A, --C>0&&Cdig[np[0]]) bis=atoi_F(np), --C,++A;
/u/bsh/bsh.c: if (znam[i]=0, von<0||NameCk(znam)!=NULL) bsh_Err(LS16|E_PARBEZ, znam);
/u/bsh/bsh.c: for (l=0; (c=*s, c)&&l<szof(Cifs0); ++l,++s) {
/u/bsh/bsh.c: if (bp>=buf+sizeof(buf)-2&&(bp=buf, !fnd))
/u/bsh/bsh.c: if (i=0, len&&(eo&4)) break;
/u/bsh/bsh.c: if (c=eo, (c&2)||(c&1)&&(c&4)) c|=8, i=0;
/u/bsh/bsh.c: /*if (nr!=i&&(nw-=i-nr, O['_'])) write1("nr!=r" NL);*/
/u/bsh/bsh.c: //while (++i, *++n) if (!Cnam[*n]||i>=NAMLEN) return n;
/u/bsh/bsh.c: while (++i, *++n&&!Cstrn[*n]) if (!Cnam[*n]||i>=NAMLEN) return NULL;
/u/bsh/bsh.c: if (vp!=NULL&&(t0=vp->t, (t0&V_r))) bsh_Err(LS16|E_RDONLY, vn);
/u/bsh/bsh.c: if ((ap=Args[i], ap)&&ap>=a&&ap<b)
/u/bsh/bsh.c: if ((path=dirs=file, dirs)&&*dirs) {
/u/bsh/bsh.c: if (++p,*bp++ =0, dp==dirs&&(--bp, 1)||!dp[1])
/u/bsh/bsh.c: if (s=ErrS[i].s, !*s&&str) s=str, str=0;
/u/bsh/bsh.c: ||c==gOEND&&(ge=--G.goend,1))&&(Exe|=X_If, 1) );
/u/bsh/bsh.c: ||c==gOEND&&(ge=--G.goend,1))&&(Exe|=X_If, 1) );
/u/bsh/bsh.c: ||c==gOEND&&(++cg,1))&&(Exe|=X_WH, 1) );
/u/bsh/bsh.c: ||c==gOEND&&(++cg,1))&&(Exe|=X_WH, 1) );
/u/bsh/bsh.c: if (nn=c-3, nn&&Vn>=0)
/u/bsh/bsh.c: while ((C-=na, C>0)&&!Exe&&(awi+=na,Seek(pos, 0), 1));
/u/bsh/bsh.c: if (a=A[0], Cdig[*a]||(*a=='-'||*a=='+'||*a=='.')&&Cdig[a[1]]) {
/u/bsh/bsh.c: if (a=A[0], C>0&&!(Cnam[*a]&&!Cdig[*a])) {
/u/bsh/bsh.c: if (ec-=o, o=='('&&ec!=1||o!='('&&ec!=2)
/u/bsh/bsh.c: case '?': if (z=Zs[--zs], z.fi==1&&!z.i||
/u/bsh/bsh.c: if ((c=*lp++)==0||c==EoF) return (S->A=lp, 0);
/u/bsh/bsh.c: if (c=='#'&&(c2=*lp, c2)&&c2!=EoF) {
/u/bsh/bsh.c: if (++lp, (c=c2)==lSHL||c==lSHR)
/u/bsh/bsh.c: if ((c=rGET)==0||c==EoF) return (rBK, 0);
/u/bsh/bsh.c: else if (*v=0L, O['u']&&!Exe) bsh_Err(LS16|E_VREAD, nam);
/u/bsh/bsh.c: for (; C>0&&a[0]&&((pm=a[0][0], pm=='-')||
/u/bsh/bsh.c: for (endarg=0,i=1; (c=a[0][i], c)||i==1; ++i) {
/u/bsh/bsh.c: if (o_c&&(CstrP=cstr, !cstr)) { i=E_CSTR; goto SOE; }
/u/bsh/mod/cat.c: for (--C,++A; C>0&&(a=A[0], *a=='-'); --C,++A) {
/u/bsh/mod/catv.c: if (i-='a', i<0||i>=26||conv[i]=='_') continue;
/u/bsh/mod/comx.c: if (i=0x7fffffff, a[1]>='0'&&a[1]<='9') i=atoi_F(a+1);
/u/bsh/mod/comx.c: if (b=A[0][0], b>='0'&&b<='9') i= b-'0';
/u/bsh/mod/comx.c: if (b=A[0][0], b>='0'&&b<='9') i= b-'0';
/u/bsh/mod/comx.c: if (i=0x7fff, a[1]>='0'&&a[1]<='9') i=atoi_F(a+1);
/u/bsh/mod/cut.c: c=='\r'||c=='\n'&&(ncf=l=0, 1)) *op++ =c;
/u/bsh/mod/cut.c: if (tre=0, l<l_&&ncf>=lst[l][0]) {
/u/bsh/mod/echo.c: if (C>0&&(bp=*A, *bp=='-')) {
/u/bsh/mod/echo.c: if (i-='a', i<0||i>=26||conv[i]=='_') continue;
/u/bsh/mod/expr.c: if (cb[0]!=':' || cb[1]&&(wr=0, cb[1]==':'?cb[2]:NameCk(nam=cb+1)!=NULL))
/u/bsh/mod/expr.c: if (ucbuf[l=o]=0, wr&&l>0) {
/u/bsh/mod/expr.c: if (a+=j, num==0||i==0) continue;
/u/bsh/mod/fnex.c: for (dp=dir; (*dp=*pp, *pp&&*pp!=PNT); ++dp,++pp)
/u/bsh/mod/fnex.c: for (p0=path; (*name=*path, *path&&*path!=PNT); ++name,++path)
/u/bsh/mod/fnex.c: for (; (*pa=*pb, *pb)&&*pb!=PNT; ++pa,++pb);
/u/bsh/mod/fnex.c: for (pa=file; *pb!=PNT&&(*pa=*pb, *pb); ++pa,++pb);
/u/bsh/mod/fumod.c: else if (w&&(++n, !(o&64)))
/u/bsh/mod/fumod.c: if ((o&(2|8|128))==10&&l&&(++n, !(o&64)))
/u/bsh/mod/fumod.c: if (w!=7&&(w=0, ot&t)) ++w;
/u/bsh/mod/fumod.c: if (w&&(++n, !(o&64))) writeE(1, dirl+s, lw-s);
/u/bsh/mod/fumod.c: if (lw+=l, o&8 && t&EMD)
/u/bsh/mod/fumod.c: else if (w&&(++n, !(o&64))) writeE(1, dir, lw);
/u/bsh/mod/fumod.c: if (!lw&&o&128&&l&&(++n, !(o&64)))
/u/bsh/mod/fumod.c: if (k=ap[i], k!='.'&&k!='-') {
/u/bsh/mod/fumod.c: for (c=1,z=0; p<pe&&(c=*p, c); p+=1) {
/u/bsh/mod/fumod.c: for (z=mp[0],l=1; l<5&&(c=mp[l], c); ++l) {
/u/bsh/mod/fumod.c: if (sp=N, l&&dir[l-1]!=PNT) sp=PNTS;
/u/bsh/mod/fumod.c: if (lw+=l, t&EMD && o&8) {
/u/bsh/mod/fumod.c: if (qt&EMD&&(I.o|=o&8, I.o&128)
/u/bsh/mod/fumod.c: if (z[I.lz=lz]=0, (zt=zt0)&EMD &&!(I.o&(512|8)) ) {
/u/bsh/mod/fumod.c: if (z[I.lz=lz]=0, zt&EMD&&!(qt&EMD)) {
/u/bsh/mod/fumod.c: if (s=slF[i][0], s&&s<min) min=s, mi=i;
/u/bsh/mod/function.c: do if (*t==MSKCH&&EXMCH(t)) ++t; while (*s++ = *t, *t++);
/u/bsh/mod/function.c: if (*cp&&(t=2, l)) *buf++ =0, *++pa=buf, l=0;
/u/bsh/mod/function.c: if (*cp&&(t=0, l)) *buf++ =0, *++pa=buf;
/u/bsh/mod/function.c: if (s=S0, s&&n>0) { register const byte *a=S1; va_list ap;
/u/bsh/mod/function.c: if (s=S0, s&&n>0) { const BYTE *sa; va_list a;
/u/bsh/mod/function.c: for (s=S; (c=*s, c); ++s) if (c>='a'&&c<='z') *s-='a'-'A';
/u/bsh/mod/function.c: if (ic=*on, ic<'0'||ic>'9') { r=-1; break; }
/u/bsh/mod/function.c: while ((ic=*++on, ic)&&ic>='0'&&ic<='9');
/u/bsh/mod/function.c: for (c=0; Cnam[*s]&&(yx[i].nam[c]=*s, 1); ++c,++s);
/u/bsh/mod/grep.c: for (--C,++A; C>0&&(a=A[0], oe||*a=='-'&&(!o.e||a[1]=='e')); --C,++A) {
/u/bsh/mod/kzed.c: if (zi>1&&(c==','&&(++komma, 1)||c=='?'&&(++quest, 1))) {
/u/bsh/mod/kzed.c: if (n=nz, n<nzeil-1&&!(komma|quest)) {
/u/bsh/mod/line.c: if (C>0&&(a=A[0], (*a=='-'||*a=='+')&&a[1]>='0'&&a[1]<='9')) {
/u/bsh/mod/line.c: if (n|=1, pm=='-'&&lnu==bis) break;
/u/bsh/mod/mucrc.c: if (++A, --C<4||C>5) return 1;
/u/bsh/mod/patt.c: if (!*++b||*b==MSKCH&&EXMCH(b)&&(++b, 0)) break;
/u/bsh/mod/patt.c: if (p=0, *b=='['&&b[-1]!=MSKCH)
/u/bsh/mod/patt.c: if (!*++b||*b==MSKCH&&EXMCH(b)&&(++b, 0)) break;
/u/bsh/mod/prints.c: if (vnam=0, C>=2&&A[0][0]=='v'&&A[0][1]=='s') vnam=A[1];
/u/bsh/mod/readx.c: else if (p->vsp=0, sp&&p==sp) sp=0;
/u/bsh/mod/readx.c: else if (p->vsp=0, sp&&p==sp) sp=0;
/u/bsh/mod/readx.c: else if (p->vsp=0, sp&&p==sp) sp=0;
/u/bsh/mod/readx.c: for (i=0; i<NE(lzol[0])&&(vsp=sp[i].list, vsp); ++i) { byte *vpi, z,c,dl; int r,d,o;
/u/bsh/mod/readx.c: for (i=1; i<NE(lzol[0])&&(px=&sp[i],q=px->list, q)&&(z=px->ziel, z); ++i) { int lq;
/u/bsh/mod/regexp.c: # define isLET (c=*patt++, c>='a'&&c<='z'||c>='A'&&c<='Z')
/u/bsh/mod/regexp.c: # define isLOW (c=*patt++, c>='a'&&c<='z')
/u/bsh/mod/regexp.c: # define isUPP (c=*patt++, c>='A'&&c<='Z')
/u/bsh/mod/regexp.c: else while ( bre.low--) if (c=*patt++, isDIG(c)||!c) goto ADVR0;
/u/bsh/mod/regexp.c: else while (bre.size--) if (c=*patt++, isDIG(c)||!c) break;
/u/bsh/mod/regexp.c: else while ( bre.low--) if (c=*patt++, Cnam[c]||!c) goto ADVR0;
/u/bsh/mod/regexp.c: else while (bre.size--) if (c=*patt++, Cnam[c]||!c) break;
/u/bsh/mod/regexp.c: # define isLET (c=*patt++, c>='a'&&c<='z'||c>='A'&&c<='Z')
/u/bsh/mod/regexp.c: # define isLOW (c=*patt++, c>='a'&&c<='z')
/u/bsh/mod/regexp.c: # define isUPP (c=*patt++, c>='A'&&c<='Z')
/u/bsh/mod/regexp.c: else while ( low--) if (c=*patt++, isDIG(c)||!c) goto ADVR0;
/u/bsh/mod/regexp.c: else while (size--) if (c=*patt++, isDIG(c)||!c) break;
/u/bsh/mod/regexp.c: else while ( low--) if (c=*patt++, Cnam[c]||!c) goto ADVR0;
/u/bsh/mod/regexp.c: else while (size--) if (c=*patt++, Cnam[c]||!c) break;
/u/bsh/mod/rel.c: if (zv=1, nr>1&&buf.b[nr-2]=='\r') zv=2;
/u/bsh/mod/sem.c: if (--C<=0||(++A, A[0][0]!='-')) goto RET1;
/u/bsh/mod/sem.c: if (--C<=0||(++A, A[0][0]!='-')) goto RET1;
/u/bsh/mod/test.c: if (--c==0||av[c][0]!=']'||(a1=av[c][1], !k&&a1)||k&&a1!=']'
/u/bsh/mod/test.c: if ((po=a[0][0], po)&&!a[0][1]) {
/u/bsh/mod/test.c: if (os<0||(t=Os[os], po>tstp[t])) { Os[++os]=onu;continue; }
/u/bsh/mod/test.c: if (sc=Ss[1][0], !Cdig[sc]&&Cnam[sc]) {
/u/bsh/mod/test.c: if (sc=Ss[0][0], !Cdig[sc]&&Cnam[sc]) {
/u/bsh/mod/test.c: if ((i=0, o[0]&&o[0]<=127)&&(++i, o[1])&&(o[1]>127||(++i, o[2])))
/u/bsh/mod/tr.c: if (c=f[1], c=='['||c=='\\') ++f;
/u/bsh/mod/wc.c: for (--C,++A; C>0&&(a=A[0], *a=='-'); --C,++A) {
/u/bsh/mod/xregexp140715.c: if (noop=cre, typ!='M'&&typ!='|'&&typ!='E')
/u/bsh/mod/xregexp.c: for (i=0; i<6&&(a=lc[i], a); ++i) xrei.zk[zk_x][a]= 1;
/u/bsh/mod/xregexp.c: for (i=0; i<6&&(a=uc[i], a); ++i) xrei.zk[zk_x][a]= 1;
/u/bsh/mod/xregexp.c: for (i=0; i<15&&(a=pt[i], a); ++i) xrei.zk[zk_Po][a]= 1;
/u/bsh/mod/sha.c: if (++cs, c>='0'&&c<='9'||c>='a'&&c<='f'||c>='A'&&c<='F')
/u/bsh/mod/bgrep.c: if (o=0, bg.Nmax-bg.Nr>0&&bg.Nr>=pgsz) bg.Nr-=pgsz, o=pgsz-fl;
/u/bsh/mod/expr070815.c: cb[1]&&(wr=0, cb[1]==':'?cb[2]:NameCk(nam=cb+1)!=NULL))
/u/bsh/mod/expr070815.c: if (cbuf[l=o]=0, wr&&l>0) {
/u/bsh/mod/hx.c: for (--C,++A; C>0&&(a=A[0], *a++ =='-'); --C,++A) {
/u/bsh/mod/hx.c: if (!nhc||nhc<nb&&(offs_-=nhc, 1)) break;
/u/bsh/mod/hx.c: (!memcmp1(l.b, L.b, nhc)||(skip=0, skip)) ) {
/u/bsh/mod/hx.c: if (hx.bnmode=='b'&&(hx.bdmode=='h'||hx.bdmode=='H'&&(aA='A', 1))) {
/u/bsh/mod/hx.c: if (c=*cp, c<' '||c>=127) *cp='.';
/u/bsh/mod/pg.c: for (endarg=0,i=1; (c=a[0][i], c)||i==1; ++i) {
/u/bsh/mod/pg.c: if (lcnt&&lcnt<nl&&pg.otty&&(l0-=nl-lcnt, l0>=1L)) goto AGAIN;
/u/bsh/mod/pg.c: if (lcnt&&lcnt<nl&&pg.otty&&(l0-=nl-lcnt, l0>=1L)) goto AGAIN;
/u/bsh/mod/pg.c: if ((pgp=pg.pga[p], pgp<A)||pgp>=A+(int)sizeof(buf)-IPL*cols) { l64[0]=0;
/u/bsh/mod/pg.c: if (nl!=lnu||lp==bp) return (pg.eof=2, 0);
======================================================================================

Bonita Montero

unread,
Nov 8, 2022, 10:49:23 PM11/8/22
to
Am 09.11.2022 um 02:53 schrieb Helmut Schellong:

> Es stimmt, daß es mittlerweile auf dieses Sparen nicht mehr ankommt.

Mittlerweile ? Das war garantiert noch nie so !

Thomas Koenig

unread,
Nov 9, 2022, 1:26:35 AM11/9/22
to
Die Argumention ist schräg. Nach der C-Norm ergibt das Beispiel
einen Sinn, genau weil sie nicht ausgeführt wird.

Vergleiche Fortran: Da hat man DO-Schleifen in Fortran 77
ebenfalls abweisend gemacht. Leere Arrays sollte man vernünftig
behandeln.

Aber nehmen wir ein anderes Beispiel: Durchlaufen einer
(möglicherweise leeren) verketteten Listes, mit Bedingungen
drin. Behaupte jetzt nicht, eine leere verkettete Liste
wäre sinnlos.

Formulierung mit for-Schleife:

for (mytyp * p = first; p; p = p->next) {
...
if (cond1)
continue;
...
if (cond2)
continue;
}

Wie würdest du das ohne for-Schleife formulieren, wie viele Zeilen
(bei gleichem Umbruch wie oben) kämen dazu, und wie viele
Statements?

Thomas Koenig

unread,
Nov 9, 2022, 1:32:00 AM11/9/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
> Claus Reibenstein <crei...@gmail.com> writes:
>> Rainer Weikusat schrieb am 08.11.2022 um 20:33:
>>> Thomas Koenig <tko...@netcologne.de> writes:
>>>> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>>>>
>>>>> Wäre mir bislang noch nicht störend aufgefallen. ZB würde ich für obiges
>>>>> immer
>>>>>
>>>>> i = 0;
>>>>> do {
>>>>> } while (++i < n);
>>>>>
>>>>> benutzen, wodurch dieses Problem gar nicht erst aufträte.
>>>>
>>>> Und was passiert, wenn n<0 ist?
>>>
>>> Dann hat das Beispiel keinen Sinn, weil der Code in der Schleife
>>> ohnehin nicht ausgefüht wird.
>>
>> FALSCH!
>>
>> Der Code im Body des o.b. Konstrukts wird _immer_ mindestens 1x
>> ausgeführt, auch bei n<0.
>
> Das ist mir (und vermutlich jedem anderen) bekannt. Es ist aber müßig,
> Aussagen über den Code in Schleifen, die ohnehin nicht ausgeführt
> werden, zu machen und Zählschleifen werden normalerweise ausgeführt,

"normalerweise" meinetwegen. Allerdings ist der Punkt dabei, dass
für n=0 halt _nichts_ passiert.

Hilft gegen eine ganze Menge Fehler.

> obwohl sie in C normalerweise eigentlich unrichtig als abweisende Schleifen
> formuliert werden.

Da ist nichts unrichtig dran. Fortran, der Meister der Zählschleifen,
hat es vorgemacht, seit FORTRAN 77 sind die auch definiert abweisend
(vorher war es undefiniert).

>Wenn man das Gegenteil für ein spezifisches Beispiel
> für wesentlich hält, sollte man das dazuschreiben, denn sowas verhindert
> vermeidbare Mißverständnisse.

*prust*

OK, dann schreibe ich das für alle Zukunft dazu: Wenn ich einen
Codeschnipsel poste, dann meine ich damit das, was da nach den
Regeln der entsprechenden Programmiersprache steht, und nicht
irgendetwas anderes, ähnliches.

Es überrascht mich, das jemand, der ja anscheinend einiges an
Programmiererfahrung hat wie du, einfach mal die Semantik von
Code ändert.

Rainer Weikusat

unread,
Nov 9, 2022, 7:09:05 AM11/9/22
to
Thomas Koenig <tko...@netcologne.de> writes:
> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>> Claus Reibenstein <crei...@gmail.com> writes:
>>> Rainer Weikusat schrieb am 08.11.2022 um 20:33:
>>>> Thomas Koenig <tko...@netcologne.de> writes:
>>>>> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>>>>>
>>>>>> Wäre mir bislang noch nicht störend aufgefallen. ZB würde ich für obiges
>>>>>> immer
>>>>>>
>>>>>> i = 0;
>>>>>> do {
>>>>>> } while (++i < n);
>>>>>>
>>>>>> benutzen, wodurch dieses Problem gar nicht erst aufträte.
>>>>>
>>>>> Und was passiert, wenn n<0 ist?
>>>>
>>>> Dann hat das Beispiel keinen Sinn, weil der Code in der Schleife
>>>> ohnehin nicht ausgefüht wird.
>>>
>>> FALSCH!
>>>
>>> Der Code im Body des o.b. Konstrukts wird _immer_ mindestens 1x
>>> ausgeführt, auch bei n<0.
>>
>> Das ist mir (und vermutlich jedem anderen) bekannt. Es ist aber müßig,
>> Aussagen über den Code in Schleifen, die ohnehin nicht ausgeführt
>> werden, zu machen und Zählschleifen werden normalerweise ausgeführt,
>
> "normalerweise" meinetwegen. Allerdings ist der Punkt dabei, dass
> für n=0 halt _nichts_ passiert.
>
> Hilft gegen eine ganze Menge Fehler.

Darum ging's angeblich nicht. Sondern um Code im
Schleifenkörper. Vorbedingungen für n hattest Du keine genannt und
Kontext, aus dem man sie hätte ersehen können, gab es auch
keinen. Folglicherweise ist

Vorbedingung: n > 0

so gültig, wie jede beliebige andere. Ansonsten ist die
Alternativkonstruktion:

i = -1;
while (++i < n) {
}

trivial genug, daß man sie wohl nicht unbedingt posten müsste. Der Punkt
ist in beiden Fällen, daß man den imaginären «Vorteil» des for
(;;)-Konstrukts, nicht einen sondern zwei Positionen zu haben (Warum
keine 15? Damit könnte man hier noch viel mehr optisches Chaos anrichten!), wo man
irgendwelchen Code reinschreiben kann, der unabhängig von
Flußkontrollanweisungen ausgeführt wird, mit einer solchen Position,
genauso hat.

[...]

>>Wenn man das Gegenteil für ein spezifisches Beispiel
>> für wesentlich hält, sollte man das dazuschreiben, denn sowas verhindert
>> vermeidbare Mißverständnisse.
>
> *prust*
>
> OK, dann schreibe ich das für alle Zukunft dazu: Wenn ich einen
> Codeschnipsel poste, dann meine ich damit das, was da nach den
> Regeln der entsprechenden Programmiersprache steht, und nicht
> irgendetwas anderes, ähnliches.

Wenn Du bestimmte Vorbedingungen (siehe oben) für von Dir geposteten
Code vorraussetzt, mußt die nennen, wenn man sie nicht anderweitig
(Kontext) ersehen kann. Oder damit leben, daß Leute, die sich zu etwas
ganz anderem äußern wollten, sich welche aussuchen, die ihnen passen,

Thomas Koenig

unread,
Nov 9, 2022, 5:10:53 PM11/9/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
Also gibt es keine, n kann jeden belibigen Wert haben, und sich
eine aus den Fingern zu saugen, ist ein bisschen komisch. Aber
gut, wenn du so arbeitest, meinetwegen.

>Folglicherweise ist
>
> Vorbedingung: n > 0
>
> so gültig, wie jede beliebige andere.

... nämlich gar nicht.

Aber widerholen wir doch noch mal ein Beispiel aus einem anderen
Artikel. Wie würdest du (wenn first entweder NULL ist oder auf
den ersten Eintrag einer vergetteten Liste zeigt)

Wie würdest du

for (meintyp * p = first; p; p = p->next) {
/*Teil 1 */
if (cond1)
continue;
/*Teil 2 */
if (cond2)
continue;
/*Teil 3 */
}

möglichst elegant mit einer while-Schleife erledigen?

Rainer Weikusat

unread,
Nov 10, 2022, 11:46:13 AM11/10/22
to
Thomas Koenig <tko...@netcologne.de> writes:
> Rainer Weikusat <rwei...@talktalk.net> schrieb:

[...]

>>>> Das ist mir (und vermutlich jedem anderen) bekannt. Es ist aber müßig,
>>>> Aussagen über den Code in Schleifen, die ohnehin nicht ausgeführt
>>>> werden, zu machen und Zählschleifen werden normalerweise ausgeführt,
>>>
>>> "normalerweise" meinetwegen. Allerdings ist der Punkt dabei, dass
>>> für n=0 halt _nichts_ passiert.
>>>
>>> Hilft gegen eine ganze Menge Fehler.
>>
>> Darum ging's angeblich nicht. Sondern um Code im
>> Schleifenkörper. Vorbedingungen für n hattest Du keine genannt und
>> Kontext, aus dem man sie hätte ersehen können, gab es auch
>> keinen.
>
> Also gibt es keine, n kann jeden belibigen Wert haben, und sich
> eine aus den Fingern zu saugen, ist ein bisschen komisch. Aber
> gut, wenn du so arbeitest, meinetwegen.

Arbeitest Du eigentlich so, wie Dein anscheinend durch nichts zu
bremsender Hang, ebenso unsinnige wie unsachliche Mutmaßungen über
andere Personen zu machen, nahelegt? Also, um es mal auf Deutsch zu
sagen, wie der typische Büroradfahrer, der reflexmäßig nach oben buckelt
und nach unten tritt und weitere Interessen oder Fähigkeiten bestenfalls
zufällig besitzt?

Thomas Koenig

unread,
Nov 10, 2022, 4:33:10 PM11/10/22
to
Rainer Weikusat <rwei...@talktalk.net> schrieb:
> Thomas Koenig <tko...@netcologne.de> writes:
>> Rainer Weikusat <rwei...@talktalk.net> schrieb:
>
> [...]
>
>>>>> Das ist mir (und vermutlich jedem anderen) bekannt. Es ist aber müßig,
>>>>> Aussagen über den Code in Schleifen, die ohnehin nicht ausgeführt
>>>>> werden, zu machen und Zählschleifen werden normalerweise ausgeführt,
>>>>
>>>> "normalerweise" meinetwegen. Allerdings ist der Punkt dabei, dass
>>>> für n=0 halt _nichts_ passiert.
>>>>
>>>> Hilft gegen eine ganze Menge Fehler.
>>>
>>> Darum ging's angeblich nicht. Sondern um Code im
>>> Schleifenkörper. Vorbedingungen für n hattest Du keine genannt und
>>> Kontext, aus dem man sie hätte ersehen können, gab es auch
>>> keinen.
>>
>> Also gibt es keine, n kann jeden belibigen Wert haben, und sich
>> eine aus den Fingern zu saugen, ist ein bisschen komisch. Aber
>> gut, wenn du so arbeitest, meinetwegen.
>
> Arbeitest Du eigentlich so, wie Dein anscheinend durch nichts zu
> bremsender Hang, ebenso unsinnige wie unsachliche Mutmaßungen über
> andere Personen zu machen, nahelegt?

Meine Güte, da reagiert aber jemand gereizt. Ich bilde mir mein
Urteil nach dem, was du hier schreibst (und andere Leser tun das
genauso). Und Code zu transformieren, indem man nicht spezifizierte
Bedingungen verwendet, ist halt ein Fehler, und einen solchen
(durchaus lässlichen) Fehler partout nicht zugeben zu wollen...
naja, da kann sich jeder seinen Reim drauf machen.

[Müll entsorgt]

Du schriebst ja, du hättest noch nie im Leben eine for-Schleife
verwendet. Ich frage dich jetzt schon zum Dritten Mal, du
hast entweder nicht geantwortet oder gesnippt, wie denn deine
bevorzugte Lösung mittels while-Schleife für

for (meintyp * p = first; p; p = p->next) {
/*Teil 1 */
if (cond1)
continue;
/*Teil 2 */
if (cond2)
continue;
/*Teil 3 */
}

aussieht. Wenn du noch nie im Leben for-Schleifen verwendet hast,
wie du upthread verwendet hast, wird dir sicher eine elegante
Lösung dafür einfallen. Wenn du nicht antwortest, ist davon
auszugehen, dass dir nix vernünftiges eingefallen ist.

So be it. Du wärst nicht der erste, der sich mal mit einer
Aussage vergallopiert hat (habe ich auch schon oft genug :-)
0 new messages