468,484 Members | 1,540 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,484 developers. It's quick & easy.

finding matrix transpose - why doesn't it work when passing pointer argument?

1
Hi

I'm adapting some code I've written using 2d arrays (to represent matrices) to handle large arrays such that double matrix[][] goes to double **matrix and then I'm using malloc.

It seems to work fine for part of my program up to where I have to find the matrix transpose at which point it does something I don't understand. I've taken that bit of code out and run it by itself (included below), get the same problem... which is that the input matrix is getting modified when the function is called, here's an example for a test 3 by 3:
The input is:in[0][0] = 10.000000
in[0][1] = 10.000000
in[0][2] = 10.000000
in[1][0] = 5.000000
in[1][1] = 5.000000
in[1][2] = 5.000000
in[2][0] = 3.333333
in[2][1] = 3.333333
in[2][2] = 3.333333

but after being passed to find_transpose is comes out as:in[0][0] = 10.000000
in[0][1] = 10.000000
in[0][2] = 10.000000
in[1][0] = 10.000000
in[1][1] = 5.000000
in[1][2] = 10.000000
in[2][0] = 3.333333
in[2][1] = 3.333333
in[2][2] = 10.000000

and the actual transpose output is:
out[0][0] = 10.000000
out[0][1] = 10.000000
out[0][2] = 10.000000
out[1][0] = 10.000000
out[1][1] = 5.000000
out[1][2] = 3.333333
out[2][0] = 10.000000
out[2][1] = 10.000000
out[2][2] = 10.000000

I really don't understand why!?
Can anyone help??

Thanks
jbd


nt find_transpose(int n, double **a, double **b)
{
int i,j;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
b[i][j] = a[i][j];
}
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
b[i][j] = a[j][i];
}

}


int main (void)
{

int i, j, p=3;
double **in, **out;

in = malloc(p * sizeof(int *));
out = malloc(p * sizeof(int *));

for (i=0; i<p; i++){
in[i]= malloc(p * sizeof(int *));
out[i]= malloc(p * sizeof(int *));}

for (i=0; i<p; i++)
{
for (j=0; j<p; j++)
{in[i][j]= 10./(i+1);
printf("in[%i][%i] = %f\n", i, j, in[i][j]);
}
}

find_transpose(p, in, out);

for (i=0; i<p; i++)
{
for (j=0; j<p; j++)
printf("in[%i][%i] = %f\n", i, j, in[i][j]);
}

for (i=0; i<p; i++)
{
for (j=0; j<p; j++)
printf("out[%i][%i] = %f\n", i, j, out[i][j]);
}

return 0;
}
Feb 7 '08 #1
2 2435
hdanw
61
Hi



[qoute]
int find_transpose(int n, double **a, double **b)
{
int i,j;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
b[i][j] = a[i][j];
}
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
b[i][j] = a[j][i];
}
}
[/qoute]
Did you compile this?
The first loop is useless, the intire contents are over written by the second loop.
Also need to return a val since you said it would return one, ore declare the function void.

[qoute]
Expand|Select|Wrap|Line Numbers
  1. double **in, **out;
  2.  
  3. in = malloc(p * sizeof(int *));
  4. out = malloc(p * sizeof(int *));
  5.  
[/qoute]

This is not currently a problem, but you are mixing your pointers up.

Dont declare it as a pointer to a double unless it is. What you have is pointers to ints.

[qoute]
Expand|Select|Wrap|Line Numbers
  1. int **in, **out;
  2.  
[/qoute]

And you ought to cast them so :
[qoute]
Expand|Select|Wrap|Line Numbers
  1. in =  ( int ** ) malloc(p * sizeof(int *));
  2. out =( int ** ) malloc(p * sizeof(int *));
  3.  
[/qoute]

Again for the rows
[qoute]
Expand|Select|Wrap|Line Numbers
  1. for (i=0; i<p; i++){
  2. in[i]= malloc(p * sizeof(int *));
  3. out[i]= malloc(p * sizeof(int *));}
  4.  
[/qoute]

Should be

[qoute]
Expand|Select|Wrap|Line Numbers
  1. for (i=0; i<p; i++){
  2. in[i]= ( int * ) malloc(p * sizeof(int *));
  3. out[i]= ( int * ) malloc(p * sizeof(int *));}
  4.  
[/qoute]


I would suggest getting rid og malloc alltogether:

Expand|Select|Wrap|Line Numbers
  1.  //in = malloc(p * sizeof(int *));
  2.   in = new int*[p];
  3.  
  4. //out = malloc(p * sizeof(int *));
  5.  out = new int*[p];
  6.  
  7. for (i=0; i<p; i++){
  8.  
  9. // in[i]= malloc(p * sizeof(int *));
  10.    in[i] = new int[p];
  11.  
  12. //out[i]= malloc(p * sizeof(int *));
  13.   out[i] = new int[p];
  14.  
  15. }
  16.  
  17.  
After compileing this, it works fine.
Feb 8 '08 #2
weaknessforcats
9,207 Expert Mod 8TB
There are no multi-dimensional arrays in C or C++.

You might read this:
First, there are only one-dimensional arrays in C or C++. The number of elements in put between brackets:
Expand|Select|Wrap|Line Numbers
  1. int array[5];
  2.  
That is an array of 5 elements each of which is an int.

Expand|Select|Wrap|Line Numbers
  1. int array[];
  2.  
won't compile. You need to declare the number of elements.

Second, this array:
Expand|Select|Wrap|Line Numbers
  1. int array[5][10];
  2.  
is still an array of 5 elements. Each element is an array of 10 int.

Expand|Select|Wrap|Line Numbers
  1. int array[5][10][15];
  2.  
is still an array of 5 elements. Each element is an array of 10 elements where each element is an array of 15 int.


Expand|Select|Wrap|Line Numbers
  1. int array[][10];
  2.  
won't compile. You need to declare the number of elements.

Third, the name of an array is the address of element 0
Expand|Select|Wrap|Line Numbers
  1. int array[5];
  2.  
Here array is the address of array[0]. Since array[0] is an int, array is the address of an int. You can assign the name array to an int*.

Expand|Select|Wrap|Line Numbers
  1. int array[5][10];
  2.  
Here array is the address of array[0]. Since array[0] is an array of 10 int, array is the address of an array of 10 int. You can assign the name array to a pointer to an array of 10 int:
Expand|Select|Wrap|Line Numbers
  1. int array[5][10];
  2.  
  3. int (*ptr)[10] = array;
  4.  
Fourth, when the number of elements is not known at compile time, you create the array dynamically:

Expand|Select|Wrap|Line Numbers
  1. int* array = new int[value];
  2. int (*ptr)[10] = new int[value][10];
  3. int (*ptr)[10][15] = new int[value][10][15];
  4.  
In each case value is the number of elements. Any other brackets only describe the elements.

Using an int** for an array of arrays is incorrect and produces wrong answers using pointer arithmetic. The compiler knows this so it won't compile this code:

Expand|Select|Wrap|Line Numbers
  1. int** ptr = new int[value][10];    //ERROR
  2.  
new returns the address of an array of 10 int and that isn't the same as an int**.

Likewise:
Expand|Select|Wrap|Line Numbers
  1. int*** ptr = new int[value][10][15];    //ERROR
  2.  
new returns the address of an array of 10 elements where each element is an array of 15 int and that isn't the same as an int***.

With the above in mind this array:
Expand|Select|Wrap|Line Numbers
  1. int array[10] = {0,1,2,3,4,5,6,7,8,9};
  2.  
has a memory layout of

0 1 2 3 4 5 6 7 8 9

Wheras this array:
Expand|Select|Wrap|Line Numbers
  1. int array[5][2] = {0,1,2,3,4,5,6,7,8,9};
  2.  
has a memory layout of

0 1 2 3 4 5 6 7 8 9

Kinda the same, right?

So if your disc file contains

0 1 2 3 4 5 6 7 8 9

Does it make a difference wheher you read into a one-dimensional array or a two-dimensional array? No.

Therefore, when you do your read use the address of array[0][0] and read as though you have a
one-dimensional array and the values will be in the correct locations.
Feb 8 '08 #3

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

7 posts views Thread by sangeetha | last post: by
8 posts views Thread by Klaas Vantournhout | last post: by
2 posts views Thread by DarrenWeber | last post: by
reply views Thread by DarrenWeber | last post: by
8 posts views Thread by Matt | last post: by
12 posts views Thread by Nezhate | last post: by
275 posts views Thread by Astley Le Jasper | last post: by
2 posts views Thread by gieforce | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.