C
Canonical Latin
Leor Zolman said:I know you asked me not to answer any more of your questions, but I'mCanonical Latin said:...
But I'm still curious as to the rational of having type
pointer-to-array-of-size-N-of-type-T (which is fine) and not having type
array-of-size-N-of-type-T (with some exceptions, which is curious).
So far
the consensus seems to be that while everyone is aware of this no one knows
the rational behind it. I'm sure there must be a compelling reason for this
and once explained it would be obvious![]()
stubborn ;-)
The place where you can't have array-of-size-N is in the special case of a
function parameter. Otherwise they're fine.
In the case of function parameters, if an array got passed by value, that
would be a very expensive operation. Most of the time folks would have to
program around it, by writing an expression that evaluates to a pointer of
some kind and passing /that/. But believe it or not, if arrays got passed
by value, that would actually be the special case...because of the
following:
As I'm fond of saying, arrays are just "smoke and mirrors" anyway; they're
mostly syntactic sugar, and compilers translate array names into pointers
to their first elements (there are a few exceptions, such as when applying
sizeof). That's true even if you don't pass them to a function.
So, given:
int a[10];
a[3] = 5;
that last line actually compiles into something like:
*(&a[0] + 3) = 5;
Therefore, in a function call such as:
func(a);
it makes perfect sense what gets passed is a pointer to the first element
of the array:
func(&a[0]);
and thus there's no information available to the function about the size of
that array.
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Type checking and passing by value are two different issues. Consider:
fun1 (T[]); // pointer-to-type-T
fun2 (T[2]); // array-of-size-2-of-type-T
fun3 (T[3]); // array-of-size-3-of-type-T
fun4 (T**); // pointer-to-pointer-to-type-T
fun5 (T*[2]); // pointer-to-array-of-size-2-of-type-T
fun6 (T*[3]); // pointer-to-array-of-size-3-of-type-T
In none of the cases the whole array is passed by value and this is not the
issue. Suppose that c++ actually did have a legitimate type
array-of-size-N-of-type-T. Then
fun (T x[]); // fun1
fun (T x[2]); // fun2
fun (T x[3]); // fun3
main() {
T a[2];
T b[3];
T c[4];
T *d;
fun(a); // call fun2
fun(b) ; // call fun3
fun(c) ; // call fun1 (see comment at end)
fun(d) ; // call fun1
}
Obviously this doesn't work in c++ because compiler sees
array-of-size-N-of-type-T as pointer-to-type-T in most cases. Enforcing type
checking for arrays has nothing to do with passing the whole array by value.
If you think my description of supposed behavior is too far fetched, or that
arrays are just "smoke and mirror" then consider
void fun (T **x) { cout << "fun1"; }
void fun (T (*x)[2]) { cout << "fun2"; }
void fun (T (*x)[3]) { cout << "fun3"; }
int main(int argc, char *argv[]) {
T (*a)[2];
T (*b)[3];
T (*c)[4];
T **d;
fun(a); // call fun2
fun(b) ; // call fun3
fun((T**)(c)) ; // call fun1 (unsafe in c++)
fun(d) ; // call fun1
}
which compiles and behaves as expected. Note that nothing is passed by
value. What this is saying is that pointer-to-array-of-size-N-of-type-T is a
different type for each value of N. What I am saying is that so far I have
not heard a compelling reason why array-of-size-N-of-type-T should not also
be a different type for each value of N.
Another issue that is closely related to this: There is already a problem in
c++ with type pointer-to-array-of-size-N-of-type-T which I marked as
"unsafe" in my example. Essentially you cannot convert
pointer-to-array-of-size-N-of-type-T to pointer-to-pointer-of-type-T without
using a reinterpret cast. This perhaps is the source of the odd behavior of
reinterpreting array-of-size-N-of-type-T as pointer-to-type-T. Of course,
this whole business would go away (and we get true typed arrays in bargain)
if array-of-size-N-of-type-T is automatically converted to pointer-to-type-T
only if there is no matching type for the specific value of N.