473,322 Members | 1,778 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

2d array A[][] is the same as **A, right?

I'm getting an error when using a C program that accepts **float as
arguments in my C++ code. Here the code (short):

float A[3][3] = {0,0,0,1,2,0,3,4,0};
float W[3] = {0,0,0};
float V[3][3] = {0,0,0,0,0,0,0,0,0};

svdcmp(A,2,2,W,V);

where the function svdcmp is void svdcmp(float **a, int m, int n, float
w[], float **v).

The compiler (MSVC++) message is:
Error C2664: 'svdcmp' : cannot convert parameter 1 from 'float [3][3]'
to 'float ** '. Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast

I'm sure I'm making a blunder somewhere but it's so long since I've
used either C or C++...! Thanks for any help.

Jul 22 '05 #1
6 1914
<sp******@yahoo.com> wrote...
I'm getting an error when using a C program that accepts **float as
arguments in my C++ code. Here the code (short):

float A[3][3] = {0,0,0,1,2,0,3,4,0};
float W[3] = {0,0,0};
float V[3][3] = {0,0,0,0,0,0,0,0,0};

svdcmp(A,2,2,W,V);

where the function svdcmp is void svdcmp(float **a, int m, int n, float
w[], float **v).

The compiler (MSVC++) message is:
Error C2664: 'svdcmp' : cannot convert parameter 1 from 'float [3][3]'
to 'float ** '. Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast

I'm sure I'm making a blunder somewhere but it's so long since I've
used either C or C++...! Thanks for any help.


A two-dimensional array of T (T [N][M]) is not convertible to a pointer
to a pointer to T. Period.

Do not do reinterpret_cast either because it won't work. The types do
_not_ have the same data layout in memory. The only thing that is kind
of similar is that you can use operator[] on both, and the resulting
type allows you to use operator[] again, and the result is T&. But the
main difference is that the former type yields 'array of T' when you
use operator[], and the latter yields 'a pointer to T'.

If you have control over how 'svdcmp' is written, and you want to keep
it working for both T** and T[][], make two templates out of it. One
will have T[N][M] as the argument type, the other will have T**.

If you don't have control over 'svdcmp', and you just have to convert
your arrays into a pointer to pointers, then you'll need to create some
temporary arrays of pointers and pass them:

float A[3][3] = { ...
float V[3][3] = { ...

float *pA[] = { &A[0][0], &A[1][0], &A[2][0] };
float *pV[] = { &V[0][0], &V[1][0], &V[2][0] };

svdcmp(pA,2,2,W,pV);

Now, without knowing more I can't vouch for the functionality being up
to your needs, but it should at least give you an idea.

V
Jul 22 '05 #2

<sp******@yahoo.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
I'm getting an error when using a C program that accepts **float as
arguments in my C++ code. Here the code (short):

float A[3][3] = {0,0,0,1,2,0,3,4,0};
float W[3] = {0,0,0};
float V[3][3] = {0,0,0,0,0,0,0,0,0};

svdcmp(A,2,2,W,V);

where the function svdcmp is void svdcmp(float **a, int m, int n, float
w[], float **v).

The compiler (MSVC++) message is:
Error C2664: 'svdcmp' : cannot convert parameter 1 from 'float [3][3]'
to 'float ** '. Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast

I'm sure I'm making a blunder somewhere but it's so long since I've
used either C or C++...! Thanks for any help.


No, no no 2D array is not the same as a pointer to pointer - think of it
this way, an array is a contiguous set of data, so declaring float[3][3]
will occupy 3*3*sizeof(float) contigous bytes of memory. Pointers can point
*anywhere* and it is likely that they will if they were allocated at
different points in the program.
Allan
Jul 22 '05 #3

Victor Bazarov wrote:
...
If you have control over how 'svdcmp' is written, and you want to keep it working for both T** and T[][], make two templates out of it. One
will have T[N][M] as the argument type, the other will have T**.
...


Ah, thanks for the tips. I do have the source code for svdcmp() - I'd
like to modify it to accept *a (much more convenient) rather than **a
or a[][]. Just a sanity check - in the code wherever it says a[j][k]
then I need to change this to a[j*N+k] (or a[k*N+j], whatever you know
what I mean :) where N is the length of that dimension.

Jul 22 '05 #4
you only need a single pointer, and then you can access it however u
like.

#define WIDTH 5
#define HEIGHT 5

#define ACCESS(ptr, x, y) (ptr[(y*WIDTH)+x])

float array[WIDTH][HEIGHT] = { .... };
float *parray = array;

ACCESS(parry, 1, 1); // same as array[1][1]

Jul 22 '05 #5
In message <7s********************@comcast.com>, Victor Bazarov
<v.********@comAcast.net> writes
<sp******@yahoo.com> wrote...
I'm getting an error when using a C program that accepts **float as
arguments in my C++ code. Here the code (short):

float A[3][3] = {0,0,0,1,2,0,3,4,0};
float W[3] = {0,0,0};
float V[3][3] = {0,0,0,0,0,0,0,0,0};

svdcmp(A,2,2,W,V);

where the function svdcmp is void svdcmp(float **a, int m, int n, float
w[], float **v).

The compiler (MSVC++) message is:
Error C2664: 'svdcmp' : cannot convert parameter 1 from 'float [3][3]'
to 'float ** '. Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast

I'm sure I'm making a blunder somewhere but it's so long since I've
used either C or C++...! Thanks for any help.
A two-dimensional array of T (T [N][M]) is not convertible to a pointer
to a pointer to T. Period.

Do not do reinterpret_cast either because it won't work. The types do
_not_ have the same data layout in memory. The only thing that is kind
of similar is that you can use operator[] on both, and the resulting
type allows you to use operator[] again, and the result is T&. But the
main difference is that the former type yields 'array of T' when you
use operator[], and the latter yields 'a pointer to T'.

If you have control over how 'svdcmp' is written, and you want to keep
it working for both T** and T[][], make two templates out of it. One
will have T[N][M] as the argument type, the other will have T**.


Better still, define a template "matrix traits" class which encapsulates
the concept of Matrix and provides typedefs for things like value_type
and reference, and static functions for element access and size, and
specialise that for different argument types. Then template svdcmp on
generic Matrix types deduced from its arguments. Now you can add new
Matrix representations without having to make any changes to the code of
svdcmp.

// Untested code

template <class M>
struct MatrixTraits
{
/* assume that by default this will be instanced with M as some kind of
Matrix class which already provides all the needed functionality:
*/
typedef M matrix_type;
typedef typename M::value_type value_type;
typedef typename M::reference reference;
static reference element(matrix_type & m, size_t i, size_t j)
{ return m(i, j); }
static value_type element(matrix_type const & m, size_t i, size_t j)
{ return m(i, j); }
static size_t width(matrix_type & m) { return m.width(); }
static size_t height(matrix_type & m) { return m.height(); }
// etc...
};

// specialise for array of array
template <class T, size_t M, size_t N>
struct MatrixTraits <T[M][N]>
{
typedef T value_type;
typedef T & reference;
typedef T matrix_type[M][N];
static reference element(matrix_type & m, size_t i, size_t j)
{ return m[i][j]; }
static value_type element(matrix_type const & m, size_t i, size_t j)
{ return m[i][j]; }
static size_t width(matrix_type & m) { return M; }
static size_t height(matrix_type & m) { return N; }
// etc...
};

typedef typename M::value_type value_type;
static value_type element(M & m, size_T i, size_t j) { return m(i, j); }
static size_t width(M & m) { return m.width(); }
static size_t height(M & m) { return m.height(); }
// etc...
};

template <class A, class V, class W>
void svdcmp(A & a, V & v, W & w)
{
typedef MatrixTraits<A> at;
typedef MatrixTraits<V> vt;
typedef MatrixTraits<W> wt;

size_t const m = at::width(a);
size_t const n = at::height(a);
for (size_t i = 0; i<m; ++i)
for (size_t j = 0; i<n; ++i)
{
at::value_type a_ij = at::element(a, i, j);
/etc.../
}
}

Or something like that.

If you don't have control over 'svdcmp', and you just have to convert
your arrays into a pointer to pointers, then you'll need to create some
temporary arrays of pointers and pass them:

float A[3][3] = { ...
float V[3][3] = { ...

float *pA[] = { &A[0][0], &A[1][0], &A[2][0] };
float *pV[] = { &V[0][0], &V[1][0], &V[2][0] };

svdcmp(pA,2,2,W,pV);

Now, without knowing more I can't vouch for the functionality being up
to your needs, but it should at least give you an idea.

V


--
Richard Herring
Jul 22 '05 #6
[reposted, less scrambled formatting :-( ]
In message <7s********************@comcast.com>, Victor Bazarov
<v.********@comAcast.net> writes
<sp******@yahoo.com> wrote...
I'm getting an error when using a C program that accepts **float as
arguments in my C++ code. Here the code (short):

float A[3][3] = {0,0,0,1,2,0,3,4,0};
float W[3] = {0,0,0};
float V[3][3] = {0,0,0,0,0,0,0,0,0};

svdcmp(A,2,2,W,V);

where the function svdcmp is void svdcmp(float **a, int m, int n, float
w[], float **v).

The compiler (MSVC++) message is:
Error C2664: 'svdcmp' : cannot convert parameter 1 from 'float [3][3]'
to 'float ** '. Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast

I'm sure I'm making a blunder somewhere but it's so long since I've
used either C or C++...! Thanks for any help.
A two-dimensional array of T (T [N][M]) is not convertible to a pointer
to a pointer to T. Period.

Do not do reinterpret_cast either because it won't work. The types do
_not_ have the same data layout in memory. The only thing that is kind
of similar is that you can use operator[] on both, and the resulting
type allows you to use operator[] again, and the result is T&. But the
main difference is that the former type yields 'array of T' when you
use operator[], and the latter yields 'a pointer to T'.

If you have control over how 'svdcmp' is written, and you want to keep
it working for both T** and T[][], make two templates out of it. One
will have T[N][M] as the argument type, the other will have T**.


Better still, define a template "matrix traits" class which encapsulates
the concept of Matrix and provides typedefs for things like value_type
and reference, and static functions for element access and size, and
specialise that for different argument types. Then template svdcmp on
generic Matrix types deduced from its arguments. Now you can add new
Matrix representations without having to make any changes to the code of
svdcmp.

// Untested code

template <class M>
struct MatrixTraits
{
/* assume that by default this will be instanced with M as some kind of Matrix class
which already provides all the needed functionality:
*/
typedef M matrix_type;
typedef typename M::value_type value_type;
typedef typename M::reference reference;
static reference element(matrix_type & m, size_t i, size_t j)
{ return m(i, j); }
static value_type element(matrix_type const & m, size_t i, size_t j)
{ return m(i, j); }
static size_t width(matrix_type & m) { return m.width(); }
static size_t height(matrix_type & m) { return m.height(); }
// etc...
};

// specialise for array of array
template <class T, size_t M, size_t N>
struct MatrixTraits <T[M][N]>
{
typedef T value_type;
typedef T & reference;
typedef T matrix_type[M][N];
static reference element(matrix_type & m, size_t i, size_t j)
{ return m[i][j]; }
static value_type element(matrix_type const & m, size_t i, size_t j)
{ return m[i][j]; }
static size_t width(matrix_type & m) { return M; }
static size_t height(matrix_type & m) { return N; }
// etc...
};
template <class A, class V, class W>
void svdcmp(A & a, V & v, W & w)
{
typedef MatrixTraits<A> at;
typedef MatrixTraits<V> vt;
typedef MatrixTraits<W> wt;

size_t const m = at::width(a);
size_t const n = at::height(a);
for (size_t i = 0; i<m; ++i)
for (size_t j = 0; i<n; ++i)
{
at::value_type a_ij = at::element(a, i, j);
/etc.../
}
}

Or something like that.
If you don't have control over 'svdcmp', and you just have to convert
your arrays into a pointer to pointers, then you'll need to create some
temporary arrays of pointers and pass them:

float A[3][3] = { ...
float V[3][3] = { ...

float *pA[] = { &A[0][0], &A[1][0], &A[2][0] };
float *pV[] = { &V[0][0], &V[1][0], &V[2][0] };

svdcmp(pA,2,2,W,pV);

Now, without knowing more I can't vouch for the functionality being up
to your needs, but it should at least give you an idea.

V


--
Richard Herring
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

58
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of...
7
by: Bangalore | last post by:
Hi all, Plz clarify me, on the implementation of two or three dimensional array using overloaded operator. Thanks, in advance Bangalore
20
by: Pavel Stehule | last post by:
Hello, Is possible merge two arrays like array + array => array select array_append(array, array); ERROR: function array_append(integer, integer) does not exist
18
by: Joshua Neuheisel | last post by:
The following code compiles with gcc 3.2.2 and Visual C++ 6: #include <stdio.h> int main() { int a = {3, 4}; printf ("%d\n", 0); return 0; }
25
by: prashna | last post by:
Hi all, I have seen a piece of code(while doing code review) which declared an array of size 0.One of my friend told although it is not standard C,some compilers will support this..I am very...
24
by: Kavya | last post by:
int main (){ int a={{1,2,3},{4,5,6}}; int (*ptr)=a; /* This should be fine and give 3 as output*/ printf("%d\n",(*ptr)); ++ptr;
21
by: arnuld | last post by:
int main() { const char* arr = {"bjarne", "stroustrup", "c++"}; char* parr = &arr; } this gives an error: $ g++ test.cpp test.cpp: In function 'int main()': test.cpp:4: error: cannot...
17
by: =?Utf-8?B?U2hhcm9u?= | last post by:
Hi Gurus, I need to transfer a jagged array of byte by reference to unmanaged function, The unmanaged code should changed the values of the array, and when the unmanaged function returns I need...
18
by: mdh | last post by:
>From p112 ( K&R). Given an array declared as static char arr= { { 0,1,........},{0,1,.....}}; let arr be passed as an argument to f. f( int (*arr) ) {....} It is noted that the...
13
by: pereges | last post by:
I've an array : {100,20, -45 -345, -2 120, 64, 99, 20, 15, 0, 1, 25} I want to split it into two different arrays such that every number <= 50 goes into left array and every number 50 goes...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.