Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #2883 > unrolled thread

multidimensional heap arrays

Started byJack Boot <jackboot@mailinator.com>
First post2011-04-25 19:36 +0000
Last post2011-04-25 22:57 -0400
Articles 20 on this page of 32 — 10 participants

Back to article view | Back to comp.lang.c


Contents

  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 →


#2883 — multidimensional heap arrays

FromJack Boot <jackboot@mailinator.com>
Date2011-04-25 19:36 +0000
Subjectmultidimensional 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]


#2885

FromFrancois Grieu <fgrieu@gmail.com>
Date2011-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]


#2886

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-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]


#2902

FromAnand Hariharan <mailto.anand.hariharan@gmail.com>
Date2011-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]


#2903

FromFrancois Grieu <fgrieu@gmail.com>
Date2011-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]


#2919

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-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]


#2921

FromIan Collins <ian-news@hotmail.com>
Date2011-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]


#2931

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-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]


#2932

FromIan Collins <ian-news@hotmail.com>
Date2011-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]


#2933

FromKeith Thompson <kst-u@mib.org>
Date2011-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]


#2936

FromIan Collins <ian-news@hotmail.com>
Date2011-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]


#2938

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-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]


#2941

FromKeith Thompson <kst-u@mib.org>
Date2011-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]


#2950

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-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]


#2934

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-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]


#2937

FromIan Collins <ian-news@hotmail.com>
Date2011-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]


#2940

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-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]


#2943

FromIan Collins <ian-news@hotmail.com>
Date2011-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]


#2945

FromKeith Thompson <kst-u@mib.org>
Date2011-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]


#2947

FromIan Collins <ian-news@hotmail.com>
Date2011-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