RTX-2000 processor PC/AT add-in card (any takers?)
Sean Conner
spc at conman.org
Mon Apr 10 22:02:57 CDT 2017
It was thus said that the Great Sean Conner via cctalk once stated:
> It was thus said that the Great Jecel Assumpcao Jr. via cctalk once stated:
>
> > You can declare
> > new variables inside { ... } and they will shadow variables with the
> > same name declared outside of these brackets but this has no effect on
> > the runtime structures.
> >
> > Pascal, on the other hand, allows proceedures to be declared inside
> > other proceedures and these nested scopes can access stuff declared in
> > the more external scopes.
>
> Yes. You cannot do this in C because unlike Pascal (and I support others
> in the Algol family), C allows you to pass functions to other functions via
> function pointers. Pascal does not allow this [1], because of exactly this
> reason---external scopes. [2] It becomes more difficult to support. Not
> impossible, just real ugly (and most likely a special case).
Actually, I want to expand upon this a bit. Given the following
hypothetical C code:
int do_the_sort(foobar *foo,size_t nfoo,int sort_criteria[])
{
qsort(
foo,
nfoo,
sizeof(foobar),
int (const foobar *l,const foobar *r)
{
if (sort_criteria[l->type] < sort_criteria[r->type])
return -1;
else if (sort_criteria[l->type] > sort_criteria[r->type])
return 1;
return strcmp(l->name,r->name);
}
);
/* ... rest of code
}
The anonymous sorting function accesses data in an outer lexical scope,
but the issue here is there's an undetermined number of intermediate stack
frames between do_the_sort() and the anonymous sort function. A way around
this issue (and it's not limited to this pseudo-C but any function that
allows nested functions like this) is to have "fat function pointers" that
include two pointers---one to the current lexical scope and one to the
actual function, so it would probably look like this in an actual
implementation:
qsort(
foo,
nfoo,
sizeof(foobar),
ADDRESS_OF_STACK_FRAME(do_the_sort),
int (STACKFRAME *p,const foobar *l,const foobar *r)
{
if (p->sort_criteria[l->type] < p->sort_criteria[r->type])
...
}
);
(plus some magic in calling the anonymous function from qsort(), like
setting the stack frame register (EBP on x86, A6 by convention on the 68000,
U on the 6809, R12 on the VAX) to the passed in stack frame prior to calling
the function so it just works like any other nested function)
The harder issue is the following:
void set_signal_handlers(int signum,int what_to_do)
{
void handler(int sig)
{
if (what_to_do == EXIT)
_exit(1);
if (what_to_do == LOG)
syslog(LOG_DEBUG,"signal %d happened",sig);
}
signal(signum,handler);
}
signal() doesn't actually call the locally scoped function---it just does
some system magic to have handler() called when SIGINT or SIGTERM is raised.
Unlike the anonymous function in do_the_sort(), where it's called during the
execution of qsort so the frame for do_the_sort() still exists, here, the
frame for seg_signal_handlers() is long gone by the time the local function
handler() is called. And this is a *much harder* problem to solve.
I really think it's for *this* reason (the handler() example) that C
doesn't allow nested functions.
-spc (Misses anonymous and nested functions in C, but has learned to work
around it)
More information about the cctalk
mailing list