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

Discussion in 'C++' started by mathieu, Sep 14, 2007.

  1. mathieu

    mathieu Guest

    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[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;
    }
    mathieu, Sep 14, 2007
    #1
    1. Advertising

  2. 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[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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Sep 14, 2007
    #2
    1. Advertising

  3. mathieu

    Barry Guest

    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[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
    Barry, Sep 14, 2007
    #3
  4. mathieu

    mathieu Guest

    On Sep 14, 5:42 pm, "Victor Bazarov" <> 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[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[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, Sep 14, 2007
    #4
  5. mathieu

    mathieu Guest

    On Sep 14, 6:01 pm, Barry <> 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[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
    mathieu, Sep 14, 2007
    #5
  6. mathieu

    Barry Guest

    mathieu wrote:
    > On Sep 14, 6:01 pm, Barry <> 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[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],
    read the declaration like this:

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


    --
    Thanks
    Barry
    Barry, Sep 14, 2007
    #6
  7. 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[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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Sep 14, 2007
    #7
  8. mathieu

    James Kanze Guest

    On Sep 14, 6:26 pm, "Victor Bazarov" <> 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:
    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
    James Kanze, Sep 15, 2007
    #8
  9. mathieu

    Barry Guest

    mathieu wrote:
    > On Sep 14, 6:01 pm, Barry <> 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[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
    Barry, Sep 15, 2007
    #9
  10. mathieu

    James Kanze Guest

    On Sep 14, 6:10 pm, mathieu <> wrote:
    > On Sep 14, 6:01 pm, Barry <> 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[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:
    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
    James Kanze, Sep 15, 2007
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. bd
    Replies:
    0
    Views:
    621
  2. Replies:
    2
    Views:
    9,007
    Heinz Ozwirk
    Aug 9, 2006
  3. Replies:
    11
    Views:
    1,101
  4. Javier
    Replies:
    2
    Views:
    559
    James Kanze
    Sep 4, 2007
  5. Carsten Fuchs
    Replies:
    45
    Views:
    1,535
    James Kanze
    Oct 8, 2009
Loading...

Share This Page