Topic: Minimum Size of Array in Standard


Author: AllanW@my-dejanews.com
Date: 1998/11/14
Raw View
In article <199811130655.AAA00379@centurion.flash.net>,
  blargg@flash.net (Gargantua Blargg) wrote:
> In article <364A5E81.D8768AE4@ix.netcom.com>, "Paul D. DeRocco"
> <pderocco@ix.netcom.com> wrote:
>
> ...
> > The nice thing about allowing either zero elements or an unspecified
> > number of elements is that sizeof can return the size of the structure
> > before any array elements are added, thus slightly simplifying and
> > clarifying the arithmetic necessary to compute the parameter to malloc.
> >
> > Of course, malloc is un-C++ like anyway. I've always preferred using the
> > placement-new syntax for allocating such things:
> >
> >         class foo {
> >         public:
> >             size_t len;
> >             char data[1];
> >             foo(size_t l): len(l) {}
> >             void* operator new(size_t n, size_t l) {
> >                 return malloc(n + l - 1);
> >                 }
> >             };
> >
> >         foo* z = new(20) foo(20);
>
> offsetof () must be in people's kill-filters or something. I mention this
> solution so often. Anyway, just use offsetof defined in stddef.h:

Perhaps not as easy to use as you think. Error prone?

>     malloc( offsetof (foo,len [number_of_array_elements]) )
                            ^^^
That should be data, not len.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: blargg@flash.net (Gargantua Blargg)
Date: 1998/11/15
Raw View
In artivle <<72hqcr$fel$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com wrote:
> In article <199811130655.AAA00379@centurion.flash.net>,
>   blargg@flash.net (Gargantua Blargg) wrote:
> > In article <364A5E81.D8768AE4@ix.netcom.com>, "Paul D. DeRocco"
> > <pderocco@ix.netcom.com> wrote:
...
> > > The nice thing about allowing either zero elements or an unspecified
> > > number of elements is that sizeof can return the size of the structure
> > > before any array elements are added, thus slightly simplifying and
> > > clarifying the arithmetic necessary to compute the parameter to malloc.
...
> > Anyway, just use offsetof defined in stddef.h:
>
> Perhaps not as easy to use as you think. Error prone?
>
[ struct foo's array is named data, not len ]
> >     malloc( offsetof (foo,len [number_of_array_elements]) )
>                             ^^^
> That should be data, not len.

OK, so I made an error. The compiler will catch it. However, the
alternative, even when the compiler doesn't include the size of the array
in the structure size, is more error-prone, because you have to mention
the type of the array when allocating:

    alloc_size = sizeof (my_struct) + sizeof (array_type) * array_size

For all we know, my_struct doesn't even have an array in it! The compiler
won't catch that from this usage, though.

offsetof doesn't require you to mention the type of the array (and works
without the array size -1 thing required if the compiler doesn't allow a
zero-length array at the end)

    alloc_size = offsetof (my_struct,end_array [array_size])

I still stand by the recommendation to use offsetof () in preference to
the alternative of manually calculating the size as discussed so far.

--
blarggflash.net | Gargantua Blargg | http://www.flash.net/~blargg/


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Jim Cobban" <Jim.Cobban.jcobban@nt.com>
Date: 1998/11/16
Raw View
In article <199811150346.VAA09025@centurion.flash.net>,
Gargantua Blargg <blargg@flash.net> wrote:
...
>I still stand by the recommendation to use offsetof () in preference to
>the alternative of manually calculating the size as discussed so far.

In C++ offsetof only applies to PODs where sizeof applies to anything.


--
Jim Cobban   |  jcobban@nortel.ca                   |  Phone: (613) 763-8013
Nortel Networks (MED)                               |  FAX:   (613) 763-5199


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/11/16
Raw View
In article <199811150346.VAA09025@centurion.flash.net>,
  blargg@flash.net (Gargantua Blargg) wrote:
 > > > Anyway, just use offsetof defined in stddef.h:
 > >
 > > Perhaps not as easy to use as you think. Error prone?
 > >
 > [ struct foo's array is named data, not len ]
 > > >     malloc( offsetof (foo,len [number_of_array_elements]) )
 > >                             ^^^
 > > That should be data, not len.
 >
 > OK, so I made an error. The compiler will catch it. However, the
 > alternative, even when the compiler doesn't include the size of the array
 > in the structure size, is more error-prone, because you have to mention
 > the type of the array when allocating:
 >
 >     alloc_size = sizeof (my_struct) + sizeof (array_type) * array_size
 >
 > For all we know, my_struct doesn't even have an array in it! The compiler
 > won't catch that from this usage, though.
 >
 > offsetof doesn't require you to mention the type of the array (and works
 > without the array size -1 thing required if the compiler doesn't allow a
 > zero-length array at the end)
 >
 >     alloc_size = offsetof (my_struct,end_array [array_size])
 >
 > I still stand by the recommendation to use offsetof () in preference to
 > the alternative of manually calculating the size as discussed so far.

Okay, I'm convinced. I agree with you.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/11/12
Raw View
David R Tribble wrote:
>
> That's what comments are for:
>
>         int           elements[1];    // 1 or more elements

The nice thing about allowing either zero elements or an unspecified
number of elements is that sizeof can return the size of the structure
before any array elements are added, thus slightly simplifying and
clarifying the arithmetic necessary to compute the parameter to malloc.

Of course, malloc is un-C++ like anyway. I've always preferred using the
placement-new syntax for allocating such things:

 class foo {
 public:
     size_t len;
     char data[1];
     foo(size_t l): len(l) {}
     void* operator new(size_t n, size_t l) {
         return malloc(n + l - 1);
         }
     };

 foo* z = new(20) foo(20);

--

Ciao,
Paul


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/11/13
Raw View
David R Tribble <david.tribble@noSPAM.central.beasys.com> writes:

>Yes, but something has been added to C9x for just this sort of thing:

>    struct varstruct2
>    {
>        unsigned int  num_elements;
>        int           elements[];   // FAM
>    };

>C9x allows the last member of a struct to be an array of unspecified
>size, which is called a "flexible array member".  The only legal
>way to reserve storage for type varstruct2 is by calling malloc()
>(or its equivalent); in particular, you can't define auto objects
>of this type.  But C++ doesn't have this feature (yet).

The feature would have to be restricted to POD-structs, and
we'd need a further restriction that you could not derive
from such a struct.  Variable-sized elements don't mix well with
inheritance -- especially multiple inheritance. A FAM-struct would
be a partly complete type, a concept we don't currently have in C++.
(It isn't an incomplete type since you can allocate one on the heap.)

OTOH, the C++ type system is based on the idea that an object's
type tells you all you need to know about it, including its size.
The construct above gives you objects of the "same" type that
are in fact different. What do we say about the compiler-generated
copy constructor and copy assignment operator? I think we need
yet another exception -- you can't assign or copy the objects.

Wouldn't it make more sense in C++ to use a template?

template<size_t num_elements> struct varstruct2
{
 // we don't need a member for the element count
 int elements[num_elements];
};

Now objects with the same type really have the same type.

If instead you want objects of the same type nevertheless to
have different array sizes, you can use the common technique
of putting the array on the heap and keep only a pointer in
the class. (The constructors and destructor do all the work
for you.)

And of course, we already have vector and valarray templates.

I don't see FAM-structs as a valuable addition to C++. The story
is different for C, where you don't have templates or constructors.

--
Steve Clamage, stephen.clamage@sun.com
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: blargg@flash.net (Gargantua Blargg)
Date: 1998/11/13
Raw View
In article <364A5E81.D8768AE4@ix.netcom.com>, "Paul D. DeRocco"
<pderocco@ix.netcom.com> wrote:

...
> The nice thing about allowing either zero elements or an unspecified
> number of elements is that sizeof can return the size of the structure
> before any array elements are added, thus slightly simplifying and
> clarifying the arithmetic necessary to compute the parameter to malloc.
>
> Of course, malloc is un-C++ like anyway. I've always preferred using the
> placement-new syntax for allocating such things:
>
>         class foo {
>         public:
>             size_t len;
>             char data[1];
>             foo(size_t l): len(l) {}
>             void* operator new(size_t n, size_t l) {
>                 return malloc(n + l - 1);
>                 }
>             };
>
>         foo* z = new(20) foo(20);

offsetof () must be in people's kill-filters or something. I mention this
solution so often. Anyway, just use offsetof defined in stddef.h:

    malloc( offsetof (foo,len [number_of_array_elements]) )

Of course, the type (foo in this case) must be a POD for offsetof () to
yield defined results. And, as the recent threads regarding this issue
have shown, the whole thing isn't very well-defined anyway (no matter how
you allocate, and size  the array in the struct).

--
blarggflash.net | Gargantua Blargg | http://www.flash.net/~blargg/
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/11/13
Raw View
In article <364A319A.25A8@pratique.fr>,
Valentin Bonnard  <bonnardv@pratique.fr> wrote:
>Hans Olsson wrote:
>
>> Does the final standard make the situation more clear, or is there
>> something wrong with this analysis?
>
>The standard makes nothing about PODs, unions, and dirty tricks
>clear. I would say that the standard doesn't say anything about
>unions except their syntax and static semantics (well-formed vs
>ill-formed programs).

I agree that the standard leaves some things unclear; this
is often intentional (to allow compilers to choose) and sometimes
errors might have slipped past the committee (I believe that the
definition of when a[i] is undefined fall in the latter category).

As an example consider the two structs I had:

struct {T data9[9];} s9;
struct {T data1[1];} s1;

(where offsetof(s9,data9)==offsetof(s1,data1)==0).
My first attempt was (Header and T are POD-types):

struct {Header h;T data9[9];} s9;
struct {Header h;T data1[1];} s1;

But then I couldn't find that offsetof(s9,data9)==offsetof(s1,data1).

I'm not sure if I'm missing something, the C++ standard committee missed
it, or the intention was to allow a compiler to align the larger array
for faster access.
--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/11/13
Raw View
Steve Clamage wrote:

> David R Tribble <david.tribble@noSPAM.central.beasys.com> writes:

> >Yes, but something has been added to C9x for just this sort of thing:

> >    struct varstruct2
> >    {
> >        unsigned int  num_elements;
> >        int           elements[];   // FAM
> >    };

> >C9x allows the last member of a struct to be an array of unspecified
> >size, which is called a "flexible array member".  The only legal
> >way to reserve storage for type varstruct2 is by calling malloc()
> >(or its equivalent); in particular, you can't define auto objects
> >of this type.  But C++ doesn't have this feature (yet).

> The feature would have to be restricted to POD-structs, and
> we'd need a further restriction that you could not derive
> from such a struct.  Variable-sized elements don't mix well with
> inheritance -- especially multiple inheritance. A FAM-struct would
> be a partly complete type, a concept we don't currently have in C++.
> (It isn't an incomplete type since you can allocate one on the heap.)

> OTOH, the C++ type system is based on the idea that an object's
> type tells you all you need to know about it, including its size.
> The construct above gives you objects of the "same" type that
> are in fact different. What do we say about the compiler-generated
> copy constructor and copy assignment operator? I think we need
> yet another exception -- you can't assign or copy the objects.

> Wouldn't it make more sense in C++ to use a template?

> template<size_t num_elements> struct varstruct2
> {
>         // we don't need a member for the element count
>         int elements[num_elements];
> };

In the typical application using this construct, the number of elements
is often a variable, not a run-time constant, which would make your
template hard to use. That variable will often take on, at run-time,
every possible value from 1 to a very large upper limit. This template
would require that functions taking varstruct2 arguments be templated by
num_elements, and be instantiated for every possible num_elements. For
some applications, that would require 10's of thousands of
instantiations.

vector<> or valarray<> would probably be acceptable replacements in most
contexts.


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/11/11
Raw View
In article <729jdk$fvu$1@nnrp1.dejanews.com>,  <markw65@my-dejanews.com> wrote:
>In article <3647600B.17EE@noSPAM.central.beasys.com>,
>  dtribble@technologist.com wrote:
>>
>>     struct varstruct
>>     {
>>         unsigned int  num_elements;
>>         int           elements[1];   // 1 or more
>>     };
>>
[Deleted]
>>         struct varstruct *   p;
[Deleted]
>>         ... p->elements[i] ...      // i < n [A]
>>     }
>>
>> The statement at [A] probably invokes undefined behavior, even
>> though the object that p points to is obviously large enough to
>> hold an array member of n ints.  So while it's probably undefined
>> behavior, I don't think you're going to find a real implementation
>> where it won't work (as long as i >= 0 and i < n).
>
>There is at least one. And as optimizations improve there should be more. As
>soon as you access p->elements[i], the compiler can deduce that 0 <= i <
>sizeof(p->elements) / p->elements[0.

Can it?

The problem is if what allows the compiler to determine that p->elements[i]
(for i>=1) is illegal; we have at least the following alternatives:

1: p->elements is declared as an array of size 1.
2: p->elements (converted to a pointer) is an element of an array of size 1.
3: All arrays that have p->elements (converted to a pointer) as element
of the array have an array size of 1.

Reading CD2 seemed to indicate that it is either 2 or 3, but definitely
not 1. (Alternative 1 is used in languages where arrays don't decay
into pointers, e.g. Pascal).

The problem with alternative 3 is that it seems to require global
analysis to perform the optimization, whereas alternative 2 can
lead to surprising results.

Obviously separating alternative 2 and 3
require that we can create two arrays with common elements without
invoking undefined behavior. I believe this is possible:

struct var1 {int array1[1];};
struct var9 {int array9[9];};

char*c=operator new(sizeof(var9)+sizeof(var1)); // Surely this is sufficient.

var1*v1=static_cast<var1*>(c);
var9*v9=static_cast<var9*>(c);

If I understand POD-structs correctly var1.array1 and
var9.array9 (converted to int*) point to the same object,
and it is thus an element of two arrays of different length.

Alternative 3 would make v1->array1[5] legal, whereas
alternative 2 would make v9->array9[5] undefined.

Does the final standard make the situation more clear, or is there
something wrong with this analysis?

--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/11/12
Raw View
Hans Olsson wrote:

> Does the final standard make the situation more clear, or is there
> something wrong with this analysis?

The standard makes nothing about PODs, unions, and dirty tricks
clear. I would say that the standard doesn't say anything about
unions except their syntax and static semantics (well-formed vs
ill-formed programs).

I asked some core group commitee members and I didn't felt any
support to make things clear.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: markw65@my-dejanews.com
Date: 1998/11/10
Raw View
In article <3647600B.17EE@noSPAM.central.beasys.com>,
  dtribble@technologist.com wrote:
>
>     struct varstruct
>     {
>         unsigned int  num_elements;
>         int           elements[1];   // 1 or more
>     };
>
>     void varfunc(int n)
>     {
>         char *               c;
>         struct varstruct *   p;
>
>         assert(n > 0);
>         c = new char[sizeof(struct varstruct) + (n-1)*sizeof(int)];
>         p = static_cast<struct varstruct *>(c);
>         p->num_elements = n;
>
>         ... p->elements[i] ...      // i < n [A]
>     }
>
> The statement at [A] probably invokes undefined behavior, even
> though the object that p points to is obviously large enough to
> hold an array member of n ints.  So while it's probably undefined
> behavior, I don't think you're going to find a real implementation
> where it won't work (as long as i >= 0 and i < n).

There is at least one. And as optimizations improve there should be more. As
soon as you access p->elements[i], the compiler can deduce that 0 <= i <
sizeof(p->elements) / p->elements[0.

In this case, that doesnt leave much scope for i... In general it provides
oportunities for a variety of value-range based optimizations.

Mark Williams

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <david.tribble@noSPAM.central.beasys.com>
Date: 1998/11/10
Raw View
"Jim Cobban" <Jim.Cobban.jcobban@nt.com> writes:
>> ...
>> This is used in a lot of existing code to
>> represent an array whose size is known by some implementation
>> specific method, for example in a structure such as the following:
>>   struct varstruct
>>   {
>>       unsigned int   num_elements;
>>       int            elements[0];
>>   };

J. Kanze <kanze@gabi-soft.fr> wrote in article
>> This code is illegal (in C).

Yes, but something has been added to C9x for just this sort of thing:

    struct varstruct2
    {
        unsigned int  num_elements;
        int           elements[];   // FAM
    };

C9x allows the last member of a struct to be an array of unspecified
size, which is called a "flexible array member".  The only legal
way to reserve storage for type varstruct2 is by calling malloc()
(or its equivalent); in particular, you can't define auto objects
of this type.  But C++ doesn't have this feature (yet).

>> The code can be made to compile by changing the dimension of the
>> array elements to [1] but this would be misleading to the reader
>> since num_elements may be zero.

That's what comments are for:

        int           elements[1];    // 1 or more elements

J. Kanze <kanze@gabi-soft.fr> wrote:
>> If the use you make of it is what I suspect, you also invoke
>> undefined  behavior later.  If the array is declared with a length
>> of 1, any attempt to access an element with an index greater than 0
>> is undefined behavior.  At least in C.

This is probably true.  I asked this question on comp.std.c a while
back, but never got an straight answer.

However, consider this fragment:

    struct varstruct
    {
        unsigned int  num_elements;
        int           elements[1];   // 1 or more
    };

    void varfunc(int n)
    {
        char *               c;
        struct varstruct *   p;

        assert(n > 0);
        c = new char[sizeof(struct varstruct) + (n-1)*sizeof(int)];
        p = static_cast<struct varstruct *>(c);
        p->num_elements = n;

        ... p->elements[i] ...      // i < n [A]
    }

The statement at [A] probably invokes undefined behavior, even
though the object that p points to is obviously large enough to
hold an array member of n ints.  So while it's probably undefined
behavior, I don't think you're going to find a real implementation
where it won't work (as long as i >= 0 and i < n).

And you're probably not interested in strictly conforming code
anyway; I'll bet you're only going to port your code to a dozen or
so platforms.

Greg Colvin <colvin@no.spam.please> wrote:
> I think the well defined thing to do is something like
>    struct varstruct
>    {
>      unsigned int       num_elements;
>      int                elements[MAX_VARSTRUCT_ELEMENTS];
>    };
>
> and then malloc just as much space as needed.

The problem with this approach is that it gives the false impression
that elements[] contains MAX_VARSTRUCT_ELEMENTS items when in fact
it contains less, just like the problem with declaring it as having
only 1 element.  But again, that's what comments are for.

-- David R. Tribble, dtribble@technologist.com --
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Greg Colvin" <colvin@no.spam.please>
Date: 1998/11/04
Raw View
J. Kanze <kanze@gabi-soft.fr> wrote in article
> "Jim Cobban" <Jim.Cobban.jcobban@nt.com> writes:
> ...
> |>  This is used in a lot of existing code to
> |>  represent an array whose size is known by some implementation specific
> |>  method, for example in a structure such as the following:
> |>
> |>   struct varstruct
> |>   {
> |>     unsigned int num_elements;
> |>     int  elements[0];
> |>   };
>
> This code is illegal (in C).
>
> |>  The code can be made to compile by changing the dimension of the array
> |>  elements to [1] but this would be misleading to the reader since
> |>  num_elements may be zero.
>
> If the use you make of it is what I suspect, you also invoke undefined
> behavior later.  If the array is declared with a length of 1, any
> attempt to access an element with an index greater than 0 is undefined
> behavior.  At least in C.

I think the well defined thing to do is something like

   struct varstruct
   {
     unsigned int num_elements;
     int  elements[MAX_VARSTRUCT_ELEMENTS];
   };

and then malloc just as much space as needed.

Greg Colvin
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jkanze@otelo.ibmmail.com
Date: 1998/11/05
Raw View
In article <199811032027.NAA25799@ncar.ucar.EDU>,
  "Greg Colvin" <colvin@no.spam.please> wrote:
> J. Kanze <kanze@gabi-soft.fr> wrote in article
> > "Jim Cobban" <Jim.Cobban.jcobban@nt.com> writes:
> > ...
> > |>  This is used in a lot of existing code to
> > |>  represent an array whose size is known by some implementation specific
> > |>  method, for example in a structure such as the following:
> > |>
> > |>   struct varstruct
> > |>   {
> > |>     unsigned int num_elements;
> > |>     int  elements[0];
> > |>   };
> >
> > This code is illegal (in C).
> >
> > |>  The code can be made to compile by changing the dimension of the array
> > |>  elements to [1] but this would be misleading to the reader since
> > |>  num_elements may be zero.
> >
> > If the use you make of it is what I suspect, you also invoke undefined
> > behavior later.  If the array is declared with a length of 1, any
> > attempt to access an element with an index greater than 0 is undefined
> > behavior.  At least in C.
>
> I think the well defined thing to do is something like
>
>    struct varstruct
>    {
>      unsigned int num_elements;
>      int  elements[MAX_VARSTRUCT_ELEMENTS];
>    };
>
> and then malloc just as much space as needed.

This was suggested as well in comp.std.c.  If I recall right, the conclusion
was that you have a varstruct object, and if you allocate less memory than
sizeof( varstruct ), and then access it as a varstruct, you have undefined
behavior.

--
James Kanze                         email: kanze@gabi-soft.fr

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: AllanW@my-dejanews.com
Date: 1998/10/24
Raw View
In article <F1A9A0.F0t@research.att.com>,
  ark@research.att.com (Andrew Koenig) wrote:
>
> In article <70o2gd$86q$1@bcarh8ab.ca.nortel.com>,
> Jim Cobban <Jim.Cobban.jcobban@nt.com> wrote:
>
> > My issue is that this deviates from past practice which permitted
explicitly
> > declaring an array with size 0.  This is used in a lot of existing code to
> > represent an array whose size is known by some implementation specific
> > method, for example in a structure such as the following:
>
> >  struct varstruct
> >  {
> >    unsigned int num_elements;
> >    int  elements[0];
> >  };
>
> > The code can be made to compile by changing the dimension of the array
> > elements to [1] but this would be misleading to the reader since
> > num_elements may be zero.
>
> Neither the C nor the C++ standard supports this technique.  Period.

You are both right.

The standard forbids this. It always has.

There is a lot of existing code out there that uses it. Also, sometimes
the programmers -- apparently including Jim -- didn't even know that
they were relying on local extensions supported by their compiler,
but not neccesarily portable.

Jim, if the structure is fairly high-level, you can replace it with
some other construct, perhaps a list or vector. If it's low level
(i.e. you're reading it from a file, or writing it to a file), then
the obvious change would be to use an array of size 1, and modify
all your sizeof()'s accordingly.  Or consider this:

    struct varstruct_base {
        unsigned int num_elements;
        // If any changes are made, also modify varstruct
    };
    struct varstruct {
        unsigned int num_elements;
        // If any changes are made before this point,
        // also modify varstruct_base
        int elements[1];
    };
(Or, alternatively
    struct varstruct_base {
        unsigned int num_elements;
    };
    struct varstruct {
        varstruct_base base;
        int elements[1];
    };
but this may require additional source code changes.)

Now use sizeof(varstruct_base) when you need the size of the
structure for memory allocation, file I/O, etc. But use varstruct
unchanged everywhere else.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/10/26
Raw View
"Jim Cobban" <Jim.Cobban.jcobban@nt.com> writes:

|>  In the December 1996 draft in section 8.3.4 "Arrays" paragraph 1 it states:
|>
|>  "If the constant-expression (_expr.const_) is present, it shall be an
|>   integral  constant  expression  and  its  value  shall  be greater  than
|>   zero."
|>
|>  Is this statement still present in the standard?
|>
|>  My issue is that this deviates from past practice which permitted explicitly
|>  declaring an array with size 0.

C never allowed arrays with a length of 0.

|>  This is used in a lot of existing code to
|>  represent an array whose size is known by some implementation specific
|>  method, for example in a structure such as the following:
|>
|>   struct varstruct
|>   {
|>     unsigned int num_elements;
|>     int  elements[0];
|>   };

This code is illegal (in C).

|>  The code can be made to compile by changing the dimension of the array
|>  elements to [1] but this would be misleading to the reader since
|>  num_elements may be zero.

If the use you make of it is what I suspect, you also invoke undefined
behavior later.  If the array is declared with a length of 1, any
attempt to access an element with an index greater than 0 is undefined
behavior.  At least in C.

|>  My current compiler (GCC 2.7.1) does not consider this an error, but I will
|>  have a lot of work on my plate if a later version decides to comply with the
|>  standard.

A certain number of compilers do implement this as an extension.

|>  This point is not referred to in the Compatibility section of the draft
|>  standard, and is not mentioned in Stroustrup 3rd Edition.

Probably because there is no compatibility problem.  See ISO 9899,
6.5.4.2, under "constraints": "The expression delimited by [ and ]
(which specifies the size of the array) shall be an integral constant
expression that has a value greater than zero."  This sounds awfully
like the sentence in the C++ standard.

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient   e objet --
              -- Beratung in objektorientierter Datenverarbeitung
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Jim Cobban" <Jim.Cobban.jcobban@nt.com>
Date: 1998/10/26
Raw View
In article <70psn6$7k2$1@nnrp1.dejanews.com>,  <nimel@hem1.passagen.se> wrote:
>
>Why not use a vector<int> then?

 1) STL is broken in GCC 2.7.1.  That is you cannot use STL containers in
    more than one .cc file of a program and still be able to link.
 2) The struct is describing the layout of information in memory.  That
    memory comes from another program over which I have no control.
 3) There are over 700 instances of this in this one program.

--
Jim Cobban   |  jcobban@nortel.ca                   |  Phone: (613) 763-8013
Nortel (MCS) |                                      |  FAX:   (613) 763-5199


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Jim Cobban" <Jim.Cobban.jcobban@nt.com>
Date: 1998/10/22
Raw View
In the December 1996 draft in section 8.3.4 "Arrays" paragraph 1 it states:

"If the constant-expression (_expr.const_) is present, it shall be an
 integral  constant  expression  and  its  value  shall  be greater  than
 zero."

Is this statement still present in the standard?

My issue is that this deviates from past practice which permitted explicitly
declaring an array with size 0.  This is used in a lot of existing code to
represent an array whose size is known by some implementation specific
method, for example in a structure such as the following:

 struct varstruct
 {
   unsigned int num_elements;
   int  elements[0];
 };

The code can be made to compile by changing the dimension of the array
elements to [1] but this would be misleading to the reader since
num_elements may be zero.

My current compiler (GCC 2.7.1) does not consider this an error, but I will
have a lot of work on my plate if a later version decides to comply with the
standard.

This point is not referred to in the Compatibility section of the draft
standard, and is not mentioned in Stroustrup 3rd Edition.
--
Jim Cobban   |  jcobban@nortel.ca                   |  Phone: (613) 763-8013
Nortel (MCS) |                                      |  FAX:   (613) 763-5199


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/10/23
Raw View
im Cobban wrote:
>
> In the December 1996 draft in section 8.3.4 "Arrays" paragraph 1 it
> states:

> "If the constant-expression (_expr.const_) is present, it shall be an
>  integral  constant  expression  and  its  value  shall  be greater
>  than zero."

> Is this statement still present in the standard?

Yep. Happy hunting.

--

Ciao,
Paul



[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: ark@research.att.com (Andrew Koenig)
Date: 1998/10/23
Raw View
In article <70o2gd$86q$1@bcarh8ab.ca.nortel.com>,
Jim Cobban <Jim.Cobban.jcobban@nt.com> wrote:

> My issue is that this deviates from past practice which permitted explicitly
> declaring an array with size 0.  This is used in a lot of existing code to
> represent an array whose size is known by some implementation specific
> method, for example in a structure such as the following:

>  struct varstruct
>  {
>    unsigned int num_elements;
>    int  elements[0];
>  };

> The code can be made to compile by changing the dimension of the array
> elements to [1] but this would be misleading to the reader since
> num_elements may be zero.

Neither the C nor the C++ standard supports this technique.  Period.

--
    Andrew Koenig
    ark@research.att.com
    http://www.research.att.com/info/ark




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: nimel@hem1.passagen.se
Date: 1998/10/23
Raw View
In article <70o2gd$86q$1@bcarh8ab.ca.nortel.com>,
  "Jim Cobban" <Jim.Cobban.jcobban@nt.com> wrote:
>
> In the December 1996 draft in section 8.3.4 "Arrays" paragraph 1 it states:
>
> "If the constant-expression (_expr.const_) is present, it shall be an
>  integral  constant  expression  and  its  value  shall  be greater  than
>  zero."
>
> Is this statement still present in the standard?

Yes, the standard text is exactly as quoted above.

[snip...]

>  struct varstruct
>  {
>    unsigned int num_elements;
>    int  elements[0];
>  };

This is a hack that was discussed quite recently in either C++ Report or
C/C++ Users Journal. I don't remember the conclusion or exactly when I
read it but is was definitly within the last 6 months.

> My current compiler (GCC 2.7.1) does not consider this an error, but I will
> have a lot of work on my plate if a later version decides to comply with the
> standard.

Why not use a vector<int> then?

/Niklas Mellin

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/10/23
Raw View
Andrew Koenig wrote:
>
> In article <70o2gd$86q$1@bcarh8ab.ca.nortel.com>,
> Jim Cobban <Jim.Cobban.jcobban@nt.com> wrote:
>
> > My issue is that this deviates from past practice which permitted explicitly
> > declaring an array with size 0.  This is used in a lot of existing code to
> > represent an array whose size is known by some implementation specific
> > method, for example in a structure such as the following:
>
> >  struct varstruct
> >  {
> >    unsigned int       num_elements;
> >    int                elements[0];
> >  };
>
> > The code can be made to compile by changing the dimension of the array
> > elements to [1] but this would be misleading to the reader since
> > num_elements may be zero.
>
> Neither the C nor the C++ standard supports this technique.  Period.

As I've mentioned in another message, C9X will support a variant of this
technique, using 'elements[]' rather than 'elements[0]'.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Bill Wade" <bill.wade@stoner.com>
Date: 1998/10/23
Raw View

Andrew Koenig wrote in message ...
>
>> [struct hack]
>
>Neither the C nor the C++ standard supports this technique.  Period.


The next C standard (C9X) provides support, with a slightly different
syntax.  I believe it looks like

  struct hack { foo stuff; bar elements[]; };

Cheers.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]