Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #2883 > unrolled thread
| Started by | Jack Boot <jackboot@mailinator.com> |
|---|---|
| First post | 2011-04-25 19:36 +0000 |
| Last post | 2011-04-25 22:57 -0400 |
| Articles | 20 on this page of 32 — 10 participants |
Back to article view | Back to comp.lang.c
multidimensional heap arrays Jack Boot <jackboot@mailinator.com> - 2011-04-25 19:36 +0000
Re: multidimensional heap arrays Francois Grieu <fgrieu@gmail.com> - 2011-04-25 23:16 +0200
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-25 22:35 +0100
Re: multidimensional heap arrays Anand Hariharan <mailto.anand.hariharan@gmail.com> - 2011-04-25 21:19 -0700
Re: multidimensional heap arrays Francois Grieu <fgrieu@gmail.com> - 2011-04-26 08:19 +0200
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-26 12:19 +0100
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-26 23:25 +1200
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-26 21:06 +0100
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 08:59 +1200
Re: multidimensional heap arrays Keith Thompson <kst-u@mib.org> - 2011-04-26 14:39 -0700
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 10:03 +1200
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-26 23:41 +0100
Re: multidimensional heap arrays Keith Thompson <kst-u@mib.org> - 2011-04-26 16:33 -0700
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-27 04:05 +0100
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-26 22:49 +0100
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 10:19 +1200
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-27 00:38 +0100
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 11:48 +1200
Re: multidimensional heap arrays Keith Thompson <kst-u@mib.org> - 2011-04-26 17:38 -0700
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 13:08 +1200
Re: multidimensional heap arrays Tim Rentsch <txr@alumni.caltech.edu> - 2011-04-26 18:31 -0700
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 14:01 +1200
Re: multidimensional heap arrays Tim Rentsch <txr@alumni.caltech.edu> - 2011-04-27 00:04 -0700
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 19:58 +1200
Re: multidimensional heap arrays Ian Collins <ian-news@hotmail.com> - 2011-04-27 20:03 +1200
Re: multidimensional heap arrays Keith Thompson <kst-u@mib.org> - 2011-04-27 00:03 -0700
Re: multidimensional heap arrays Tim Rentsch <txr@alumni.caltech.edu> - 2011-04-26 18:20 -0700
Re: multidimensional heap arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-04-27 03:59 +0100
Re: multidimensional heap arrays Tim Rentsch <txr@alumni.caltech.edu> - 2011-04-27 00:24 -0700
Re: multidimensional heap arrays "io_x" <a@b.c.invalid> - 2011-04-26 09:42 +0200
Re: multidimensional heap arrays Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-04-25 20:50 -0400
Re: multidimensional heap arrays James Kuyper <jameskuyper@verizon.net> - 2011-04-25 22:57 -0400
Page 1 of 2 [1] 2 Next page →
| From | Jack Boot <jackboot@mailinator.com> |
|---|---|
| Date | 2011-04-25 19:36 +0000 |
| Subject | multidimensional heap arrays |
| Message-ID | <ip4if6$hhk$1@speranza.aioe.org> |
hi we have been discussing methods for multidimensional heap arrays, between us we have 3 preferred approaches 1: array of pointers each mallocated, ie int ** A = malloc(nrow * sizeof(int*)); for(i=0;i<nrow;i++) A[i]=malloc(ncol * sizeof(int)); 2: array of pointers set into one big mallocated array, ie int ** A = malloc(nrow * sizeof(int*)); int * Astorage = malloc(nrow * ncol * sizeof(int)); for(i=0;i<nrow;i++) A[i]=Astorage+i*ncol; 3: one big mallocated array, no separate row pointers but an accessor macro instead, ie int * Astorage = malloc(nrow * ncol * sizeof(int)); #define A(i,j) Astorage[i*ncol+j]; what is your opinion of these methods? what situations is one is better than another? should some of them never be used? what is standard/best practice? cheers JB
[toc] | [next] | [standalone]
| From | Francois Grieu <fgrieu@gmail.com> |
|---|---|
| Date | 2011-04-25 23:16 +0200 |
| Message-ID | <4db5e4b6$0$19111$426a74cc@news.free.fr> |
| In reply to | #2883 |
On 25/04/2011 21:36, Jack Boot wrote: > hi > > we have been discussing methods for multidimensional heap arrays, between > us we have 3 preferred approaches > > 1: array of pointers each mallocated, ie > int ** A = malloc(nrow * sizeof(int*)); > for(i=0;i<nrow;i++) A[i]=malloc(ncol * sizeof(int)); Except for the lack of error checking, this one seems OK to me. Contrary to the other two, it has a chance to work when the heap is fragmented, or there otherwise exists a restriction on the size of allocated object. > 2: array of pointers set into one big mallocated array, ie > int ** A = malloc(nrow * sizeof(int*)); > int * Astorage = malloc(nrow * ncol * sizeof(int)); > for(i=0;i<nrow;i++) A[i]=Astorage+i*ncol; This one could be subject to overflow when computing nrow * ncol; it can be improved: Astorage = malloc(ncol * sizeof(int) * nrow). > 3: one big mallocated array, no separate row pointers but an accessor > macro instead, ie > int * Astorage = malloc(nrow * ncol * sizeof(int)); > #define A(i,j) Astorage[i*ncol+j]; That macro should be #define A(i,j) Astorage[(i)*(size_t(ncol)+(j)] in order to work e.g. when i is an expression, and to avoid the the same overflow problem. And then there is the issue of the scope of Astorage and ncol, and one should #undef A when either becomes out of scope. > What is your opinion of these methods? What situations is one is better > than another? Should some of them never be used? What is standard/best > practice? The first is the most likely to work. It is arguably the most standard and closest to best practice. The third may be noticeably faster - or not. None is best practice, for lack of proper error check. Francois Grieu
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-04-25 22:35 +0100 |
| Message-ID | <0.3b2fcc49ff70b692295a.20110425223547BST.87vcy2dnf0.fsf@bsb.me.uk> |
| In reply to | #2883 |
Jack Boot <jackboot@mailinator.com> writes:
> we have been discussing methods for multidimensional heap arrays, between
> us we have 3 preferred approaches
>
> 1: array of pointers each mallocated, ie
> int ** A = malloc(nrow * sizeof(int*));
> for(i=0;i<nrow;i++) A[i]=malloc(ncol * sizeof(int));
A useful idiom when assigning allocated storage to E = malloc(...) is to
use sizeof *E as the size. By keeping the pattern the same, you can
avoid accidentally using the wrong size. So I'd write:
int **A = malloc(nrow * sizeof *A);
if (A)
for (i = 0; i < nrow; i++)
A[i] = malloc(ncol * sizeof *A[i]);
> 2: array of pointers set into one big mallocated array, ie
> int ** A = malloc(nrow * sizeof(int*));
> int * Astorage = malloc(nrow * ncol * sizeof(int));
> for(i=0;i<nrow;i++) A[i]=Astorage+i*ncol;
>
> 3: one big mallocated array, no separate row pointers but an accessor
> macro instead, ie
> int * Astorage = malloc(nrow * ncol * sizeof(int));
> #define A(i,j) Astorage[i*ncol+j];
You can avoid the macro by allocating (and thus pointing to) an array
type:
int (*A)[ncol] = malloc(nrow * sizeof *A);
The sizeof idiom really pays off here: there is no need to think about
what the right type element type is.
If ncol is not a constant expression, you will need a modern C compiler
for this to work (by which I mean C99). Use them while you can, since
they will no longer be required in the next C standard.
> what is your opinion of these methods? what situations is one is better
> than another? should some of them never be used? what is standard/best
> practice?
Sorry, no idea. It is sometimes possible to pick the "best" if enough is
known about the problem being solved and the constraints on the solution
but I don't think there is a "best" without any such information.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Anand Hariharan <mailto.anand.hariharan@gmail.com> |
|---|---|
| Date | 2011-04-25 21:19 -0700 |
| Message-ID | <509bd6d5-21c0-4150-9aa4-7e68492782f1@v10g2000yqn.googlegroups.com> |
| In reply to | #2886 |
On Apr 25, 4:35 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote: > Jack Boot <jackb...@mailinator.com> writes: (...) > > 3: one big mallocated array, no separate row pointers but an accessor > > macro instead, ie > > int * Astorage = malloc(nrow * ncol * sizeof(int)); > > #define A(i,j) Astorage[i*ncol+j]; > > You can avoid the macro by allocating (and thus pointing to) an array > type: > > int (*A)[ncol] = malloc(nrow * sizeof *A); > > The sizeof idiom really pays off here: there is no need to think about > what the right type element type is. > > If ncol is not a constant expression, you will need a modern C compiler > for this to work (by which I mean C99). Use them while you can, since > they will no longer be required in the next C standard. > Could you please elaborate? Is the next standard getting rid of VLAs or will the 'arr' in the following code be a 'plain and ordinary' array ... const int ncol = 5; int arr[ncol]; ... or did you mean something else entirely? - Anand
[toc] | [prev] | [next] | [standalone]
| From | Francois Grieu <fgrieu@gmail.com> |
|---|---|
| Date | 2011-04-26 08:19 +0200 |
| Message-ID | <4db663d9$0$4789$426a74cc@news.free.fr> |
| In reply to | #2902 |
On 26/04/2011 06:19, Anand Hariharan wrote: > On Apr 25, 4:35 pm, Ben Bacarisse<ben.use...@bsb.me.uk> wrote: >> Jack Boot<jackb...@mailinator.com> writes: > (...) >>> 3: one big mallocated array, no separate row pointers but an accessor >>> macro instead, ie >>> int * Astorage = malloc(nrow * ncol * sizeof(int)); >>> #define A(i,j) Astorage[i*ncol+j]; >> >> You can avoid the macro by allocating (and thus pointing to) an array >> type: >> >> int (*A)[ncol] = malloc(nrow * sizeof *A); >> >> The sizeof idiom really pays off here: there is no need to think about >> what the right type element type is. >> >> If ncol is not a constant expression, you will need a modern C compiler >> for this to work (by which I mean C99). Use them while you can, since >> they will no longer be required in the next C standard. >> > > Could you please elaborate? Is the next standard getting rid of VLAs (..) The next standard is making VLAs optional. Under ISO/IEC 9899:1999 VLAs are mandated (and some compilers have not implemented it). > or will the 'arr' in the following code be a 'plain and ordinary' > array ... > > const int ncol = 5; > int arr[ncol]; I'm genuinely wondering: is ncol a "constant expression" ? Francois Grieu
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-04-26 12:19 +0100 |
| Message-ID | <0.ba05a251a5fe8eed2ac7.20110426121957BST.8739l5dztu.fsf@bsb.me.uk> |
| In reply to | #2903 |
Francois Grieu <fgrieu@gmail.com> writes: > On 26/04/2011 06:19, Anand Hariharan wrote: >> On Apr 25, 4:35 pm, Ben Bacarisse<ben.use...@bsb.me.uk> wrote: >>> Jack Boot<jackb...@mailinator.com> writes: >> (...) >>>> 3: one big mallocated array, no separate row pointers but an accessor >>>> macro instead, ie >>>> int * Astorage = malloc(nrow * ncol * sizeof(int)); >>>> #define A(i,j) Astorage[i*ncol+j]; >>> >>> You can avoid the macro by allocating (and thus pointing to) an array >>> type: >>> >>> int (*A)[ncol] = malloc(nrow * sizeof *A); >>> >>> The sizeof idiom really pays off here: there is no need to think about >>> what the right type element type is. >>> >>> If ncol is not a constant expression, you will need a modern C compiler >>> for this to work (by which I mean C99). Use them while you can, since >>> they will no longer be required in the next C standard. >>> >> >> Could you please elaborate? Is the next standard getting rid of VLAs (..) > > The next standard is making VLAs optional. Under ISO/IEC 9899:1999 VLAs > are mandated (and some compilers have not implemented it). I suppose it is worth saying that this is the current plan though I don't think there is any chance it will be changed. It's very unlikely that any compiler that currently implements VLAs will stop doing so, but it does alter their status as a language feature. I'd hoped that the very useful concurrency in the new C would have acted as a spur to implementers this finally getting C99 widely adopted but, presumably, the committee felt that parts of C99 must be optional to have any change of the new standard getting adopted. >> or will the 'arr' in the following code be a 'plain and ordinary' >> array ... >> >> const int ncol = 5; >> int arr[ncol]; The former. This is a VLA and will remain so in C1x. > I'm genuinely wondering: is ncol a "constant expression" ? It might be in that an implementation can define its own forms of constant expression, but it does not meet the standard's minimum requirements to be an "integer constant expression" (which is what is required to declare a non-VL array). -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-04-26 23:25 +1200 |
| Message-ID | <91noctFq9bU7@mid.individual.net> |
| In reply to | #2919 |
On 04/26/11 11:19 PM, Ben Bacarisse wrote: > Francois Grieu<fgrieu@gmail.com> writes: > >> On 26/04/2011 06:19, Anand Hariharan wrote: > >>> or will the 'arr' in the following code be a 'plain and ordinary' >>> array ... >>> >>> const int ncol = 5; >>> int arr[ncol]; > > The former. This is a VLA and will remain so in C1x. > >> I'm genuinely wondering: is ncol a "constant expression" ? > > It might be in that an implementation can define its own forms of > constant expression, but it does not meet the standard's minimum > requirements to be an "integer constant expression" (which is what is > required to declare a non-VL array). Which is really silly. I do wish they could fix that and bring it in line with C++. But I guess adding VLAs shot that idea in the foot. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-04-26 21:06 +0100 |
| Message-ID | <0.bece330a32ff7f1d21e3.20110426210623BST.87r58odbgg.fsf@bsb.me.uk> |
| In reply to | #2921 |
Ian Collins <ian-news@hotmail.com> writes: > On 04/26/11 11:19 PM, Ben Bacarisse wrote: >> Francois Grieu<fgrieu@gmail.com> writes: >> >>> On 26/04/2011 06:19, Anand Hariharan wrote: >> >>>> or will the 'arr' in the following code be a 'plain and ordinary' >>>> array ... >>>> >>>> const int ncol = 5; >>>> int arr[ncol]; >> >> The former. This is a VLA and will remain so in C1x. >> >>> I'm genuinely wondering: is ncol a "constant expression" ? >> >> It might be in that an implementation can define its own forms of >> constant expression, but it does not meet the standard's minimum >> requirements to be an "integer constant expression" (which is what is >> required to declare a non-VL array). > > Which is really silly. I do wish they could fix that and bring it in > line with C++. But I guess adding VLAs shot that idea in the foot. I too would like to have seen the same constant expression definition between C++ and C but I don't see how C's VLAs got in the way of that. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-04-27 08:59 +1200 |
| Message-ID | <91oq24Fq9bU9@mid.individual.net> |
| In reply to | #2931 |
On 04/27/11 08:06 AM, Ben Bacarisse wrote: > Ian Collins<ian-news@hotmail.com> writes: > >> On 04/26/11 11:19 PM, Ben Bacarisse wrote: >>> Francois Grieu<fgrieu@gmail.com> writes: >>> >>>> On 26/04/2011 06:19, Anand Hariharan wrote: >>> >>>>> or will the 'arr' in the following code be a 'plain and ordinary' >>>>> array ... >>>>> >>>>> const int ncol = 5; >>>>> int arr[ncol]; >>> >>> The former. This is a VLA and will remain so in C1x. >>> >>>> I'm genuinely wondering: is ncol a "constant expression" ? >>> >>> It might be in that an implementation can define its own forms of >>> constant expression, but it does not meet the standard's minimum >>> requirements to be an "integer constant expression" (which is what is >>> required to declare a non-VL array). >> >> Which is really silly. I do wish they could fix that and bring it in >> line with C++. But I guess adding VLAs shot that idea in the foot. > > I too would like to have seen the same constant expression definition > between C++ and C but I don't see how C's VLAs got in the way of that. The code above sums it up, if ncol is an "integer constant expression" is arr an array, or a VLA? Would it be acceptable for a language change to change (all be it subtly) the behaviour of existing code? -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-04-26 14:39 -0700 |
| Message-ID | <lny62wy9ns.fsf@nuthaus.mib.org> |
| In reply to | #2932 |
Ian Collins <ian-news@hotmail.com> writes:
> On 04/27/11 08:06 AM, Ben Bacarisse wrote:
>> Ian Collins<ian-news@hotmail.com> writes:
>>
>>> On 04/26/11 11:19 PM, Ben Bacarisse wrote:
>>>> Francois Grieu<fgrieu@gmail.com> writes:
>>>>
>>>>> On 26/04/2011 06:19, Anand Hariharan wrote:
>>>>
>>>>>> or will the 'arr' in the following code be a 'plain and ordinary'
>>>>>> array ...
>>>>>>
>>>>>> const int ncol = 5;
>>>>>> int arr[ncol];
>>>>
>>>> The former. This is a VLA and will remain so in C1x.
>>>>
>>>>> I'm genuinely wondering: is ncol a "constant expression" ?
>>>>
>>>> It might be in that an implementation can define its own forms of
>>>> constant expression, but it does not meet the standard's minimum
>>>> requirements to be an "integer constant expression" (which is what is
>>>> required to declare a non-VL array).
>>>
>>> Which is really silly. I do wish they could fix that and bring it in
>>> line with C++. But I guess adding VLAs shot that idea in the foot.
>>
>> I too would like to have seen the same constant expression definition
>> between C++ and C but I don't see how C's VLAs got in the way of that.
>
> The code above sums it up, if ncol is an "integer constant expression"
> is arr an array, or a VLA?
>
> Would it be acceptable for a language change to change (all be it
> subtly) the behaviour of existing code?
What behavior would change?
Currently, arr is a VLA. If the rules were changed to make ncol a
constant expression, as it is in C++, arr would be an ordinary array
object, not a VLA. As far as I can tell, this would merely make some
things legal and well-defined that are currently either constraint
violations or undefined behavior. I can't think of any cases were valid
code would either become invalid or change its (currently defined)
behavior. Can you?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-04-27 10:03 +1200 |
| Message-ID | <91otpcFq9bU11@mid.individual.net> |
| In reply to | #2933 |
On 04/27/11 09:39 AM, Keith Thompson wrote: > Ian Collins<ian-news@hotmail.com> writes: >> On 04/27/11 08:06 AM, Ben Bacarisse wrote: >>> Ian Collins<ian-news@hotmail.com> writes: >>> >>>> On 04/26/11 11:19 PM, Ben Bacarisse wrote: >>>>> Francois Grieu<fgrieu@gmail.com> writes: >>>>> >>>>>> On 26/04/2011 06:19, Anand Hariharan wrote: >>>>> >>>>>>> or will the 'arr' in the following code be a 'plain and ordinary' >>>>>>> array ... >>>>>>> >>>>>>> const int ncol = 5; >>>>>>> int arr[ncol]; >>>>> >>>>> The former. This is a VLA and will remain so in C1x. >>>>> >>>>>> I'm genuinely wondering: is ncol a "constant expression" ? >>>>> >>>>> It might be in that an implementation can define its own forms of >>>>> constant expression, but it does not meet the standard's minimum >>>>> requirements to be an "integer constant expression" (which is what is >>>>> required to declare a non-VL array). >>>> >>>> Which is really silly. I do wish they could fix that and bring it in >>>> line with C++. But I guess adding VLAs shot that idea in the foot. >>> >>> I too would like to have seen the same constant expression definition >>> between C++ and C but I don't see how C's VLAs got in the way of that. >> >> The code above sums it up, if ncol is an "integer constant expression" >> is arr an array, or a VLA? >> >> Would it be acceptable for a language change to change (all be it >> subtly) the behaviour of existing code? > > What behavior would change? > > Currently, arr is a VLA. If the rules were changed to make ncol a > constant expression, as it is in C++, arr would be an ordinary array > object, not a VLA. As far as I can tell, this would merely make some > things legal and well-defined that are currently either constraint > violations or undefined behavior. I can't think of any cases were valid > code would either become invalid or change its (currently defined) > behavior. Can you? No I can't off hand, but I'm sure someone could (Ben?). To be honest, I was struggling to find a reason why this obvious change hadn't been made and VLAs were the only (if feeble) one I could find... -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-04-26 23:41 +0100 |
| Message-ID | <0.03f3b69bd092863fec1b.20110426234112BST.87fwp4d4af.fsf@bsb.me.uk> |
| In reply to | #2933 |
Keith Thompson <kst-u@mib.org> writes: > Ian Collins <ian-news@hotmail.com> writes: <snip> >> Would it be acceptable for a language change to change (all be it >> subtly) the behaviour of existing code? > > What behavior would change? > > Currently, arr is a VLA. If the rules were changed to make ncol a > constant expression, as it is in C++, arr would be an ordinary array > object, not a VLA. As far as I can tell, this would merely make some > things legal and well-defined that are currently either constraint > violations or undefined behavior. I can't think of any cases were valid > code would either become invalid or change its (currently defined) > behavior. Can you? I think I can, but only in the most obscure way. For example: const int n = 10; int vla[n]; int (*vlap)[n] = &vla; int i = 0; sizeof vlap[i++]; must make i == 1 if vla is a VLA and must leave it at zero otherwise. For simplicity I've snipped the discussion that got us here so I feel I should re-state that I don't think this matters much (to put it mildly). -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-04-26 16:33 -0700 |
| Message-ID | <lntydky4dp.fsf@nuthaus.mib.org> |
| In reply to | #2938 |
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> Ian Collins <ian-news@hotmail.com> writes:
> <snip>
>>> Would it be acceptable for a language change to change (all be it
>>> subtly) the behaviour of existing code?
>>
>> What behavior would change?
>>
>> Currently, arr is a VLA. If the rules were changed to make ncol a
>> constant expression, as it is in C++, arr would be an ordinary array
>> object, not a VLA. As far as I can tell, this would merely make some
>> things legal and well-defined that are currently either constraint
>> violations or undefined behavior. I can't think of any cases were valid
>> code would either become invalid or change its (currently defined)
>> behavior. Can you?
>
> I think I can, but only in the most obscure way. For example:
>
> const int n = 10;
> int vla[n];
> int (*vlap)[n] = &vla;
> int i = 0;
> sizeof vlap[i++];
>
> must make i == 1 if vla is a VLA and must leave it at zero otherwise.
>
> For simplicity I've snipped the discussion that got us here so I feel I
> should re-state that I don't think this matters much (to put it mildly).
Interesting case. I think it illustrates a problem with C99's definition
of sizeof. C99 6.5.3.4p2 says:
If the type of the operand is a variable length array type, the
operand is evaluated; otherwise, the operand is not evaluated
and the result is an integer constant.
I think this both causes things to be evaluated that needn't be, and
doesn't cause things to be evaluated that should be, though it probably
matters only in obscure cases.
In the simplest case of applying sizeof to a VLA:
int r = rand() % 10 + 1;
int vla[r];
sizeof vla;
I'm not sure what it even means here to evaluate ``vla''. Certainly it
has to evaluate *something*, but that something is probably an anonymous
variable. (In particular, it's not r, since r can be modified without
affecting the VLA.)
In this contrived example:
int i;
void *p;
size_t s = sizeof (i = 42, (int(*)[i])p);
the argument to sizeof is not evaluated, even though the evaluation
of ``i = 42'' is needed for the type ``int(*)[i]'' to be valid.
On the other hand, in this case what's really being evaluated is
the size of a pointer, which probably (certainly?) doesn't actually
depend on the value of i.
Of course sizeof can also take a parenthesized type name as its
argument:
sizeof(int[rand() % 10 + 1]);
This is "evaluating" a type name. It's not at all clear what
that means, but presumably it includes evaluating the expression
``rand() % 10 + 1''.
Would this work?
If the operand is an expression, it is not evaluated. If the
operand is a parenthesized type name, each full expression that
is part of the type name is evaluated.
A VLA is the only case I can think of where a type name can include a
non-constant expression.
Hmm. In ``sizeof (int[42])'' is the expression ``42'' "evaluated"? C99
6.6.2 implies that it is ("A constant expression can be evaluated during
translation rather than runtime"), but 6.5.3.4 kinda sorta implies that it
isn't. Does the description of sizeof need to distinguish between
translation-time and execution-time evaluation?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-04-27 04:05 +0100 |
| Message-ID | <0.c3712d16eda3a0d863e2.20110427040508BST.87mxjcbdi3.fsf@bsb.me.uk> |
| In reply to | #2941 |
Keith Thompson <kst-u@mib.org> writes:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>> Keith Thompson <kst-u@mib.org> writes:
>>> Ian Collins <ian-news@hotmail.com> writes:
>> <snip>
>>>> Would it be acceptable for a language change to change (all be it
>>>> subtly) the behaviour of existing code?
>>>
>>> What behavior would change?
>>>
>>> Currently, arr is a VLA. If the rules were changed to make ncol a
>>> constant expression, as it is in C++, arr would be an ordinary array
>>> object, not a VLA. As far as I can tell, this would merely make some
>>> things legal and well-defined that are currently either constraint
>>> violations or undefined behavior. I can't think of any cases were valid
>>> code would either become invalid or change its (currently defined)
>>> behavior. Can you?
>>
>> I think I can, but only in the most obscure way. For example:
>>
>> const int n = 10;
>> int vla[n];
>> int (*vlap)[n] = &vla;
>> int i = 0;
>> sizeof vlap[i++];
>>
>> must make i == 1 if vla is a VLA and must leave it at zero otherwise.
>>
>> For simplicity I've snipped the discussion that got us here so I feel I
>> should re-state that I don't think this matters much (to put it mildly).
>
> Interesting case. I think it illustrates a problem with C99's definition
> of sizeof. C99 6.5.3.4p2 says:
>
> If the type of the operand is a variable length array type, the
> operand is evaluated; otherwise, the operand is not evaluated
> and the result is an integer constant.
>
> I think this both causes things to be evaluated that needn't be, and
> doesn't cause things to be evaluated that should be, though it probably
> matters only in obscure cases.
>
> In the simplest case of applying sizeof to a VLA:
>
> int r = rand() % 10 + 1;
> int vla[r];
> sizeof vla;
>
> I'm not sure what it even means here to evaluate ``vla''. Certainly it
> has to evaluate *something*, but that something is probably an anonymous
> variable. (In particular, it's not r, since r can be modified without
> affecting the VLA.)
At least in this case no program can tell if anything is or it not
evaluated.
> In this contrived example:
>
> int i;
> void *p;
> size_t s = sizeof (i = 42, (int(*)[i])p);
>
> the argument to sizeof is not evaluated, even though the evaluation
> of ``i = 42'' is needed for the type ``int(*)[i]'' to be valid.
>
> On the other hand, in this case what's really being evaluated is
> the size of a pointer, which probably (certainly?) doesn't actually
> depend on the value of i.
I don't think it such a dependence is prohibited (as it is for pointers
to structs for example).
Do you think there is something wrong with the very type itself when 'i'
is indeterminate?
> Of course sizeof can also take a parenthesized type name as its
> argument:
>
> sizeof(int[rand() % 10 + 1]);
>
> This is "evaluating" a type name. It's not at all clear what
> that means, but presumably it includes evaluating the expression
> ``rand() % 10 + 1''.
I've always taken it to mean that, but not based on any real evidence
from the standard. I don't think the notion is well-defined at all.
> Would this work?
>
> If the operand is an expression, it is not evaluated. If the
> operand is a parenthesized type name, each full expression that
> is part of the type name is evaluated.
That looks good to me. Of course it would change the meaning of the
code I posted but that's a good thing in this case.
> A VLA is the only case I can think of where a type name can include a
> non-constant expression.
>
> Hmm. In ``sizeof (int[42])'' is the expression ``42'' "evaluated"? C99
> 6.6.2 implies that it is ("A constant expression can be evaluated during
> translation rather than runtime"), but 6.5.3.4 kinda sorta implies that it
> isn't. Does the description of sizeof need to distinguish between
> translation-time and execution-time evaluation?
I can't see any advantage in doing that, but it's way too late here for
thinking about such things.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-04-26 22:49 +0100 |
| Message-ID | <0.967ba25c6450811178a3.20110426224949BST.87liywd6o2.fsf@bsb.me.uk> |
| In reply to | #2932 |
Ian Collins <ian-news@hotmail.com> writes: > On 04/27/11 08:06 AM, Ben Bacarisse wrote: >> Ian Collins<ian-news@hotmail.com> writes: >> >>> On 04/26/11 11:19 PM, Ben Bacarisse wrote: >>>> Francois Grieu<fgrieu@gmail.com> writes: >>>> >>>>> On 26/04/2011 06:19, Anand Hariharan wrote: >>>> >>>>>> or will the 'arr' in the following code be a 'plain and ordinary' >>>>>> array ... >>>>>> >>>>>> const int ncol = 5; >>>>>> int arr[ncol]; >>>> >>>> The former. This is a VLA and will remain so in C1x. >>>> >>>>> I'm genuinely wondering: is ncol a "constant expression" ? >>>> >>>> It might be in that an implementation can define its own forms of >>>> constant expression, but it does not meet the standard's minimum >>>> requirements to be an "integer constant expression" (which is what is >>>> required to declare a non-VL array). >>> >>> Which is really silly. I do wish they could fix that and bring it in >>> line with C++. But I guess adding VLAs shot that idea in the foot. >> >> I too would like to have seen the same constant expression definition >> between C++ and C but I don't see how C's VLAs got in the way of that. > > The code above sums it up, if ncol is an "integer constant expression" > is arr an array, or a VLA? Yes, a change in what constitutes an integer const expression would change some VLAs to plain arrays but I don't think that counts as "[shooting] that idea in the foot". > Would it be acceptable for a language change to change (all be it > subtly) the behaviour of existing code? I think so, in part because I am not certain that one can rely on the current behaviour. An implementation that permitted initialised const variables to appear in constant expressions would already have the "new" semantics (at least I think it would) so it could be argued that the code was skating on thin ice already. In addition, the change is very sight. A program that behaves differently were a VLA to become a plain arrays is already something of a monster. I can come up with such programs, but they are all very contrived. There may be a natural example, but it seems unlikely. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-04-27 10:19 +1200 |
| Message-ID | <91ouo6Fq9bU12@mid.individual.net> |
| In reply to | #2934 |
On 04/27/11 09:49 AM, Ben Bacarisse wrote:
> Ian Collins<ian-news@hotmail.com> writes:
>
>> On 04/27/11 08:06 AM, Ben Bacarisse wrote:
>>> Ian Collins<ian-news@hotmail.com> writes:
>>>
>>>> On 04/26/11 11:19 PM, Ben Bacarisse wrote:
>>>>> Francois Grieu<fgrieu@gmail.com> writes:
>>>>>
>>>>>> On 26/04/2011 06:19, Anand Hariharan wrote:
>>>>>
>>>>>>> or will the 'arr' in the following code be a 'plain and ordinary'
>>>>>>> array ...
>>>>>>>
>>>>>>> const int ncol = 5;
>>>>>>> int arr[ncol];
>>>>>
>>>>> The former. This is a VLA and will remain so in C1x.
>>>>>
>>>>>> I'm genuinely wondering: is ncol a "constant expression" ?
>>>>>
>>>>> It might be in that an implementation can define its own forms of
>>>>> constant expression, but it does not meet the standard's minimum
>>>>> requirements to be an "integer constant expression" (which is what is
>>>>> required to declare a non-VL array).
>>>>
>>>> Which is really silly. I do wish they could fix that and bring it in
>>>> line with C++. But I guess adding VLAs shot that idea in the foot.
>>>
>>> I too would like to have seen the same constant expression definition
>>> between C++ and C but I don't see how C's VLAs got in the way of that.
>>
>> The code above sums it up, if ncol is an "integer constant expression"
>> is arr an array, or a VLA?
>
> Yes, a change in what constitutes an integer const expression would
> change some VLAs to plain arrays but I don't think that counts as
> "[shooting] that idea in the foot".
>
>> Would it be acceptable for a language change to change (all be it
>> subtly) the behaviour of existing code?
>
> I think so, in part because I am not certain that one can rely on the
> current behaviour. An implementation that permitted initialised const
> variables to appear in constant expressions would already have the "new"
> semantics (at least I think it would) so it could be argued that the
> code was skating on thin ice already.
>
> In addition, the change is very sight. A program that behaves
> differently were a VLA to become a plain arrays is already something of
> a monster. I can come up with such programs, but they are all very
> contrived. There may be a natural example, but it seems unlikely.
I was trying to come up with one and the first example I conjured up
surprised me:
typedef char C[16];
void f( C* c ) {}
int main(void)
{
char c[16];
f( &c );
const unsigned n = 15;
char cc[n];
f( &cc );
}
Compiles fine as c99 (which was the surprise), but fails as C++ (type
mismatch). What did surprise me was the VLA type matching even though
the size differed. Changing the declaration of cc to cc[15] did produce
the expected compiler warnings.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-04-27 00:38 +0100 |
| Message-ID | <0.bae52d41338584cfc66d.20110427003859BST.87aafcd1m4.fsf@bsb.me.uk> |
| In reply to | #2937 |
Ian Collins <ian-news@hotmail.com> writes:
> On 04/27/11 09:49 AM, Ben Bacarisse wrote:
<snip>
>> In addition, the change is very sight. A program that behaves
>> differently were a VLA to become a plain arrays is already something of
>> a monster. I can come up with such programs, but they are all very
>> contrived. There may be a natural example, but it seems unlikely.
>
> I was trying to come up with one and the first example I conjured up
> surprised me:
>
> typedef char C[16];
>
> void f( C* c ) {}
>
> int main(void)
> {
> char c[16];
>
> f( &c );
>
> const unsigned n = 15;
>
> char cc[n];
>
> f( &cc );
> }
>
> Compiles fine as c99 (which was the surprise),
Hmm... At first glance it looks like a diagnostic is required. 6.7.5.2
p6 says:
"For two array types to be compatible, both shall have compatible
element types, and if both size specifiers are present, and are
integer constant expressions, then both size specifiers shall have the
same constant value. If the two array types are used in a context
which requires them to be compatible, it is undefined behavior if the
two size specifiers evaluate to unequal values."
so are '&cc' and the parameter 'c' pointers to compatible types? This
paragraph does not say. Maybe it is specified somewhere else, but I
can't find it.
I think the intent of the last sentence is to make the program's
behaviour is undefined, but that would imply the need for a diagnostic.
> but fails as C++ (type
> mismatch). What did surprise me was the VLA type matching even though
> the size differed. Changing the declaration of cc to cc[15] did
> produce the expected compiler warnings.
The standard can't mandate a type compatibility test that requires an
arbitrary non-constant expression to be evaluated, so in one way it is
not surprising that there is no error message. Unfortunately I can't
square that with the requirement to issue a diagnostic when a pointer to
an incompatible type is passed to a function.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-04-27 11:48 +1200 |
| Message-ID | <91p3udFq9bU13@mid.individual.net> |
| In reply to | #2940 |
On 04/27/11 11:38 AM, Ben Bacarisse wrote:
> Ian Collins<ian-news@hotmail.com> writes:
>
>> On 04/27/11 09:49 AM, Ben Bacarisse wrote:
> <snip>
>>> In addition, the change is very sight. A program that behaves
>>> differently were a VLA to become a plain arrays is already something of
>>> a monster. I can come up with such programs, but they are all very
>>> contrived. There may be a natural example, but it seems unlikely.
>>
>> I was trying to come up with one and the first example I conjured up
>> surprised me:
>>
>> typedef char C[16];
>>
>> void f( C* c ) {}
>>
>> int main(void)
>> {
>> char c[16];
>>
>> f(&c );
>>
>> const unsigned n = 15;
>>
>> char cc[n];
>>
>> f(&cc );
>> }
>>
>> Compiles fine as c99 (which was the surprise),
>
> Hmm... At first glance it looks like a diagnostic is required. 6.7.5.2
> p6 says:
>
> "For two array types to be compatible, both shall have compatible
> element types, and if both size specifiers are present, and are
> integer constant expressions, then both size specifiers shall have the
> same constant value. If the two array types are used in a context
> which requires them to be compatible, it is undefined behavior if the
> two size specifiers evaluate to unequal values."
>
> so are '&cc' and the parameter 'c' pointers to compatible types? This
> paragraph does not say. Maybe it is specified somewhere else, but I
> can't find it.
Me neither, that's what surprised me.
> I think the intent of the last sentence is to make the program's
> behaviour is undefined, but that would imply the need for a diagnostic.
>
>> but fails as C++ (type
>> mismatch). What did surprise me was the VLA type matching even though
>> the size differed. Changing the declaration of cc to cc[15] did
>> produce the expected compiler warnings.
>
> The standard can't mandate a type compatibility test that requires an
> arbitrary non-constant expression to be evaluated, so in one way it is
> not surprising that there is no error message. Unfortunately I can't
> square that with the requirement to issue a diagnostic when a pointer to
> an incompatible type is passed to a function.
I agree. I tried the code with both gcc 4.5.1 (-ansi -Wall -pedantic
-std=c99) and Sun c99.
I thought a VLA would always have an incompatible type, given its size
isn't known at compile time. In cases like this, I miss C++'s typeid!
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-04-26 17:38 -0700 |
| Message-ID | <lnipu0y1dr.fsf@nuthaus.mib.org> |
| In reply to | #2943 |
Ian Collins <ian-news@hotmail.com> writes:
> On 04/27/11 11:38 AM, Ben Bacarisse wrote:
>> Ian Collins<ian-news@hotmail.com> writes:
>>> On 04/27/11 09:49 AM, Ben Bacarisse wrote:
>> <snip>
>>>> In addition, the change is very sight. A program that behaves
>>>> differently were a VLA to become a plain arrays is already something of
>>>> a monster. I can come up with such programs, but they are all very
>>>> contrived. There may be a natural example, but it seems unlikely.
>>>
>>> I was trying to come up with one and the first example I conjured up
>>> surprised me:
>>>
>>> typedef char C[16];
>>>
>>> void f( C* c ) {}
>>>
>>> int main(void)
>>> {
>>> char c[16];
>>>
>>> f(&c );
>>>
>>> const unsigned n = 15;
>>>
>>> char cc[n];
>>>
>>> f(&cc );
>>> }
>>>
>>> Compiles fine as c99 (which was the surprise),
>>
>> Hmm... At first glance it looks like a diagnostic is required. 6.7.5.2
>> p6 says:
>>
>> "For two array types to be compatible, both shall have compatible
>> element types, and if both size specifiers are present, and are
>> integer constant expressions, then both size specifiers shall have the
>> same constant value. If the two array types are used in a context
>> which requires them to be compatible, it is undefined behavior if the
>> two size specifiers evaluate to unequal values."
>>
>> so are '&cc' and the parameter 'c' pointers to compatible types? This
>> paragraph does not say. Maybe it is specified somewhere else, but I
>> can't find it.
>
> Me neither, that's what surprised me.
>
>> I think the intent of the last sentence is to make the program's
>> behaviour is undefined, but that would imply the need for a diagnostic.
>>
>>> but fails as C++ (type
>>> mismatch). What did surprise me was the VLA type matching even though
>>> the size differed. Changing the declaration of cc to cc[15] did
>>> produce the expected compiler warnings.
>>
>> The standard can't mandate a type compatibility test that requires an
>> arbitrary non-constant expression to be evaluated, so in one way it is
>> not surprising that there is no error message. Unfortunately I can't
>> square that with the requirement to issue a diagnostic when a pointer to
>> an incompatible type is passed to a function.
>
> I agree. I tried the code with both gcc 4.5.1 (-ansi -Wall -pedantic
> -std=c99) and Sun c99.
>
> I thought a VLA would always have an incompatible type, given its size
> isn't known at compile time. In cases like this, I miss C++'s typeid!
C99 6.7.5.2p6:
For two array types to be compatible, both shall have compatible
element types, and if both size specifiers are present, and are
integer constant expressions, then both size specifiers shall
have the same constant value. If the two array types are used in
a context which requires them to be compatible, it is undefined
behavior if the two size specifiers evaluate to unequal values.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-04-27 13:08 +1200 |
| Message-ID | <91p8l4Fq9bU14@mid.individual.net> |
| In reply to | #2945 |
On 04/27/11 12:38 PM, Keith Thompson wrote: > Ian Collins<ian-news@hotmail.com> writes: >> On 04/27/11 11:38 AM, Ben Bacarisse wrote: >>> >>> The standard can't mandate a type compatibility test that requires an >>> arbitrary non-constant expression to be evaluated, so in one way it is >>> not surprising that there is no error message. Unfortunately I can't >>> square that with the requirement to issue a diagnostic when a pointer to >>> an incompatible type is passed to a function. >> >> I agree. I tried the code with both gcc 4.5.1 (-ansi -Wall -pedantic >> -std=c99) and Sun c99. >> >> I thought a VLA would always have an incompatible type, given its size >> isn't known at compile time. In cases like this, I miss C++'s typeid! > > C99 6.7.5.2p6: > > For two array types to be compatible, both shall have compatible > element types, and if both size specifiers are present, and are > integer constant expressions, then both size specifiers shall > have the same constant value. If the two array types are used in > a context which requires them to be compatible, it is undefined > behavior if the two size specifiers evaluate to unequal values. Ah, so they are incompatible, but no diagnostic was issued by either compiler. I'd be interested in seeing if another C99 compiler issues one. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web