Variables allocated on stack

K

Keith Thompson

Malcolm McLean said:
I had such an implementation. int was eight bits, double 24 bits, of
which 7 were exponent. Recursion was not supported. There was no
malloc. Essentially every variable had an invisible "static"
qualifier. It wasn't conforming, but it was clearly C.

I'd say such an implementation is C-like, but it's not C.

I think what Quentin is referring to is implementations on which
activation records for function calls are not necessarily allocated
at monotonically increasing or decreasing addresses.

Any conforming C implementation must have something that behaves in
a stack-like manner. It needn't be a contiguous region of memory.
And even if, as Quentin suggested, the implementation uses a fixed
length buffer for active function calls, it still has to behave in
a stack-like manner.
 
D

David Thompson

Plus, when a "static" function pointer is passed around, either the
function must get the standard calling convention or a stub must be
written.
Or the function pointers are nonstandardly implementation-dependently
qualified (which I've seen). Or you use fat pointers that contain the
convention (which I've not seen, but it would be conforming).
Or, an implementation that wants a non-standard calling convention may
use a non-standard keyword to differentiate internal functions that
must be called with the new calling convention from exported functions.

keyword or pragma or config setting, or possibly something else. Or
the compiler can guess -- for example, any 'static' function whose
address is never directly exported nor stored anywhere that could be
exported can safely be 'optimized'. That's a simple rule that suffices
for probably most useful cases.
 
T

Tim Rentsch

Keith Thompson said:
Markus Wichmann said:
[...]
$ uname -m -o
x86_64 GNU/Linux
$ cat test.c
#include <stdio.h>

int main()
{
printf("%d\n", sizeof(long));
return 0;
}
$ gcc test.c && ./a.out
8
$ gcc -m32 test.c && ./a.out
4
[...]

That could have failed, since "%d" expects an int argument but you
passed it a size_t.

Oh, my bad. "%zd" it is, then.

No, "%zu", since size_t is an unsigned type.

[...]
OK, that's just a nitpick. The semantic difference between both of them
is that in the first case, the compiler doesn't complain if the caller
of main() passes additional arguments. In both cases the compiler
doesn't even get to see the caller, the only one who does that is the
linker.

I've argued that a program using "int main()", as opposed to "int
main(void)", has undefined behavior, since "int main()" is not one of
the forms permitted by C99 5.1.2.2.1 (nor is it quite equivalent to
either of them). [snip]

It is equivalent in the sense that the Standard uses the
term. Obviously so, since otherwise every single K&R-era
program that had 'int main(){ ... }' would have undefined
behavior under ANSI/ISO C; surely that point was considered
by the standard committee.
 
K

Keith Thompson

Tim Rentsch said:
I've argued that a program using "int main()", as opposed to "int
main(void)", has undefined behavior, since "int main()" is not one of
the forms permitted by C99 5.1.2.2.1 (nor is it quite equivalent to
either of them). [snip]

It is equivalent in the sense that the Standard uses the
term. Obviously so, since otherwise every single K&R-era
program that had 'int main(){ ... }' would have undefined
behavior under ANSI/ISO C; surely that point was considered
by the standard committee.

I'm uncomfortable with conclusions reached by first assuming that the
standard doesn't break pre-ANSI code, and interpreting the wording based
on that assumption.

I can accept, based on your argument, that "int main()" is *intended* to
be valid. I don't agree that the current wording in the standard
actually *says* that it's valid. The only basis for assuming that
"equivalent" has the meaning you say it does is that Bad Things Happen
if it doesn't.

Someone reading the current ISO C standard with no knowledge of pre-ANSI
C would have no basis to assume that "int main()" is valid.

These two programs differ only in how they define main, and they clearly
are not equivalent; the first violates a constraint, while the second
does not.

int main(void) {
if (0) return main(42);
}

int main() {
if (0) return main(42);
}

I believe this was an oversight by the authors of the standard (one that
isn't corrected in C11, unless they did something after N1570).
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
I've argued that a program using "int main()", as opposed to "int
main(void)", has undefined behavior, since "int main()" is not one of
the forms permitted by C99 5.1.2.2.1 (nor is it quite equivalent to
either of them). [snip]

It is equivalent in the sense that the Standard uses the
term. Obviously so, since otherwise every single K&R-era
program that had 'int main(){ ... }' would have undefined
behavior under ANSI/ISO C; surely that point was considered
by the standard committee.

I'm uncomfortable with conclusions reached by first assuming that the
standard doesn't break pre-ANSI code, and interpreting the wording based
on that assumption.

For me it depends on what the motivation is for forming those
conclusions. For purposes of deciding what "the general public"
ought to think about C, I think it's perfectly okay to use that
kind of reasoning. For purposes of revising and improving wording
in the Standard, I'm more inclined to reason along the lines you
are advocating. But it depends on the circumstances, because those
situations are different in some important ways.
I can accept, based on your argument, that "int main()" is *intended* to
be valid. I don't agree that the current wording in the standard
actually *says* that it's valid. The only basis for assuming that
"equivalent" has the meaning you say it does is that Bad Things Happen
if it doesn't.

Someone reading the current ISO C standard with no knowledge of pre-ANSI
C would have no basis to assume that "int main()" is valid.

These two programs differ only in how they define main, and they clearly
are not equivalent; the first violates a constraint, while the second
does not.

int main(void) {
if (0) return main(42);
}

int main() {
if (0) return main(42);
}

I believe this was an oversight by the authors of the standard (one that
isn't corrected in C11, unless they did something after N1570).

I don't think we really have any significant disagreement. I
believe the intent was that the two forms be interchangeable as
far as invokability goes, and you can accept that. You think the
existing wording need clarifying, and I can go along with that
(and if it were up to me I would simply add a footnote with the
clarification). Beyond that, I don't think it's fruitful to be
concerned about what the Standard "really says", because the
current wording includes an English word which is ambiguous in
its meaning.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top