Post by Jens Schmidt------ schnipp ------
#include <stdio.h>
#define SPEICHER 100
static int speicher [SPEICHER];
static int adressen [SPEICHER];
int *f (int i)
{
static int frei = 0;
if (adressen [i] == 0)
adressen [i] = ++frei;
return &speicher [adressen [i]];
}
int g (void)
{
return 42;
}
void show (int i)
{
printf ("Variable %d liegt in speicher[%d] und hat Wert %d\n",
i, adressen [i], speicher [adressen [i]]);
}
int main (void)
{
*f(1) = *f(2) = *f(3) = g();
show (1);
show (2);
show (3);
return 0;
}
------ schnipp ------
Es gibt keine Regel, welcher der drei Aufrufe von f() in welcher
Reihenfolge erfolgt, und wie der Aufruf von g() damit zusammenhängt.
Soweit richtig.
Post by Jens SchmidtGenaugenommen kann das auch parallel erfolgen. Wir haben also
undefiniertes Verhalten im if()-Teil von f(), solange kein Lock eine
Serialisierung erzwingt.
Nein. Diese Frage wurde seinerzeit in comp.std.c ausführlich diskutiert
und inzwischen im Standard geklärt:
| Evaluations A and B are indeterminately sequenced when A is sequenced
| either before or after B, but it is unspecified which.13)
[...]
| 13) The executions of unsequenced evaluations can interleave.
| Indeterminately sequenced evaluations cannot interleave, but can be
| executed in any order.
[...]
| There is a sequence point after the evaluations of the function
| designator and the actual arguments but before the actual call. Every
| evaluation in the calling function (including other function calls) that
| is not otherwise specifically sequenced before or after the execution of
| the body of the called function is indeterminately sequenced with
| respect to the execution of the called function.94)
[...]
| 94) In other words, function executions do not ‘‘interleave’’ with each
| other.
Die drei Aufrufe von f sowie der Aufruf von g können also in beliebiger
Reihenfolge aber nicht gleichzeitig/überlappend erfolgen.
Post by Jens SchmidtDas einzige, was sicher ist, ist dass jeweils beide Funktionsaufrufe
links und rechts einer Zuweisung erfolgen, bevor die Zuweisung selber
ausgeführt wird.
Da bin ich mir nicht so sicher. Wir haben hier 6 Sequence-Points:
1) Vor dem Ausdruck.
2) nach der Evaluation von f und 1 und vor dem Aufruf von f(1)
3) nach der Evaluation von f und 2 und vor dem Aufruf von f(2)
4) nach der Evaluation von f und 3 und vor dem Aufruf von f(3)
5) nach der Evaluation von g und vor dem Aufruf von g()
6) nach dem Ausdruck.
Die Zuweisungen müssen zwischen 1 und 6 passieren. 2 bis 5 müssen
ebenfalls zwischen 1 und 6 passieren. Über die relative Reihenfolge der
Zuweisungen und der Sequence-Points 2 bis 5 wird nichts ausgesagt.
Natürlich werden hier die Ergebnisse von f() für die Zuweisung benötigt,
also müssen sie vorher aufgerufen werden, aber g() liefert einen
konstanten Wert, also könnte der Compiler IMHO das so umformulieren:
t1 = f(1);
*t1 = 42;
t2 = f(2);
*t2 = 42;
t3 = f(3);
*t3 = 42;
g();
Rein theoretisch. In der Praxis halte ich das für ziemlich
unwahrscheinlich (sehr wahrscheinlich hingegen ist, dass der Aufruf von
g() inline expandiert wird, was zu den ersten 6 Zeilen führen könnte).
hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel