R
Richard Heathfield
Keith Thompson said:
Well, again that isn't quite true. Consider, for example, the following
code:
{
int a = foo();
int b = bar();
if(a + b < c)
{
int d = c - (a + b); /* X */
baz(d * quux() / (d - foo()));
quuy(&d);
quuz(d * quua());
}
}
The line marked X is the last line in which a and b are used. The Standard
therefore allows implementations licence to destroy a and b /before/ it
destroys d - for example, a and b can be history by the time the sequence
point in line X occurs, even though d still exists, because the program
still behaves "as if" a and b exist, and no strictly conforming program
can tell the difference (because if it could, obviously the compiler
wouldn't do the early destruction in the first place). By virtue of its
"as if" rule, the C language *does not mandate* LIFO auto allocation.
The unit of allocation is a collection of automatic objects declared
in a particular scope. That collection is conceptually created in
what can be thought of as a single "push" operation, and destroyed in
what can be thought of as a single "pop" operation. In that sense,
the language rules do imply a stack (an abstract last-in first-out
data structure, however it's implemented).
Well, again that isn't quite true. Consider, for example, the following
code:
{
int a = foo();
int b = bar();
if(a + b < c)
{
int d = c - (a + b); /* X */
baz(d * quux() / (d - foo()));
quuy(&d);
quuz(d * quua());
}
}
The line marked X is the last line in which a and b are used. The Standard
therefore allows implementations licence to destroy a and b /before/ it
destroys d - for example, a and b can be history by the time the sequence
point in line X occurs, even though d still exists, because the program
still behaves "as if" a and b exist, and no strictly conforming program
can tell the difference (because if it could, obviously the compiler
wouldn't do the early destruction in the first place). By virtue of its
"as if" rule, the C language *does not mandate* LIFO auto allocation.