On Sat, Sep 1, 2012 at 8:35 PM, John Nagle <na...@animats.com> wrote: > On 9/1/2012 9:59 AM, James Dennett wrote: >> On Fri, Aug 31, 2012 at 2:55 PM, John Nagle <na...@animats.com> >> wrote: >>> We have proposed an extension to C (primarily) and C++ (possibly) >>> to address buffer overflow prevention. Buffer overflows are still >>> a huge practical problem in C, and much important code is still >>> written in C. This is a new approach that may actually work. > ... >> Could you say a little more of why it appears necessary to introduce >> references into C for this? The reason I'm puzzled is that C already >> has the ability to pass arrays in a way that preserves their size >> (just pass the address of the array) -- what is it that references >> change in this picture that justifies such a radical change? Could >> we just permit pointer-to-array-of-n elements to convert to >> pointer-to-array-of-(n-1) elements, and/or provide some way to slice >> explicitly? > > That's an important point. C99 already has variable-length > array parameters: > > int fn(size_t n, float vec[n]); > > Unfortunately, when the parameter is received in the function body, > per N1570 ยง6.7.6.3p7: 'A declaration of a parameter as "array of _type_" > shall be adjusted to "qualified pointer to _type_", where the type > qualifiers (if any) are those specified within the [ and ] of > the array type derivation.' > > What this means is that, in the body of the function, > "vec" has type "float *", and "sizeof vec" is the size of > a pointer. The standard currently requires losing the size > of the array. > > While C99 variable-length array parameters aren't used much > (searches of open-source code have failed to find any use > cases, Microsoft refuses to implement them, and N1570 makes > them optional), these semantics also apply to passing > fixed-length arrays: > > int fn(float vec[4]); > > As before, "vec" is delivered as "float* vec". The constant > case is widely used, and changing the semantics there might silently > break existing code that uses "sizeof". We had a go-round on > this on comp.std.c, and the conclusion was that changing the > semantics of C array passing would break too much. > > The real reason for using references is that size information > is needed in other places than parameters. It's needed in > return types, on the left side of assignments, in casts, and > in structures. References to arrays have associated information; > pointers don't.
That's my point/question: pointers to arrays have exactly the same information associated with them as references to arrays, and exist in C today (and have existed in C for decades, they're just not used in conventional idioms). You seem to be asserting something about pointers that is not true. Granted, the pointer-to-first-element that an array implicitly decays to in most contexts loses that information, but that is not a pointer to the array (though for multi-dimensional arrays, i.e., arrays of arrays, it is a pointer to a subarray and its type information records the size of that subarray). A concrete example: Given the declaration void fn(int (*pointer_to_array)[5]); inside fn, pointer_to_array has type pointer to array of 5 ints, and sizeof(*pointer_to_array) is 5*sizeof(int). Callers can't pass in an array of the wrong size without a cast. Unfortunately right now they can't even pass in a _larger_ array without a cast, though I think that would be relatively minor surgery to the languages (C and C++). A call to fn looks like fn(&array), e.g., int main(void) { int array[5]; fn(&array); } Moving to references instead of pointers seems to give little except avoiding the need to write "&", which C programmers are already comfortable with. Maybe what you need is an extension of VLA-like syntax to something more like void fn(int (*pointer_to_array)[n], size_t n) though while C has gone down the path of allowing sizeof(variable) to vary at compile time, C++ has not and would, I expect, be likely to resist such a change. -- James