Velocity Reviews > C++ > converting 'float (*)[4]' to 'const float**'

# converting 'float (*)[4]' to 'const float**'

mathieu
Guest
Posts: n/a

 09-14-2007
Hi,

I know I am doing something stupid here, but it's friday night and I
cannot see what is the issue here:

Thanks,
-Mathieu

#include <iostream>

void print(const float **a,unsigned int X,unsigned int Y)
{
for(unsigned int i=0; i < X; ++i)
for(unsigned int j=0; j < Y; ++j)
std::cout << a[i][j] << std::endl;
}

int main()
{
const unsigned int X = 2;
const unsigned int Y = 4;
static const float a[X][Y] = {
{10,9,380.033,17189.4, },
{16,10,308.615,17542.4, }
};

print((const float**)a,X,Y);

return 0;
}

Victor Bazarov
Guest
Posts: n/a

 09-14-2007
mathieu wrote:
> I know I am doing something stupid here, but it's friday night and I
> cannot see what is the issue here:
>
> Thanks,
> -Mathieu
>
> #include <iostream>
>
> void print(const float **a,unsigned int X,unsigned int Y)

This function expects 'a' to be an array of pointers to const float.

> {
> for(unsigned int i=0; i < X; ++i)
> for(unsigned int j=0; j < Y; ++j)
> std::cout << a[i][j] << std::endl;
> }
>
> int main()
> {
> const unsigned int X = 2;
> const unsigned int Y = 4;
> static const float a[X][Y] = {
> {10,9,380.033,17189.4, },
> {16,10,308.615,17542.4, }
> };
>
> print((const float**)a,X,Y);

Here you pass an _array_of_arrays_ *pretending* it's an array of
pointers. That's a VERY BAD IDEA(tm).

>
> return 0;
> }

What you _could_ do (not that it's a good idea, but still), is to
create an array of pointers and pass it into 'print':

const float *aa[] = { a[0], a[1] };
print(aa, X, Y);

V
--

Barry
Guest
Posts: n/a

 09-14-2007
mathieu wrote:
> Hi,
>
> I know I am doing something stupid here, but it's friday night and I
> cannot see what is the issue here:
>
> Thanks,
> -Mathieu
>
> #include <iostream>
>
> void print(const float **a,unsigned int X,unsigned int Y)
> {
> for(unsigned int i=0; i < X; ++i)
> for(unsigned int j=0; j < Y; ++j)
> std::cout << a[i][j] << std::endl;
> }
>
> int main()
> {
> const unsigned int X = 2;
> const unsigned int Y = 4;
> static const float a[X][Y] = {
> {10,9,380.033,17189.4, },
> {16,10,308.615,17542.4, }
> };
>
> print((const float**)a,X,Y);
>
> return 0;
> }
>

a better way to rewrite your program is

template <class T, unsigned X, unsigned Y>
void print(T const (&a)[X][Y])
{
}

--
Thanks
Barry

mathieu
Guest
Posts: n/a

 09-14-2007
On Sep 14, 5:42 pm, "Victor Bazarov" <(E-Mail Removed)> wrote:
> mathieu wrote:
> > I know I am doing something stupid here, but it's friday night and I
> > cannot see what is the issue here:

>
> > Thanks,
> > -Mathieu

>
> > #include <iostream>

>
> > void print(const float **a,unsigned int X,unsigned int Y)

>
> This function expects 'a' to be an array of pointers to const float.
>
>
>
> > {
> > for(unsigned int i=0; i < X; ++i)
> > for(unsigned int j=0; j < Y; ++j)
> > std::cout << a[i][j] << std::endl;
> > }

>
> > int main()
> > {
> > const unsigned int X = 2;
> > const unsigned int Y = 4;
> > static const float a[X][Y] = {
> > {10,9,380.033,17189.4, },
> > {16,10,308.615,17542.4, }
> > };

>
> > print((const float**)a,X,Y);

>
> Here you pass an _array_of_arrays_ *pretending* it's an array of
> pointers. That's a VERY BAD IDEA(tm).
>
>
>
> > return 0;
> > }

>
> What you _could_ do (not that it's a good idea, but still), is to
> create an array of pointers and pass it into 'print':
>
> const float *aa[] = { a[0], a[1] };
> print(aa, X, Y);

Waw, I never realized that before... Thanks a bunch for the lesson.
I'll work around the issue this way (Muuuuhahhahha):

#include <iostream>

template <typename T>
void print(const T a,unsigned int X,unsigned int Y)
{
for(unsigned int i=0; i < X; ++i)
for(unsigned int j=0; j < Y; ++j)
std::cout << a[i][j] << std::endl;
}

int main()
{
const unsigned int X = 2;
const unsigned int Y = 4;
static const float a[X][Y] = {
{10,9,380.033,17189.4, },
{16,10,308.615,17542.4, }
};

print(a,X,Y);

return 0;
}

Sorry

mathieu
Guest
Posts: n/a

 09-14-2007
On Sep 14, 6:01 pm, Barry <(E-Mail Removed)> wrote:
> mathieu wrote:
> > Hi,

>
> > I know I am doing something stupid here, but it's friday night and I
> > cannot see what is the issue here:

>
> > Thanks,
> > -Mathieu

>
> > #include <iostream>

>
> > void print(const float **a,unsigned int X,unsigned int Y)
> > {
> > for(unsigned int i=0; i < X; ++i)
> > for(unsigned int j=0; j < Y; ++j)
> > std::cout << a[i][j] << std::endl;
> > }

>
> > int main()
> > {
> > const unsigned int X = 2;
> > const unsigned int Y = 4;
> > static const float a[X][Y] = {
> > {10,9,380.033,17189.4, },
> > {16,10,308.615,17542.4, }
> > };

>
> > print((const float**)a,X,Y);

>
> > return 0;
> > }

>
> a better way to rewrite your program is
>
> template <class T, unsigned X, unsigned Y>
> void print(T const (&a)[X][Y])
> {
>
> }

Thanks Barry,

Why do you use a reference in this case since you know you are
passing a pointer-to-pointer ?

Thanks
-Mathieu

Barry
Guest
Posts: n/a

 09-14-2007
mathieu wrote:
> On Sep 14, 6:01 pm, Barry <(E-Mail Removed)> wrote:
>> mathieu wrote:
>>> Hi,
>>> I know I am doing something stupid here, but it's friday night and I
>>> cannot see what is the issue here:
>>> Thanks,
>>> -Mathieu
>>> #include <iostream>
>>> void print(const float **a,unsigned int X,unsigned int Y)
>>> {
>>> for(unsigned int i=0; i < X; ++i)
>>> for(unsigned int j=0; j < Y; ++j)
>>> std::cout << a[i][j] << std::endl;
>>> }
>>> int main()
>>> {
>>> const unsigned int X = 2;
>>> const unsigned int Y = 4;
>>> static const float a[X][Y] = {
>>> {10,9,380.033,17189.4, },
>>> {16,10,308.615,17542.4, }
>>> };
>>> print((const float**)a,X,Y);
>>> return 0;
>>> }

>> a better way to rewrite your program is
>>
>> template <class T, unsigned X, unsigned Y>
>> void print(T const (&a)[X][Y])
>> {
>>
>> }

>
> Thanks Barry,
>
> Why do you use a reference in this case since you know you are
> passing a pointer-to-pointer ?
>

it's reference to const T[X][Y],

a is a reference to array(with 2D [X][Y]) of const T

--
Thanks
Barry

Victor Bazarov
Guest
Posts: n/a

 09-14-2007
mathieu wrote:
> [..]
> template <typename T>
> void print(const T a,unsigned int X,unsigned int Y)

The top-level 'const' is superfluous. For an exercise, print out
'typeid(T).name()' and 'typeid(a).name()' inside the function.

> {
> for(unsigned int i=0; i < X; ++i)
> for(unsigned int j=0; j < Y; ++j)
> std::cout << a[i][j] << std::endl;
> }
>
> int main()
> {
> const unsigned int X = 2;
> const unsigned int Y = 4;
> static const float a[X][Y] = {
> {10,9,380.033,17189.4, },
> {16,10,308.615,17542.4, }
> };
>
> print(a,X,Y);
>
> return 0;
> }

V
--

James Kanze
Guest
Posts: n/a

 09-15-2007
On Sep 14, 6:26 pm, "Victor Bazarov" <(E-Mail Removed)> wrote:
> mathieu wrote:
> > [..]
> > template <typename T>
> > void print(const T a,unsigned int X,unsigned int Y)

> The top-level 'const' is superfluous. For an exercise, print
> out 'typeid(T).name()' and 'typeid(a).name()' inside the
> function.

Not always. It's ignored by typeid, and when considering the
function *declaration* (i.e. f(int); and f( int const ); declare
the same function), but it *is* significant in the function
body.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Barry
Guest
Posts: n/a

 09-15-2007
mathieu wrote:
> On Sep 14, 6:01 pm, Barry <(E-Mail Removed)> wrote:
>> mathieu wrote:
>>> Hi,
>>> I know I am doing something stupid here, but it's friday night and I
>>> cannot see what is the issue here:
>>> Thanks,
>>> -Mathieu
>>> #include <iostream>
>>> void print(const float **a,unsigned int X,unsigned int Y)
>>> {
>>> for(unsigned int i=0; i < X; ++i)
>>> for(unsigned int j=0; j < Y; ++j)
>>> std::cout << a[i][j] << std::endl;
>>> }
>>> int main()
>>> {
>>> const unsigned int X = 2;
>>> const unsigned int Y = 4;
>>> static const float a[X][Y] = {
>>> {10,9,380.033,17189.4, },
>>> {16,10,308.615,17542.4, }
>>> };
>>> print((const float**)a,X,Y);
>>> return 0;
>>> }

>> a better way to rewrite your program is
>>
>> template <class T, unsigned X, unsigned Y>
>> void print(T const (&a)[X][Y])
>> {
>>
>> }

>
> Thanks Barry,
>
> Why do you use a reference in this case since you know you are
> passing a pointer-to-pointer ?
>

Oh, my. I always don't get the idea of the OP

I meant you could pass the array, not casting it to float** then pass it

--
Thanks
Barry

James Kanze
Guest
Posts: n/a

 09-15-2007
On Sep 14, 6:10 pm, mathieu <(E-Mail Removed)> wrote:
> On Sep 14, 6:01 pm, Barry <(E-Mail Removed)> wrote:
> > mathieu wrote:
> > > I know I am doing something stupid here, but it's friday night and I
> > > cannot see what is the issue here:

> > > #include <iostream>

> > > void print(const float **a,unsigned int X,unsigned int Y)
> > > {
> > > for(unsigned int i=0; i < X; ++i)
> > > for(unsigned int j=0; j < Y; ++j)
> > > std::cout << a[i][j] << std::endl;
> > > }

> > > int main()
> > > {
> > > const unsigned int X = 2;
> > > const unsigned int Y = 4;
> > > static const float a[X][Y] = {
> > > {10,9,380.033,17189.4, },
> > > {16,10,308.615,17542.4, }
> > > };

> > > print((const float**)a,X,Y);

> > > return 0;
> > > }

> > a better way to rewrite your program is

> > template <class T, unsigned X, unsigned Y>
> > void print(T const (&a)[X][Y])
> > {
> > }

> Why do you use a reference in this case since you know you are
> passing a pointer-to-pointer ?

You're not passing a pointer to a pointer. First, because you
don't have a pointer to a pointer anywhere in your program;
that's why it wasn't working in the first place. You have an
array of arrays, which will convert implicitly to a pointer to
an array in many contexts (but not all), but never to a pointer
to a pointer (which would be an entirely different data
structure). Second, and that's the critical aspect here, when
binding to a reference, an array only converts implicitly to a
pointer if the reference type is pointer (and the results of the
conversion won't bind to a non-const reference). What happens
here is that the compiler does template argument deduction,
given an array float[2][4], deduces that T is float, X is 2
and Y is 4, instantiates the template with these arguments, and
then binds the array to the reference. The nice part about it
is that the compiler does all of the work; you don't have to
worry about passing the dimension arguments (and maybe getting
them wrong). The bad part about it is that the compiler can
only work with what it knows; you can only pass a C style array
(which hasn't been converted to a pointer), which means that the
dimensions must be compile time constants. Another potentially
bad aspect is that the compiler instantiates a different
function for each set of dimensions, which can lead to code
bloat (although that's almost certainly not an issue for such a
small function as this).

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post 'Captain' Kirk DeHaan Firefox 4 12-17-2004 05:50 PM Paddy McCarthy VHDL 3 09-24-2004 05:34 PM TheRemedy ASP .Net 1 09-07-2004 09:55 AM Martin Geers Firefox 1 07-17-2004 01:11 AM Maria Firefox 1 04-10-2004 05:10 PM