Topic: C99 Variable length arrays, and generalization thereof
Author: giecrilj@stegny.2a.pl ("Kristof Zelechovski")
Date: Mon, 20 Nov 2006 06:22:51 GMT Raw View
Uzytkownik "John Nagle" <nagle@animats.com> napisal w wiadomosci
news:Gio4h.8564$B31.1605@newssvr27.news.prodigy.net...
> ISO/IEC 9899 (the C99 standard) has "variable length arrays" for
> on-stack allocation:
> for backwards compatibility. Many library functions take
> an array and a size, but the array first. We could now
> declare the standard function "write" as
Standard, perhaps, but not this standard.
>
> int write(int fd, char buf[n], size_t n);
>
> which captures the size information.
>
> One small step towards eliminating buffer overflows.
>
> Comments?
>
In general, there are several types of parameters passed by pointers or
references:
[stable] [constant] [optional] [output] input parameter
[optional] output parameter
unused parameter
We can have two types of constant parameters: material constant and stable
constant.
A material constant is a parameter that remains constant while the function
is executing.
It can reside in read-only memory.
A stable constant is a parameter that remains unchanged after the function
returns.
It is a special case of an output input parameter.
In general, it cannot reside in read-only memory.
An input parameter that is not stable means
that its contents may be destroyed or modified by the function in an
unspecified way.
It is an input parameter without an additional qualification.
An example is CreateProcessW of Win32 API.
When we consider arrays, we have a broad range of possibilities
because each cell can have an independent qualification.
For example,
we can declare that 100 cells must be accessible for reading, of which 50
cells must be accessible for writing,
an initial segment of them are filled with data when the function returns,
whereas what happens to the rest is unspecified, and the length of valid
data is returned.
You need a special language to express such attributes and make the compiler
reason about them.
And how would you describe the parameter type
char ***x;
where consecutive cells from **x to *x[01] are valid
and each cell (*x)[i] within range contains a pointer to a zero-terminated
string?
It is not enough to say
int foo(n, char[n]).
And I did not take the influence of exceptions into account!
Chris
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: rmabee@comcast.net (Robert Mabee)
Date: Fri, 10 Nov 2006 18:35:50 GMT Raw View
Joe Van Dyk wrote:
> On Wed, 08 Nov 2006 22:37:34 -0600, Robert Mabee wrote:
>>John Nagle wrote:
>>>We could now
>>>declare the standard function "write" as
>>> int write(int fd, char buf[n], size_t n);
>>>One small step towards eliminating buffer overflows.
>>At the expense of the cases where either pointer or length is computed
>>for a partial bufferload, or maybe with new rules for promoting char[m]
>>to char[n] iff n <= m, and char[m]+i to char[n] iff i+n <= m.
> I'm confused by what you mean by the above sentence.
C write is commonly used with a portion of an array, such as when a
preceding read didn't fill the entire array. In that case the actual
parameters won't match the suggested new requirement. Perhaps it
could be salvaged by promotion rules that would let the compiler see
an array subset as an array.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Fri, 10 Nov 2006 13:28:18 CST Raw View
Robert Mabee wrote:
> Joe Van Dyk wrote:
> > On Wed, 08 Nov 2006 22:37:34 -0600, Robert Mabee wrote:
> >>John Nagle wrote:
> >>>We could now
> >>>declare the standard function "write" as
> >>> int write(int fd, char buf[n], size_t n);
> >>>One small step towards eliminating buffer overflows.
> >>At the expense of the cases where either pointer or length is computed
> >>for a partial bufferload, or maybe with new rules for promoting char[m]
> >>to char[n] iff n <= m, and char[m]+i to char[n] iff i+n <= m.
> > I'm confused by what you mean by the above sentence.
>
> C write is commonly used with a portion of an array, such as when a
> preceding read didn't fill the entire array. In that case the actual
> parameters won't match the suggested new requirement.
What suggested new requirement would they violate? John Nagle didn't
specify any requirements, merely cross-referencing the C99 standard,
with modifications to allow the parameter that determines the length of
a VLA parameter to be declared after the VLA parameter itself. The
simplest way to do that would be to declare that the scope of parameter
names begins with the '(' that starts the argument list, rather than
starting at the end of the declarator. With such a modification, and
assuming the above declaration for write(), C99 has no requirements
that would be violated by calling write() with the arguments you
describe.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: rmabee@comcast.net (Robert Mabee)
Date: Sat, 11 Nov 2006 05:03:25 GMT Raw View
kuyper@wizard.net wrote:
> Robert Mabee wrote:
>>C write is commonly used with a portion of an array, such as when a
>>preceding read didn't fill the entire array. In that case the actual
>>parameters won't match the suggested new requirement.
>
> What suggested new requirement would they violate?
The suggestion that this helps defeat buffer overruns implies that
something is checking the new information. write() reliably respects
its length, so the bug to be detected must be that the caller is
passing a length inconsistent with whatever else may be known, in the
caller, about the char array. My only point is that the type system
alone can't check this, for many reasons including that the actual
buffer region to be written isn't of the exact type of the char array
declared somwhere in the caller (ie length can be different).
Please note, I have nothing against the VLA proposal. I am only
quibbling about an add-on (buffer overrun detection) that must either
break existing code or be too weak to be worth anything.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Mon, 13 Nov 2006 10:58:23 CST Raw View
Robert Mabee wrote:
> kuyper@wizard.net wrote:
.
> > What suggested new requirement would they violate?
>
> The suggestion that this helps defeat buffer overruns implies that
> something is checking the new information. write() reliably respects
> its length, so the bug to be detected must be that the caller is
> passing a length inconsistent with whatever else may be known, in the
> caller, about the char array. My only point is that the type system
> alone can't check this, for many reasons including that the actual
> buffer region to be written isn't of the exact type of the char array
> declared somwhere in the caller (ie length can be different).
Ah! That's the confusion. That would require borrowing an addifional
C99 feature:
int write(int fd, char buf[static n], size_t n);
C99 6.7.5.3p7: "... If the keyword static also appears within the [ and
] of the array type derivation, then for each call to the function, the
value of the corresponding actual argument shall provide access to the
first element of an array with at least as many elements as specified
by the size expression."
The "first element" requirement would indeed restrict the usuability of
write(), for precisely the reasons you suggest, and would therefore
probably be a bad idea.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Mon, 13 Nov 2006 18:54:04 GMT Raw View
kuyper@wizard.net wrote:
> Robert Mabee wrote:
>
>>kuyper@wizard.net wrote:
> Ah! That's the confusion. That would require borrowing an addifional
> C99 feature:
>
> int write(int fd, char buf[static n], size_t n);
>
> C99 6.7.5.3p7: "... If the keyword static also appears within the [ and
> ] of the array type derivation, then for each call to the function, the
> value of the corresponding actual argument shall provide access to the
> first element of an array with at least as many elements as specified
> by the size expression."
>
> The "first element" requirement would indeed restrict the usuability of
> write(), for precisely the reasons you suggest, and would therefore
> probably be a bad idea.
OK. Agreed that we can't redefine "write". But those C99 features
should be brought forward into C++. It's convenient to be able to
compile C code with C++ compilers, for mixed applications.
The C99 people are slowly breaking away from the "array equals pointer"
mindset, difficult though that is. That's a good thing.
C has brought us three decades of buffer overflows, and C++
didn't fix the problem, although it helped. Anything that can be
done to fix that problem should be done. This is far more
important that extended template features that few will ever use.
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Robert Mabee <rmabee@comcast.net>
Date: Mon, 13 Nov 2006 14:15:59 CST Raw View
John Nagle wrote:
> kuyper@wizard.net wrote:
>> int write(int fd, char buf[static n], size_t n);
>>
>> C99 6.7.5.3p7: "... If the keyword static also appears within the [ and
>> ] of the array type derivation, then for each call to the function, the
>> value of the corresponding actual argument shall provide access to the
>> first element of an array with at least as many elements as specified
>> by the size expression."
>
> The C99 people are slowly breaking away from the "array equals pointer"
> mindset, difficult though that is. That's a good thing.
>
> C has brought us three decades of buffer overflows, and C++
> didn't fix the problem, although it helped. Anything that can be
> done to fix that problem should be done. This is far more
> important that extended template features that few will ever use.
I strongly agree. But can it be done incrementally? Or would it
be better to make a clean break (to a new array type or to a new
language)? And are we implicitly accepting run-time bounds checking
for cases where the compiler can't prove correctness? Special debug
modes won't help find the overflows that happen only when the deployed
(non-debug-mode) system is deliberately attacked.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Tue, 14 Nov 2006 00:09:11 CST Raw View
Robert Mabee wrote:
> John Nagle wrote:
>
>> kuyper@wizard.net wrote:
>>
>>> int write(int fd, char buf[static n], size_t n);
>>>
>>> C99 6.7.5.3p7: "... If the keyword static also appears within the [ and
>>> ] of the array type derivation, then for each call to the function, the
>>> value of the corresponding actual argument shall provide access to the
>>> first element of an array with at least as many elements as specified
>>> by the size expression."
>>
>>
>> The C99 people are slowly breaking away from the "array equals
>> pointer"
>> mindset, difficult though that is. That's a good thing.
>>
>> C has brought us three decades of buffer overflows, and C++
>> didn't fix the problem, although it helped. Anything that can be
>> done to fix that problem should be done. This is far more
>> important that extended template features that few will ever use.
>
>
> I strongly agree. But can it be done incrementally? Or would it
> be better to make a clean break (to a new array type or to a new
> language)? And are we implicitly accepting run-time bounds checking
> for cases where the compiler can't prove correctness? Special debug
> modes won't help find the overflows that happen only when the deployed
> (non-debug-mode) system is deliberately attacked.
The implementation has the right to check subscripts. (See
the "out of bounds nonsense" discussion for that issue.)
It's tough to add this incrementally, but if we can add
features which can be used in new code, or which can be
retrofitted to old code, which allow subscript checking, that's
a step forward.
As I point out occasionally, good compiler-based subscript
checking is actually quite cheap, because it can often be hoisted out
of loops and checked once. Often, even the top-of-loop check can
be eliminated as always true.
Clearly, the C99 people are trying.
The objection of being unable to talk about a partial buffer
is really a notation problem - C and C++ have no way to talk
about an array slice. Today, we have to say
int write(int fd, char* tab, size_t len); // from library
...
char tab[100];
...
write(outfile, &tab[25],75); // write last part of array
We don't have any way to talk about the second half of the array
without using the "array=pointer" idiom.
Assuming the C99 extensions as a starting point, we need,
in addition, an array slice notation. Something like this:
int write(int fd, char tab[len], size_t len); // from library
...
char tab[100];
...
write(outfile, tab[25:75], 75); // write last part of array - new syntax
The proposed "slice" syntax is familar to Perl and Python programmers.
This doesn't mean that there's a run time array descriptor mechanism.
It just provides a way for the user to actually say to the
language what they're really trying to do.
The effect is that, when the compiler compiles the
call, it checks
char tab[len], size_t len
against
tab[25:75], 75
which, in this case, can be evaluated at compile time to "true".
So there's no new overhead.
This is backwards-compatible. Old style declarations don't
force the check. New-style array parameters in function
declarations do force the check.
For backwards compatibility, if you convert to a plain pointer:
char* p = tab[25:75];
you get the same thing as "&tab[25]" and the size information
is lost. So you can pass new style array slices to old style
parameters, but not the reverse. This eases conversions.
Here's another nice case. Consider one of the classic
buffer overflow trouble spots, "strcpy". If we define
int strcpy(char dst[len], char src[len], size_t len);
then
char s1[100];
char s2[200]
strcpy(s1,s2,100); // no problem
strcpy(s1,s2,200); // error detectable at call time.
strcpy(s1,s2[50:50],100); // copying a slice
strcpy(s1,&s2[50],100); // Compile time error given new declaration above
This starts to look useful. The C99 people have
already gone most of the way. One more step and we can start
preventing buffer overflows.
One could then have an #ifdef which turned on the
new, safer library definitions, recompile existing programs, find
what won't compile, then change the trouble spots to slice
syntax. The cases that don't resolve at compile time then get
a run-time check. No more buffer overflows on those functions.
Comments?
John Nagle
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: rmabee@comcast.net (Robert Mabee)
Date: Wed, 15 Nov 2006 06:36:19 GMT Raw View
John Nagle wrote:
>> John Nagle wrote:
>>> The C99 people are slowly breaking away from the "array equals
>>> pointer"
>>> mindset, difficult though that is. That's a good thing.
> We don't have any way to talk about the second half of the array
> without using the "array=pointer" idiom.
>
> Assuming the C99 extensions as a starting point, we need,
> in addition, an array slice notation. Something like this:
>
> char tab[100];
> write(outfile, tab[25:75], 75); // write last part of array - new syntax
>
> This is backwards-compatible. Old style declarations don't
> force the check. New-style array parameters in function
> declarations do force the check.
>
> For backwards compatibility, if you convert to a plain pointer:
>
> char* p = tab[25:75];
>
> you get the same thing as "&tab[25]" and the size information
> is lost. So you can pass new style array slices to old style
> parameters, but not the reverse. This eases conversions.
Will we someday regret the "slice is a pointer" mindset resulting
from free conversion? Perhaps write should be overloaded for second
arg of new-style array type, and an explicit conversion to pointer
can be done in this version of write.
For a function less respectful of its length arg than write, the
wrapper could convert pointer/length to the static-length array so
the work is done in a context where bounds checking can be implemented
by the compiler.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Wed, 15 Nov 2006 19:39:59 GMT Raw View
Robert Mabee wrote:
> John Nagle wrote:
>
>>> John Nagle wrote:
>>>
>>>> The C99 people are slowly breaking away from the "array equals
>>>> pointer"
>>>> mindset, difficult though that is. That's a good thing.
>>
>> We don't have any way to talk about the second half of the array
>> without using the "array=pointer" idiom.
>>
>> Assuming the C99 extensions as a starting point, we need,
>> in addition, an array slice notation. Something like this:
>>
>> char tab[100];
>> write(outfile, tab[25:75], 75); // write last part of array - new
>> syntax
>>
>> This is backwards-compatible. Old style declarations don't
>> force the check. New-style array parameters in function
>> declarations do force the check.
>>
>> For backwards compatibility, if you convert to a plain pointer:
>>
>> char* p = tab[25:75];
>>
>> you get the same thing as "&tab[25]" and the size information
>> is lost. So you can pass new style array slices to old style
>> parameters, but not the reverse. This eases conversions.
>
>
> Will we someday regret the "slice is a pointer" mindset resulting
> from free conversion? Perhaps write should be overloaded for second
> arg of new-style array type, and an explicit conversion to pointer
> can be done in this version of write.
I tend to agree, but there's so much legacy code out there...
I've previously suggested a "strict mode" for C++, where many
of the unsafe legacy features are disabled. But it's not a popular
idea.
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Wed, 8 Nov 2006 18:06:46 CST Raw View
John Nagle ha scritto:
> ISO/IEC 9899 (the C99 standard) has "variable length arrays" for
> on-stack allocation:
>
> size_t sum(int sz)
> {
> float arr[sz]; // VLA, dynamically allocated
> while (sz-- > 0)
> arr[sz] = sz;
> return sizeof(arr); // Evaluated at runtime
> }
>
> C++ should, for compatibility, have this as well, and I believe
> this is in the current draft.
There's no such thing in the current draft. I have read the minutes of
the Portland meeting and I could not find any hint that this feature is
even being considered. In fact, I disagree that C++ should support such
feature. Compatibility with C is a very weak argument in this particular
case, IMHO, because the C type system is completely different from C++.
> For C++, I'd suggest going slightly further. I'd suggest allowing
> variable length arrays as function parameters:
>
> float sum(size_t n, char tab[n]);
>
> This is useful for subscript checking, of course. But
> that's not all.
Is that really different from:
float sum(size_t n, char tab[]);
? I don't think so.
> One small step towards eliminating buffer overflows.
I don't see how it could really help.
> Comments?
I'm not in the committee, but after reading the minutes it seems that
they already have a lot of (much) more important work to do.
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Robert Mabee <rmabee@comcast.net>
Date: Wed, 8 Nov 2006 22:37:34 CST Raw View
John Nagle wrote:
> We could now
> declare the standard function "write" as
>
> int write(int fd, char buf[n], size_t n);
>
> which captures the size information.
>
> One small step towards eliminating buffer overflows.
At the expense of the cases where either pointer or length is computed
for a partial bufferload, or maybe with new rules for promoting char[m]
to char[n] iff n <= m, and char[m]+i to char[n] iff i+n <= m.
The C interface is unchangeable, and I think you can already do what
you want for C++ with a templated wrapper.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Wed, 8 Nov 2006 23:27:12 CST Raw View
Alberto Ganesh Barbati wrote:
> John Nagle ha scritto:
.
> > For C++, I'd suggest going slightly further. I'd suggest allowing
> > variable length arrays as function parameters:
> >
> > float sum(size_t n, char tab[n]);
> >
> > This is useful for subscript checking, of course. But
> > that's not all.
>
> Is that really different from:
>
> float sum(size_t n, char tab[]);
>
> ? I don't think so.
In C99, they're identical; that's not really a VLA argument. This is:
void matrix_add(int l, int m, int n, double left[l][m], double
right[m][n], product[l][n]);
which is equivalent to:
void matrix_add(int l, int m, int n, double left[][m], double
right[][n], product[][n]);
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Thu, 9 Nov 2006 11:16:44 CST Raw View
kuyper@wizard.net wrote:
> Alberto Ganesh Barbati wrote:
> > John Nagle ha scritto:
> .
> > > For C++, I'd suggest going slightly further. I'd suggest allowing
> > > variable length arrays as function parameters:
> > >
> > > float sum(size_t n, char tab[n]);
> > >
> > > This is useful for subscript checking, of course. But
> > > that's not all.
> > Is that really different from:
> >
> > float sum(size_t n, char tab[]);
> >
> > ? I don't think so.
>
> In C99, they're identical; that's not really a VLA argument. This is:
>
> void matrix_add(int l, int m, int n, double left[l][m], double
> right[m][n], product[l][n]);
>
> which is equivalent to:
>
> void matrix_add(int l, int m, int n, double left[][m], double
> right[][n], product[][n]);
That should, of couse, have been matrix_mul(), not matrix_add(), though
that's not directly relevant to what I was saying.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: joe.vandyk@boeing.com (Joe Van Dyk)
Date: Fri, 10 Nov 2006 07:14:17 GMT Raw View
On Wed, 08 Nov 2006 22:37:34 -0600, Robert Mabee wrote:
> John Nagle wrote:
>> We could now
>> declare the standard function "write" as
>>
>> int write(int fd, char buf[n], size_t n);
>>
>> which captures the size information.
>>
>> One small step towards eliminating buffer overflows.
>
> At the expense of the cases where either pointer or length is computed
> for a partial bufferload, or maybe with new rules for promoting char[m]
> to char[n] iff n <= m, and char[m]+i to char[n] iff i+n <= m.
I'm confused by what you mean by the above sentence. Could you please
clarify it? Or give an example?
Thanks,
Joe
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Fri, 10 Nov 2006 07:17:12 GMT Raw View
kuyper@wizard.net wrote:
> kuyper@wizard.net wrote:
>
>>Alberto Ganesh Barbati wrote:
>>
>>>John Nagle ha scritto:
>>
>>.
>>
>>>>For C++, I'd suggest going slightly further. I'd suggest allowing
>>>>variable length arrays as function parameters:
>>>>
>>>> float sum(size_t n, char tab[n]);
>>>>
>>>>This is useful for subscript checking, of course. But
>>>>that's not all.
>>>
>>>Is that really different from:
>>>
>>> float sum(size_t n, char tab[]);
>>>
>>>? I don't think so.
>>
>>In C99, they're identical; that's not really a VLA argument.
In C99, "sizeof" works on variable-length arrays, and it's
not a compile-time constant result. Does that work for
the parameter case?
What I'm working towards, of course, is a way to express
array sizes such that subscript checking implementations
are possible. There are still too many buffer overflows
in the world.
Incidentally, did "lengthof" ever go into the standard?
It's an extension in both Microsoft and GCC implementations,
so it's a de-facto standard. Why not put it in for real?
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Fri, 10 Nov 2006 11:15:11 CST Raw View
John Nagle wrote:
> kuyper@wizard.net wrote:
> > kuyper@wizard.net wrote:
> >>Alberto Ganesh Barbati wrote:
> >>>John Nagle ha scritto:
.
> >>>>For C++, I'd suggest going slightly further. I'd suggest allowing
> >>>>variable length arrays as function parameters:
> >>>>
> >>>> float sum(size_t n, char tab[n]);
> >>>>
> >>>>This is useful for subscript checking, of course. But
> >>>>that's not all.
> >>>
> >>>Is that really different from:
> >>>
> >>> float sum(size_t n, char tab[]);
> >>>
> >>>? I don't think so.
> >>
> >>In C99, they're identical; that's not really a VLA argument.
>
> In C99, "sizeof" works on variable-length arrays, and it's
> not a compile-time constant result. Does that work for
> the parameter case?
Yes. However, as I said, "tab" is not a VLA parameter - it's type is
"pointer to char", just as it was in C90. They had to retain that rule,
if only for backwards compatibility. Here's an example that does have a
VLA parameter:
double determinant(int n, double array[n][n])
{
...
}
Inside the function block, sizeof(array) == sizeof(double(*)[n]), and
sizeof(*array)==sizeof(double[n]).
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Wed, 8 Nov 2006 17:29:56 GMT Raw View
ISO/IEC 9899 (the C99 standard) has "variable length arrays" for
on-stack allocation:
size_t sum(int sz)
{
float arr[sz]; // VLA, dynamically allocated
while (sz-- > 0)
arr[sz] = sz;
return sizeof(arr); // Evaluated at runtime
}
C++ should, for compatibility, have this as well, and I believe
this is in the current draft.
For C++, I'd suggest going slightly further. I'd suggest allowing
variable length arrays as function parameters:
float sum(size_t n, char tab[n]);
This is useful for subscript checking, of course. But
that's not all.
We could go one step further, by defining ".begin()", ".end()",
and ".size()" for any built-in array for which "sizeof" is
meaningful. We could also provide "T::iterator"
for arrays of built-in types. This allows using C++ style
iteration on built-in arrays, and allows some useful generic
templates on built-in arrays. That may or may not be
worth the trouble. Comments?
Incidentally, it's time to add "lengthof()" to the language,
to obtain the length of an array, if it's not there already.
It's already in Microsoft's Visual C++ ".NET" and in the GCC
library, so it's a de-facto standard. With variable
length arrays, it's more useful; it's what you use
to get array bounds. The usual idiom will be
for (int i=0; i < lengthof(tab); i++)
{ ... }
which is easy to understand and easy to get right.
One last thing. If we allow
float sum(size_t n, char tab[n]);
we should also allow
float sum(char tab[n], size_t n);
even though the use of n precedes its declaration. This is
for backwards compatibility. Many library functions take
an array and a size, but the array first. We could now
declare the standard function "write" as
int write(int fd, char buf[n], size_t n);
which captures the size information.
One small step towards eliminating buffer overflows.
Comments?
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Wed, 8 Nov 2006 13:40:06 CST Raw View
John Nagle wrote:
> ISO/IEC 9899 (the C99 standard) has "variable length arrays" for
> on-stack allocation:
>
> size_t sum(int sz)
> {
> float arr[sz]; // VLA, dynamically allocated
> while (sz-- > 0)
> arr[sz] = sz;
> return sizeof(arr); // Evaluated at runtime
> }
>
> C++ should, for compatibility, have this as well, and I believe
> this is in the current draft.
>
> For C++, I'd suggest going slightly further. I'd suggest allowing
> variable length arrays as function parameters:
>
> float sum(size_t n, char tab[n]);
C99 supports this feature, so I think if C++ is going to borrow the
other uses of VLAs from C99, it should borrow this one, too.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Andrei Polushin" <polushin@gmail.com>
Date: Wed, 8 Nov 2006 14:59:59 CST Raw View
John Nagle wrote:
> We could go one step further, by defining ".begin()", ".end()",
> and ".size()" for any built-in array for which "sizeof" is
> meaningful. We could also provide "T::iterator"
> for arrays of built-in types. This allows using C++ style
> iteration on built-in arrays, and allows some useful generic
> templates on built-in arrays. That may or may not be
> worth the trouble. Comments?
We may get it with the concepts proposal:
auto concept Measurable<class T> {
size_t T::size(T) const;
};
concept_map Measurable<char[32]> {
size_t T::size(T) const { return 32; }
};
"auto concept" is applied automatically, and suitable for use in
generic code.
--
Andrei Polushin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]