Topic: Type of "new" expression


Author: NULL@NULL.NULL ("Tom s")
Date: Fri, 24 Mar 2006 16:07:06 GMT
Raw View
For argument's sake, let's say we have the following function which we wa=
nt=20
to invoke:

void ProcessFiveMemberships( unsigned (&memberships)[5] );


If "new" is used to allocate an array, as follows:

    new unsigned[5];

Then the type of this expression is not "unsigned (*)[5]", but "unsigned =
*".

My first question is, Why was this made so? It would make more sense to m=
e=20
to return a pointer to an array of five objects, rather than a pointer to=
=20
one sole object.

We want to invoke "ProcessFiveMemberships". The following is ill-formed:

void ProcessFiveMemberships( unsigned (&memberships)[5] )
{
    //Empty function body

    for (;;)
    {
        break;
    }
}

int main()
{
    unsigned* p_first_membership =3D new unsigned[5];

    ProcessFiveMemberships( *p_first_membership ); // type mismatch

    delete [] p_first_membership;
}


Is there any perfectly legal, fully portable way of turning our "unsigned=
=20
*" into an "unsigned (*)[5]"?


How about the two following methods:


ProcessFiveMemberships(
    *reinterpret_cast<unsigned (*)[5]>(p_first_membership)
    );

or:

ProcessFiveMemberships(
    *static_cast< unsigned(*)[5] > (
        static_cast<void*>(p_first_membership)
        )
    );



-Tom=E1s

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Tom s" <NULL@NULL.NULL>
Date: Fri, 24 Mar 2006 19:56:27 CST
Raw View
> Then the type of this expression is not "unsigned (*)[5]", but
> "unsigned *".

I found a solution. Use:

    new unsigned[1][5]

instead of:

    new unsigned[5]


Now the following is okay:

void Array()
{
    unsigned (*p_numbers)[5] = new unsigned[1][5];

    (*p_numbers)[0] = 5;

    (*p_numbers)[1] = 6;

    delete [] p_numbers;
}

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alfps@start.no ("Alf P. Steinbach")
Date: Sat, 25 Mar 2006 01:56:06 GMT
Raw View
* NULL@NULL.NULL:
> For argument's sake, let's say we have the following function which we want
> to invoke:
>
> void ProcessFiveMemberships( unsigned (&memberships)[5] );
>
>
> If "new" is used to allocate an array, as follows:
>
>     new unsigned[5];
>
> Then the type of this expression is not "unsigned (*)[5]", but "unsigned *".
>
> My first question is, Why was this made so?

Most practical; usually the array size is determined at run-time.


> It would make more sense to me
> to return a pointer to an array of five objects, rather than a pointer to
> one sole object.

Then J&W Pascal is the language for you. ;-)


> We want to invoke "ProcessFiveMemberships". The following is ill-formed:
>
> void ProcessFiveMemberships( unsigned (&memberships)[5] )
> {
>     //Empty function body
>
>     for (;;)
>     {
>         break;
>     }
> }
>
> int main()
> {
>     unsigned* p_first_membership = new unsigned[5];
>
>     ProcessFiveMemberships( *p_first_membership ); // type mismatch
>
>     delete [] p_first_membership;
> }
>
>
> Is there any perfectly legal, fully portable way of turning our "unsigned
> *" into an "unsigned (*)[5]"?

     void ProcessFiveMemberships( unsigned (&memberships)[5] )
     {
         for (;;) { memberships; break; }
     }

     int main()
     {
         typedef unsigned UnsignedArray5[5];

         UnsignedArray5* ua5 = new UnsignedArray5[1];

         ProcessFiveMemberships( *ua5 );

         delete[] ua5;
     }


> How about the two following methods:
>
>
> ProcessFiveMemberships(
>     *reinterpret_cast<unsigned (*)[5]>(p_first_membership)
>     );

Formally UB.


> or:
>
> ProcessFiveMemberships(
>     *static_cast< unsigned(*)[5] > (
>         static_cast<void*>(p_first_membership)
>         )
>     );

Not sure whether it's formally valid or not, but while it's in-practice
technically OK (except perhaps on AS400 or original ENIAC...) it's
ungood as software engineering practice.

If you want a fixed-size array, just wrap it in a struct.

You might also find it beneficial to check out the Boost array facilities.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in 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://www.comeaucomputing.com/csc/faq.html                      ]