Variable-length array parameters in NCEG C
Robert Jervis
uunet!bjervis!rbj
Tue Jul 7 13:21:58 PDT 1992
I have to start out by saying that I have a personal preference for
Dennis Ritchie's proposal. It's primary drawback, from my perspective,
is that it means calling function and passing multidimensional arrays will
look very different in C and FORTRAN. Otherwise, I like the cleanliness
of the solution (since it is built around the notion of pointers to variable
length arrays that are sized at runtime).
Dennis has even pointed out that FORTRAN-style function calls could be
used, for example:
func(float a[?][?]); /* not fortran-like */
fortfunc(float a[], int i, int j); /* fortran-like */
float x[10][20];
func(x);
fortfunc(x, 10, 20);
}
func(float a[?][?])
{
a[n][m] = ...;
}
fortfunc(float arg_a[], int i, int j)
{
float (*a)[?] = (float [i][j])arg_a;
a[n][m] = ...;
}
For some reason, this proposal has not gotten much support. Most of the
attention has been focused on the various FORTRAN-like proposals. There
have been three essentially different approaches, each flawed in one way
or another:
- Use different scope rules for prototype arguments than anywhere
else in C. These are the permuted order rules and other such
proposals that try to allow flexible argument ordering (to match
FORTRAN) without extra syntax. This is legitimately criticized
for mugging the C scope rules. A language with general scope rules
that work for this situation would be implementable (it would involve
relaxing the ordering requirements of all declarations), but it
wouldn't be C.
- Use some variation of old-style definition syntax. This works for
definitions, but we would like prototypes to use the same syntax.
It could still work, but it isn't very clean, and there are really
nasty problems is you try to declare a function which accepts a
function pointer argument. What if both those functions need
variable array arguments?
- Use some variation of forward declarations inside the prototype.
Either the array bounds variables are listed first, or else a
tentative declaration of the array. I prefer the tentative decl
of the array, since it puts the arguments in their real order
first (and thereby mimics the ordering found in old-style
definitions). This approach involves significant new syntax, but
does work.
Of these approaches, the last is the most defensible one. Changing the
scope rules really undermines the uniformity of the language in a surprising
way. Resurrecting old-style definition syntax in whole or in part runs
counter to the fact that standard C deprecates old-style syntax in general.
We wanted prototypes to be the future of C, so it is with prototypes that
we should solve this problem.
If forward declarations are thought to be the right solution (see my
opening comments for my real feelings in this matter), then something like
the following would be my preference:
func(float a[?][?], int i, int j;
float a[i][j]);
This puts the arguments in their real call order first, which is the most
important information. The detailed declaration of the array follows. This
is consistent with the general rule in C that incomplete types can be
mentioned in an early declaration and then completed by a later one. It is
also consistent with the FORTRAN ordering of declarations, in which the
arguments are listed first and their declarations follow. This same point
holds for old-style C syntax (a weak argument given the obsolete status of
old-style syntax).
This debate has been circulating for several years now. It shows little sign
of converging on a single solution. The only real forward progress that
seems to have been made is to settle on a few requirements of any solution:
- Variable arrays should be declarable in prototypes as well as
definitions, so we can have our compilers check the actual
calls.
- Sizeof is a runtime computation for these arrays.
- Automatic variable dimensioned arrays are needed. The battle
has been waged on more than just the function call front.
- An ability to machine-translate between FORTRAN and C is
desirable, and this means minimal changes to interfaces.
- Pointers to variable dimensioned arrays are needed.
- Structures with variable dimensioned arrays are NOT needed.
I think that one of the issues that has worked against the Ritchie
proposal (despite the fact that it covers all of these points now) is
the fact the Ritchie's variable array pointers is that they include
descriptors at runtime (at least one integer for each variable dimension).
The alternate proposals fix the dimensions statically as part of the
declaration, so descriptors are only needed if the bounds expressions
change during the lifetime of the array. This should tend to make the
storagusage and code generation a little better than with the Ritchie
proposal.
At this point, I don't think very much new light will be shed on the
debate. We are quibbling over syntactic issues for the most part. Sooner
or later we need simply to accept something and move on.
Thanks for indulging my ravings
Bob Jervis
bjervis!rbjauunet.uu.net
More information about the Numeric-interest
mailing list