By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,084 Members | 1,207 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,084 IT Pros & Developers. It's quick & easy.

initialising array of unknown size (newbie)

P: n/a
Hi,

Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.

The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:

double C[A_rows][B_cols];

It looks like the compiler doesn't like this at all.

What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.

I would greatly appreciate any help.

Thanks
Adam
Oct 9 '08 #1
Share this Question
Share on Google+
33 Replies


P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.

The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:

double C[A_rows][B_cols];

It looks like the compiler doesn't like this at all.
There is nothing obviously wrong with the above. It would help to see
the code or at least the error message. In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables. Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.
Maybe. It is important to know if you can use C99. C99 (the current
standard) has some features that would make your task simpler. Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.

Have you seen the comp.lang.c FAQ? http://c-faq.com/

--
Ben.
Oct 9 '08 #2

P: n/a
On Oct 9, 11:57*am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Adam Chapman <adam.chap...@student.manchester.ac.ukwrites:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.
The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:
double C[A_rows][B_cols];
It looks like the compiler doesn't like this at all.

There is nothing obviously wrong with the above. *It would help to see
the code or at least the error message. *In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables. *Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.

Maybe. *It is important to know if you can use C99. *C99 (the current
standard) has some features that would make your task simpler. *Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.
I'm currently using the visual C++ 2008 compiler, but trying to keep
the code as standard as possible so I can use it on embedded
hardwarew, something like gumstix.
Have you seen the comp.lang.c FAQ? *http://c-faq.com/

--
Ben.
Thanks for te fast reply. Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;

int A[3][3]={1,2,3,4,5,6,7,8,9};
int B[3][3]={1,0,0,0,1,0,0,0,1};
int C = malloc(Arows * Bcols * sizeof(int));
main()
{
int row, col, i;

if (Acols!=Brows){
printf("Cannot compute; the number of columns of A
equals the number of rows of B");
for(;;);
return 0;
}
// Calculate Product
for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
C[row][col]=0;
for(i=0; i<Acols; i++)
{
*C[row][col]=C[row][col] + ((A[row][i])*(B[i]
[col])); }
}
}

for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
// printf("%1d ", C[row][col]);
}
printf("\n");
}
for(;;);
return 0;
}

I'm getting "error C2099: initializer is not a constant" from the line
"int C = malloc(Arows * Bcols * sizeof(int));"

As for the size of an array, I'd like to make my function capable of
any size (but not huge enough to fill all the memory), this is
requirement for my overall project. I know I haven't made the function
take inputs properly yet, I'm just getting it to work first.

Thanks
Adam
Oct 9 '08 #3

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
On Oct 9, 11:57*am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>Adam Chapman <adam.chap...@student.manchester.ac.ukwrites:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.
The problem is that the output array (C=A*B) has as many rows as A and
as many columns as B. I would think of initialising C with:
double C[A_rows][B_cols];
It looks like the compiler doesn't like this at all.

There is nothing obviously wrong with the above. *It would help to see
the code or at least the error message. *In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables. *Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.

Maybe. *It is important to know if you can use C99. *C99 (the current
standard) has some features that would make your task simpler. *Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.
I'm currently using the visual C++ 2008 compiler, but trying to keep
the code as standard as possible so I can use it on embedded
hardwarew, something like gumstix.
OK, then I think C99 is out. The very best portability is to be had
by aiming for the common intersection of C90 and C99. Essentially use
"old C" but avoid anything that interferes with (or is wrong in) the
new standard.
>Have you seen the comp.lang.c FAQ? *http://c-faq.com/

--
Ben.
best not to quote sig blocks. In fact, it is best to interleave your
reply with the quoted test so you can comment on specific parts.
Thanks for te fast reply. Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;
It is not a good idea to duplicate information. It is better to
define these in a manner that can be used to define the arrays.
Maybe:

#define AROWS 3
#define ACOLS 3

int A[AROWS][ACOLS] = {/*...*/};
>
int A[3][3]={1,2,3,4,5,6,7,8,9};
int B[3][3]={1,0,0,0,1,0,0,0,1};
int C = malloc(Arows * Bcols * sizeof(int));
Well there is no need for malloc here. C can be defined thus:

int C[3][3];

but you knew that! I wonder why you thought malloc was needed (I'll
explain the error later).
main()
This makes main and int rerturning function (correct) but in C99 this
"implicit int" declaration is not permitted. It is much better just
to write:

int main(void)
{
int row, col, i;

if (Acols!=Brows){
printf("Cannot compute; the number of columns of A
equals the number of rows of B");
for(;;);
Eh? If you are having the "my message disappears unless this is
there" then try to find the correct way to run your program so you can
see its output (I can't help with that -- I simply don't know).
return 0;
}
// Calculate Product
for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
C[row][col]=0;
for(i=0; i<Acols; i++)
{
*C[row][col]=C[row][col] + ((A[row][i])*(B[i]
[col]));
You just want to write C[row][col] = ... (i.e. no *). Also, C has a
+= operator that simplifies this sort of thing.
}
}
}

for(row=0; row<Arows; row++)
{
for(col=0; col<Bcols; col++)
{
// printf("%1d ", C[row][col]);
}
printf("\n");
}
As a general point, I'd break this up into functions. At the very
least, I'd have a print_matrix function, but I would also be tempted
to put the A[X][i] * B[i][X] sum calculation into a function.
for(;;);
return 0;
}

I'm getting "error C2099: initializer is not a constant" from the line
"int C = malloc(Arows * Bcols * sizeof(int));"
This is because, at file scope, an object can only be initialised with
a compiler-time constant -- something that the compiler can work out.
A call to malloc is not such a thing. In fact, for simplicity, C
rules out all function calls in such positions, even those that could
be worked out by the compiler.
As for the size of an array, I'd like to make my function capable of
any size (but not huge enough to fill all the memory), this is
requirement for my overall project. I know I haven't made the function
take inputs properly yet, I'm just getting it to work first.
The "any size" is not really enough. The issue is whether the sizes
can be know at compile time. It you need a set of very general array
manipulation functions, be prepared for a lot of learning. Have you
looked to see if there is some free code available to do what you
need?

If you want fully flexible array sizes and C90 code you may well be
better off using arrays of pointers rather than 2D arrays. If there
is any chance that you might have to change the representation of your
arrays from one form to the other (maybe because of performance
issues) it could well pay to start off to use an opaque type right
from the start:

struct matrix *matrix_create(size_t rows, size_t cols);
element_t matrix_get(struct matrix *m, size_t row, size_t col);
void matrix_set(struct matrix *m, size_t row, size_t col, element_t e);

so you can change all the details at will later on.

--
Ben.
Oct 9 '08 #4

P: n/a
On Oct 9, 1:49*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Adam Chapman <adam.chap...@student.manchester.ac.ukwrites:
On Oct 9, 11:57*am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Adam Chapman <adam.chap...@student.manchester.ac.ukwrites:
Im trying to migrate from programming in Matlab over to C. Im trying
to make a simple function to multiply one matrix by the other. I've
realised that C can't determine the size of a 2d array, so im
inputting the dimensions of those myself.
The problem is that the output array (C=A*B) has as many rows as Aand
as many columns as B. I would think of initialising C with:
double C[A_rows][B_cols];
It looks like the compiler doesn't like this at all.
There is nothing obviously wrong with the above. *It would help to see
the code or at least the error message. *In particular, the "best"
solution will be different if the dimensions are fixed and know at
compile time, are fixed but known only at run time, or if they are
true arbitrary variables. *Also, are the dimensions small?
What is the best way to define C? could i use a structure data type
for A and B, or do the dimensions of C need to be defined using
pointers? Perhaps the malloc function comes in somewhere.
Maybe. *It is important to know if you can use C99. *C99 (the current
standard) has some features that would make your task simpler. *Rather
the talk about both, it would be better to know what version of C you
are using/obliged to use.
I'm currently using the visual C++ 2008 compiler, but trying to keep
the code as standard as possible so I can use it on embedded
hardwarew, something like gumstix.

OK, then I think C99 is out. *The very best portability is to be had
by aiming for the common intersection of C90 and C99. *Essentially use
"old C" but avoid anything that interferes with (or is wrong in) the
new standard.
Have you seen the comp.lang.c FAQ? *http://c-faq.com/
--
Ben.

best not to quote sig blocks. *In fact, it is best to interleave your
reply with the quoted test so you can comment on specific parts.
Thanks for te fast reply. Here is my current code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;

It is not a good idea to duplicate information. *It is better to
define these in a manner that can be used to define the arrays.
Maybe:

#define AROWS 3
#define ACOLS 3

int A[AROWS][ACOLS] = {/*...*/};
int A[3][3]={1,2,3,4,5,6,7,8,9};
int B[3][3]={1,0,0,0,1,0,0,0,1};
int C = malloc(Arows ** Bcols * sizeof(int));

Well there is no need for malloc here. *C can be defined thus:

* int C[3][3];

but you knew that! *I wonder why you thought malloc was needed (I'll
explain the error later).
main()

This makes main and int rerturning function (correct) but in C99 this
"implicit int" declaration is not permitted. *It is much better just
to write:

int main(void)
{
* *int row, col, i;
* *if (Acols!=Brows){
* * * * * * * printf("Cannot compute; the number of columns of A
equals the number of rows of B");
* * * * * *for(;;);

Eh? *If you are having the "my message disappears unless this is
there" then try to find the correct way to run your program so you can
see its output (I can't help with that -- I simply don't know).
* * * * * *return 0;
* *}
* * // Calculate Product
* *for(row=0; row<Arows; row++)
* *{
* * * * * *for(col=0; col<Bcols; col++)
* * * * * *{
* * * * * * * * * * * * * *C[row][col]=0;
* * * * * * * * * *for(i=0; i<Acols; i++)
* * * * * * * * * *{
* * * * * * * * * * **C[row][col]=C[row][col] +((A[row][i])*(B[i]
[col]));

You just want to write C[row][col] = ... (i.e. no *). *Also, C has a
+= operator that simplifies this sort of thing.
* * * * * * * * * * * * * * * * * * * * * }
* * * * * *}
* *}
* *for(row=0; row<Arows; row++)
* *{
* * * * * *for(col=0; col<Bcols; col++)
* * * * * *{
* * * * * *// * * *printf("%1d * ", C[row][col]);
* * * * * *}
* * * * * *printf("\n");
* *}

As a general point, I'd break this up into functions. *At the very
least, I'd have a print_matrix function, but I would also be tempted
to put the A[X][i] * B[i][X] sum calculation into a function.
* *for(;;);
* *return 0;
}
I'm getting "error C2099: initializer is not a constant" from the line
"int C = malloc(Arows ** Bcols * sizeof(int));"

This is because, at file scope, an object can only be initialised with
a compiler-time constant -- something that the compiler can work out.
A call to malloc is not such a thing. *In fact, for simplicity, C
rules out all function calls in such positions, even those that could
be worked out by the compiler.
As for the size of an array, I'd like to make my function capable of
any size (but not huge enough to fill all the memory), this is
requirement for my overall project. I know I haven't made the function
take inputs properly yet, I'm just getting it to work first.

The "any size" is not really enough. *The issue is whether the sizes
can be know at compile time. *It you need a set of very general array
manipulation functions, be prepared for a lot of learning. *Have you
looked to see if there is some free code available to do what you
need?

If you want fully flexible array sizes and C90 code you may well be
better off using arrays of pointers rather than 2D arrays. *If there
is any chance that you might have to change the representation of your
arrays from one form to the other (maybe because of performance
issues) it could well pay to start off to use an opaque type right
from the start:

* struct matrix *matrix_create(size_t rows, size_t cols);
* element_t matrix_get(struct matrix *m, size_t row, size_t col);
* void matrix_set(struct matrix *m, size_t row, size_t col, element_t e);

so you can change all the details at will later on.

--
Ben.- Hide quoted text -

- Show quoted text -
Thanks. I want to eventually put the matrix multiplication function
into a header so it can be called from future scripts. The malloc was
for allocating memory for a matrix of size Arows*BCols, where Arows
and Bcols could be any size and are inputs to the function. Very
general I know, but still be useful when it finally works.
Looking at http://cboard.cprogramming.com/archi...p/t-57095.html
and http://www.hermetic.ch/cfunlib/arrays/arrays.htm, it looks very
hard. I will need to read about pointers over again (and probably
again and again!) but its all a good learnig experience I suppose.

Thanks for your time,
I appreciate it

Adam
Oct 9 '08 #5

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
On Oct 9, 1:49*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
<snip>
>best not to quote sig blocks. *In fact, it is best to interleave your
reply with the quoted test so you can comment on specific parts.
If you intend to post to technical groups like this it will really
help you if you copy the style of posting that is favoured here: snip
lots (but keep enough context so your message makes sense) and
interleave your reply with the quoted text you are replying to.

<snip>
>--
Ben.- Hide quoted text -
It will also help if it looks like you are listening to the advice!
Thanks. I want to eventually put the matrix multiplication function
into a header so it can be called from future scripts.
One usually puts function prototypes in header files. The code itself
is usually elsewhere and is said to be "linked" with the code that
calls it. For this sort of program it would be normal to write a
library of matrix functions to link with future programs.
The malloc was
for allocating memory for a matrix of size Arows*BCols, where Arows
and Bcols could be any size and are inputs to the function. Very
general I know, but still be useful when it finally works.
And it would have worked (nearly) if it had been in a function. In C
it does not help to rough things out one way and then wrap it all up
in a function because C has so many special rules. What can be done
in one place is often not allowed elsewhere. It *really* helps to
choose your functions first and sketch them out. If you don't, you
will probably have to rewrite everything when you come to "wrap it up
in a function" later.
Looking at http://cboard.cprogramming.com/archi...p/t-57095.html
and http://www.hermetic.ch/cfunlib/arrays/arrays.htm, it looks very
hard.
Yes it would. That is not good code. The variable names are hopeless
and there are no re-usable functions even for the most obviously
re-used code. The worst fault, though, is that that code does not
check any of the allocations and if you plan to write code for an
embedded device (I think you said this was your eventual target) then
this simply can't ignored.

Try reading:

http://www.eskimo.com/~scs/cclass/int/top.html

and look at Chapter 23. If you need some more basic stuff, try the
introduction to C:

http://www.eskimo.com/~scs/cclass/notes/top.html
I will need to read about pointers over again (and probably
again and again!) but its all a good learnig experience I suppose.
Note also that the code you cited does not really do 2D arrays. It
does arrays of pointers to arrays. This is just one way to represent
your data in "old C". The other is to pretend the array is flat (as
you seemed to be doing with your malloc call) and using a
multiplication to access the elements. Both have advantages and
disadvantages. It is not clear which will be better for you.

--
Ben.
Oct 9 '08 #6

P: n/a
On Oct 9, 3:32*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Adam Chapman <adam.chap...@student.manchester.ac.ukwrites:
On Oct 9, 1:49*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
<snip>
best not to quote sig blocks. *In fact, it is best to interleave your
reply with the quoted test so you can comment on specific parts.

If you intend to post to technical groups like this it will really
help you if you copy the style of posting that is favoured here: snip
lots (but keep enough context so your message makes sense) and
interleave your reply with the quoted text you are replying to.

<snip>
--
Ben.- Hide quoted text -

It will also help if it looks like you are listening to the advice!
Thanks. I want to eventually put the matrix multiplication function
into a header so it can be called from future scripts.

One usually puts function prototypes in header files. *The code itself
is usually elsewhere and is said to be "linked" with the code that
calls it. *For this sort of program it would be normal to write a
library of matrix functions to link with future programs.
The malloc was
for allocating memory for a matrix of size Arows*BCols, where Arows
and Bcols could be any size and are inputs to the function. Very
general I know, but still be useful when it finally works.

And it would have worked (nearly) if it had been in a function. *In C
it does not help to rough things out one way and then wrap it all up
in a function because C has so many special rules. *What can be done
in one place is often not allowed elsewhere. *It *really* helps to
choose your functions first and sketch them out. *If you don't, you
will probably have to rewrite everything when you come to "wrap it up
in a function" later.
Looking athttp://cboard.cprogramming.com/archive/index.php/t-57095.html
andhttp://www.hermetic.ch/cfunlib/arrays/arrays.htm, it looks very
hard.

Yes it would. *That is not good code. *The variable names are hopeless
and there are no re-usable functions even for the most obviously
re-used code. *The worst fault, though, is that that code does not
check any of the allocations and if you plan to write code for an
embedded device (I think you said this was your eventual target) then
this simply can't ignored.

Try reading:

*http://www.eskimo.com/~scs/cclass/int/top.html

and look at Chapter 23. *If you need some more basic stuff, try the
introduction to C:

*http://www.eskimo.com/~scs/cclass/notes/top.html
I will need to read about pointers over again (and probably
again and again!) but its all a good learnig experience I suppose.

Note also that the code you cited does not really do 2D arrays. *It
does arrays of pointers to arrays. *This is just one way to represent
your data in "old C". *The other is to pretend the array is flat (as
you seemed to be doing with your malloc call) and using a
multiplication to access the elements. *Both have advantages and
disadvantages. *It is not clear which will be better for you.

--
Ben.
Done it!
For anyone looking this up, here is the code i ended up with:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//double A[9], B[9];
int Arows=3, Acols=3, Brows=3, Bcols=3;
int A[3][3]={1,2,3,4,5,6,7,8,10};
int B[3][3]={9,8,7,6,5,4,3,2,1};
int **C;
int i, j, k, row, col;
main()
{
C=malloc(Arows * sizeof(int *));

for(i=0; i<Arows; i++)
{
C[i]=malloc(Bcols * sizeof(int));
for(j=0; j<Bcols; j++)
{
C[i][j]=0;

for(k=0; k<Acols; k++)
{
C[i][j]+=A[i][k]*B[k][j];

}
printf("%0d ", C[i][j]);
}
printf("\n");
}
for(;;);
return C;
}
Now I've got to set it up to take A and B as inputs and make the
function return C. Will post when I've got it

Adam
Oct 9 '08 #7

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
[...]
Done it!
For anyone looking this up, here is the code i ended up with:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//double A[9], B[9];
int Arows=3, Acols=3, Brows=3, Bcols=3;
int A[3][3]={1,2,3,4,5,6,7,8,10};
int B[3][3]={9,8,7,6,5,4,3,2,1};
You have 8 different occurences of the number 3 (not counting the two
in the initializers), and the relationship among the various 3s is not
sufficiently obvious. During maintenance, you could easily change one
of them and forget to change another one.

Also, Arows et al should really be constants. As written, you could
legally change their values; to understand your code, a reader has to
verify that you haven't done so.

Here's how I'd write the above. (A side note: "const" doesn't mean
"constant", it means read-only; "const int Arows = 3;" doesn't make
Arows a constant.)

#define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

Note that the extra braces explicitly show the individual rows of the
array.

(Actually, I might replace the #define's with this:
enum { AROWS=3, ACOLS=3, BROWS=3, BCOLS=3 };
but some consider that an abuse of the enum feature.)
>
int **C;
int i, j, k, row, col;
Why are all these global? Why not declare them inside main?
main()
Better: int main(void)
{
C=malloc(Arows * sizeof(int *));
malloc() can fail; it indicates this by returning a null pointer. You
should always check for this. If nothing else, you can just abort the
program.

And here's a useful idiom:

C = malloc(Arows * sizeof *C);

Even if the type of C changes (say, if you want arrays of doubles
rather than of ints), the call remains correct.
for(i=0; i<Arows; i++)
{
C[i]=malloc(Bcols * sizeof(int));
Again, you don't check whether the malloc call succeded.

C[i] = malloc(Bcols * sizeof *C[i]);
for(j=0; j<Bcols; j++)
{
C[i][j]=0;

for(k=0; k<Acols; k++)
{
C[i][j]+=A[i][k]*B[k][j];

}
printf("%0d ", C[i][j]);
}
printf("\n");
}
for(;;);
You know this is an infinite loop, right? Which means ...
return C;
.... that this return statement will never be executed.
}
Now I've got to set it up to take A and B as inputs and make the
function return C. Will post when I've got it
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 9 '08 #8

P: n/a
Thanks Keith, although your suggestions have brought up a lot of
errors.
Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Arows 3;
#define Acols 3;
#define Brows 3;
#define Bcols 3;
float A[Arows][Acols]={{1,2,3},{4,5,6},{7,8,9}};
float B[Brows][Bcols]={{9,8,7},{6,5,4},{3,2,1}};
float C;
main(){
C=mat_mult();
for(;;); // to stop display closing down (needs proper fix)

}
mat_mult()
{
float **C;
int i, j, k;
C = malloc(Arows * sizeof *C);

for(i=0; i<Arows; i++)
{
C[i] = malloc(Bcols * sizeof *C[i]);
for(j=0; j<Bcols; j++)
{
C[i][j]=0;

for(k=0; k<Acols; k++)
{
C[i][j]+=A[i][k]*B[k][j];

}
printf("%0f ", C[i][j]);
}
printf("\n");
}

return C;
}

#define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };
gives "error C2143: syntax error : missing ']' before ';' "

Also, I keep getting this warning: "warning C4013: 'mat_mult'
undefined; assuming extern returning int" from the line
C=mat_mult();
Sorry if I sound stupid. This is quite difficult for me to get my head
around

Adam
Oct 9 '08 #9

P: n/a
On October 9, 2008 15:11, in comp.lang.c, Adam Chapman
(ad**********@student.manchester.ac.uk) wrote:
Thanks Keith, although your suggestions have brought up a lot of
errors.
Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Arows 3;
Note what the macro Arows expands to
#define Acols 3;
Note what the macro Acols expands to
#define Brows 3;
Note what the macro Brows expands to
#define Bcols 3;
Note what the macro Bcols expands to
>

float A[Arows][Acols]={{1,2,3},{4,5,6},{7,8,9}};
Hand expanding the macros, this line reads
float A[3;][3;]={{1,2,3},{4,5,6},{7,8,9}};
Are you sure that you want this?
float B[Brows][Bcols]={{9,8,7},{6,5,4},{3,2,1}};
Hand expanding the macros, this line reads
float B[3;][3;]={{9,8,7},{6,5,4},{3,2,1}};
Again, are you certain that this is what you want?
float C;
main(){
At this point, the function mat_mult() has not been declared or defined. The
compiler will /assume/ that mat_mult() takes an unknown set of arguments,
and returns an integer. Is this what you want?
C=mat_mult();
OK, the integer returned by mat_mult() is now converted to a float.
for(;;); // to stop display closing down (needs proper fix)

}
mat_mult()
This is an error in C99 - you need to tell the compiler what the type is of
the return value. In previous levels of C, the default is an integer. So,
either you have a syntax error (in C99) or you are returning an integer (in
prior levels of C).
{
float **C;
Here, you define an automatic variable with the same name as a file-duration
static variable. /This/ local variable is the one that the function will
use.
int i, j, k;
C = malloc(Arows * sizeof *C);
Hmmmmm.....

I'll leave it to others to comment on the rest of /this code. There's
something very suspicious here, but I don't feel qualified enough to give
it the proper analysis.
>
for(i=0; i<Arows; i++)
{
C[i] = malloc(Bcols * sizeof *C[i]);
for(j=0; j<Bcols; j++)
{
C[i][j]=0;

for(k=0; k<Acols; k++)
{
C[i][j]+=A[i][k]*B[k][j];

}
printf("%0f ", C[i][j]);
}
printf("\n");
}

return C;
You defined C as a pointer to a pointer to a float.
However,
a) you defined the function as returning an integer (assuming < C99)
b) you convert the integer to a float in your main() function
Oops. A pointer is neither an integer, nor a float.
}

> #define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

gives "error C2143: syntax error : missing ']' before ';' "

Also, I keep getting this warning: "warning C4013: 'mat_mult'
undefined; assuming extern returning int" from the line
>C=mat_mult();

Sorry if I sound stupid. This is quite difficult for me to get my head
around

Adam
--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
Oct 9 '08 #10

P: n/a
>the function mat_mult() has not been declared or defined. The
compiler will /assume/ that mat_mult() takes an unknown set of arguments,
and returns an integer. Is this what you want?
Ah I see, i need

float mat_mult();

declared. This will make the output of mat_mult a float.
{
float **C;

Here, you define an automatic variable with the same name as a file-duration
static variable. /This/ local variable is the one that the function will
use.
Ok, so I changed all the "C's" in mat_mult to "d's", and deffined d
within the mat_mult function with "float **d".

So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

float mat_mult();

main(){
float C;
C=mat_mult();
printf("%f",C[0][0]);
for(;;);
}
mat_mult()
{
float **d;
int i, j, k;
d = malloc(Arows * sizeof *d);

for(i=0; i<Arows; i++)
{
d[i] = malloc(Bcols * sizeof *d[i] );
for(j=0; j<Bcols; j++)
{
d[i][j]=0;

for(k=0; k<Acols; k++)
{
d[i][j]+=A[i][k]*B[k][j];

}
printf("%0f ", d[i][j]);
}
printf("\n");
}
return d;
}

Still need to define the input type for mat_mult, but my main concern
is that I get errors with the printf in main(). It says " error C2109:
subscript requires array or pointer type". Im not sure if main has
seen the output as a 2d array.

Oct 9 '08 #11

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
[...]
So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

float mat_mult();
This declares that mat_mult takes an unspecified but fixed
number of arguments. If it takes no arguments, say so:

float mat_mult(void);

main(){
Make this:

int main(void) {

float C;
C=mat_mult();
Ok.
printf("%f",C[0][0]);
You just declared C as a float. Why are you trying to indix it as if
it were a two-dimensional array?
for(;;);
Why the infinite loop?
}
mat_mult()
Again, make this:

float mat_mult(void)

Incidentally, it usually makes more sense to use double rather than
float.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 9 '08 #12

P: n/a
(Oops - I mailed instead of posting - Apologies to adam and the rest of
c.l.c)

Posted as per personal dictum ("you post here, you read here")

On October 9, 2008 16:36, in comp.lang.c, Adam Chapman
(ad**********@student.manchester.ac.uk) wrote:
>>the function mat_mult() has not been declared or defined. The
compiler will /assume/ that mat_mult() takes an unknown set of arguments,
and returns an integer. Is this what you want?
Ah I see, i need

float mat_mult();

declared. This will make the output of mat_mult a float.
{
float **C;

Here, you define an automatic variable with the same name as a
file-duration static variable. /This/ local variable is the one thatthe
function will use.
Ok, so I changed all the "C's" in mat_mult to "d's", and deffined d
within the mat_mult function with "float **d".

So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

float mat_mult();

main(){
* * float C;
Here, C is declared and defined as a float

C=mat_mult();
printf("%f",C[0][0]);
Here, you code as if C were a two-dimensional array (with unknown
dimensions)

No.

Try
* printf("%f\n",C);

* * for(;;);
}
Prior to your main() function, you declared mat_mult() as returning a float.
Below, you define mat_mult() as returning an int.
mat_mult()
This should be...
* float mat_mult()
{

OK, I just don't have the words to explain how wrong this function is.

From your original main(), I presumed that you wanted the function to return
a single floatingpoint value, but on second-read, I see that you really
intend for the function to return an array of floatingpoint values.
However, you /really/ haven't coded that.

First off, in C, you cannot return an array. You can either return a struct
(or union) that /contains/ an array, or you can return a pointer to the
first element of an array. That's it.

Secondly, arrays are contigiously allocated space. Elements of an arrayof
* type name[size];
can either be referenced by
* name[index]
or
* *(name+index)

A two-dimensional array can be thought of as a one-dimensional array, each
element of which is a one-dimensional array.

So, elements of an array of
* type name[n_rows][n_cols];
can either be referenced as
* name[row][col]
or as
* *(name + (row * n_cols) + col)

See how, as a pointer expression, the compiler /needs/ to know the sizeof
the inner one-dimensional array?

Similarly, elements of an array of
* type name[n_pages][n_rows][n_cols];
can either be referenced as
* name[page][row][col]
or as
* *(name + (page * n_rows * n_cols) + (row * n_cols) + col)
OK, now in /your/ code below, you don't build a multi-dimensional array..
Instead, you build a *tree* of pointers. Since the dimensions are unknown
at compile time, compile-time shortcuts (like array subscripting) aren't
going to work. You have to dereference each pointer and pointer-to-pointer
to get to the data underneath.

I'm going to ignore a lot of things below (like testing malloc() for
success, and size mismatches, and the like) and try to cut to the heartof
the matter
float **d;
d is an unitialized pointer to a pointer to a float.
* * int i, j, k;
d = malloc(Arows * sizeof *d);
d now points to space for three pointers.
*d is permitted to be a pointer to a float
*
for(i=0; i<Arows; i++)
{
d[i] = malloc(Bcols * sizeof *d[i] );
Since you don't have multiple dimensions to contend with, you can get away
with
* d[i]
being equivalent to
* *(d+i)
This works for this code, here, but /will not/ work for your later use as
access to a multi-dimensional array

each of the three spaces that d can access now points to some space. The
size of the space allocated for each of those elements is three times the
size of a pointer-to-float (d is a pointer-to a pointer-to a float, so *d
resolves to be a pointer-to a float. Since *d is the same as *(d+0), and
*(d+0) is the same as d[0], then d[0] resolves to a pointer-to a float,and
consequently so does d[i].) This is important, because you asked malloc()
to allocate some space for you based on /this size/. You didn't get the
space for three floatingpoint numbers; you got what you asked for - the
space for three pointers.

for(j=0; j<Bcols; j++)
{
d[i][j]=0;
First off, you can't access your pointer-tree in this manner. It is nota
multi-dimensional array, but is a tree of pointers and
pointers-to-pointers.

Secondly, you haven't allocated space for the floatingpoint values yet,so
trying to assign anything other than a pointer value is futile and an
error.

Thirdly (and not too consequentially), 0 is not a floatingpoint value.
However 0.0 is. The good news is that, had the *left-hand-side of the
statement correctly resolved to a floatingpoint data type, C would have
converted your integer 0 to floatingpoint 0.0 for you.

for(k=0; k<Acols; k++)
{
d[i][j]+=A[i][k]*B[k][j];

}
printf("%0f * ", d[i][j]);
}
printf("\n");
}
return d;
No. You are returning a pointer. A pointer to an automatic variable that
disappears /with/ the return. You don't want to do this.
}

Still need to define the input type for mat_mult, but my main concern
is that I get errors with the printf in main(). It says " error C2109:
subscript requires array or pointer type". Im not sure if main has
seen the output as a 2d array.
See above
--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
Oct 9 '08 #13

P: n/a
On October 9, 2008 17:24, in comp.lang.c, Lew Pitcher
(lp******@teksavvy.com) wrote:
[snip]
Prior to your main() function, you declared mat_mult() as returning a
float. Below, you define mat_mult() as returning an int.
>mat_mult()

This should be...
float mat_mult()
>{
[snip]
>float **d;
[snip]
>return d;

No. You are returning a pointer.
Oops... The following is incorrect...
A pointer to an automatic variable that
disappears /with/ the return.
The pointer is pointing to valid malloc()ed memory. It won't disappear when
the function returns.
You don't want to do this.
>}

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
Oct 9 '08 #14

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
<snip>
So now I have

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
Just so I can improve my style, what was it about Keith Thompson
suggesting this that made you take note when you seemed ignore the
same suggestion from me several messages ago? :-)

<snip>
float **d;
int i, j, k;
d = malloc(Arows * sizeof *d);
You are heading into trouble here. It is very unwise to use both a 2D
array like A and B and an array of pointers like d. You will end up
with code that can't be combined in useful ways. The result of the
matrix multiply is in a different format (in C terms a different type)
to the data that is operates on. You would not, for example, be able
to multiply the result of a multiplication.

You should pick either the contiguous representation used for A and B
or the array of pointers representation used for d and not mix them.

--
Ben.
Oct 9 '08 #15

P: n/a
On October 9, 2008 16:36, in comp.lang.c, Adam Chapman
(ad**********@student.manchester.ac.uk) wrote:
[snip]
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
[snip]
mat_mult()
{
[snip]
}
OK, let's stop fiddling around and fix this thing.

Let's see if I can state your requirements for the mat_mult() function, and
then let's design and build it properly.

mat_mult() should dynamically allocate space for an array-multiply
resultset, and multiply two static, fixed-sized arrays, placing the results
into the dynamically allocted space. The function should return a pointer
to the results array to the caller, so that the results can be further
manipulated, and the array freed.

Does that sound like it?

If so, then we make some decisions:
1) mat_mult() will take no arguments, as its inputs are all statically
allocated, and of known fixed sizes
2) as C functions cannot return arrays without language trickery, the
function will return a pointer to the first element of the results array.
The caller will be responsible for determining the size of the array (the
size is fixed and known to the caller, so this shouldn't be a problem), and
must dispose of the array by use of a call to free() with the returned
pointer,
3) the function will return NULL on any failure,
3) the function will use malloc() to dynamically allocate space for the
results array. NULL from malloc() constitutes a failure condition.

So, at first try, we have a function like this....

float *mat_mult(void)
{
float *resultset;

/* matrix multiply A and B to result in resultset */
return resultset;
}

Now, let's fill in a bit of the logic. First, to allocate the result set
space

#define Arows 3
#define Acols 3

#include <stdlib.h>

float *mat_mult(void)
{
float *resultset;
/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our entire
results table. Now, let's initialize it */

/* matrix multiply A and B to result in resultset */

return resultset;
}
Now, add in some (unnecessary) logic to initialize the result set space

#define Arows 3
#define Acols 3

#include <stdlib.h>

float *mat_mult(void)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our entire
results table. Now, let's initialize it */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */

return resultset;
}
Now, add in the matrix multiplication logic

#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3

float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

#include <stdlib.h>

float *mat_mult(void)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our entire
results table. Now, let's initialize it */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}
Finally, add in your driver (in this case, main())

#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3

float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

#include <stdlib.h>

float *mat_mult(void)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our entire
results table. Now, let's initialize it */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}

#include <stdio.h>

int main(void)
{
float *Results;
int row, col;

/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult()) == NULL)
{
printf("Gaak - we ran into an error\n");
return EXIT_FAILURE;
}

/* Print out the result set */
for (row = 0; row < Arows; ++row)
{
printf("[%d]\t",row);
for (col = 0; col < Acols; ++col)
{
printf("%f\t",*(Results + (row * Acols) + col));
}
printf("*\n");
}
printf("End of results\n");

/* Free the allocated space */
free(Results);

return EXIT_SUCCESS;
}

HTH
--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
Oct 9 '08 #16

P: n/a
On Thu, 9 Oct 2008 12:11:51 -0700 (PDT), Adam Chapman
<ad**********@student.manchester.ac.ukwrote:
>Thanks Keith, although your suggestions have brought up a lot of
errors.
Here is my current code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Arows 3;
#define Acols 3;
#define Brows 3;
#define Bcols 3;
float A[Arows][Acols]={{1,2,3},{4,5,6},{7,8,9}};
float B[Brows][Bcols]={{9,8,7},{6,5,4},{3,2,1}};
float C;
main(){
This states that main returns int.
> C=mat_mult();
There is no prototype in scope for mat_mult. The compiler is required
to assume it returns int. The int value will be converted to match
the float type of C.
for(;;); // to stop display closing down (needs proper fix)
One possible way is to print a message telling the user to press enter
and using getchar to wait until then.
>
Where is the int that main should return?
>}
mat_mult()
This states that mat_mult returns int.
>{
float **C;
You do realize that this C hides the global C you defined above.
int i, j, k;
C = malloc(Arows * sizeof *C);

for(i=0; i<Arows; i++)
{
C[i] = malloc(Bcols * sizeof *C[i]);
for(j=0; j<Bcols; j++)
{
C[i][j]=0;

for(k=0; k<Acols; k++)
{
C[i][j]+=A[i][k]*B[k][j];

}
printf("%0f ", C[i][j]);
}
printf("\n");
}

return C;
Why did you ignore the diagnostic you compiler generated for this
statement? mat_mult is returning an int. C has type float**. The
two are incompatible.
>}

> #define AROWS 3
#define ACOLS 3
#define BROWS 3
#define BCOLS 3

int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

gives "error C2143: syntax error : missing ']' before ';' "
This message is probably from when your #define included the
semicolon.
>
Also, I keep getting this warning: "warning C4013: 'mat_mult'
undefined; assuming extern returning int" from the line
>C=mat_mult();
Where is the prototype that would tell the compiler what it needed to
know about mat_mult.

--
Remove del for email
Oct 9 '08 #17

P: n/a
OK, now let's improve on the mat_mult() function a bit...

On October 9, 2008 18:16, in comp.lang.c, Lew Pitcher
(lp******@teksavvy.com) wrote:
[snip]

#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3

float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

#include <stdlib.h>

float *mat_mult(void)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}
[snip]

Let's add in some new constraints/assumptions:

1) Both source matrices will have the same number of rows and columns
(we already have this assumption, but I didn't state it before)

2) The number of rows and columns will be dynamic, so that the matrix
multiply can be used on a variety of matrices

3) The two source matrices will be dynamic, so that we can use the function
on a variety of m*n matrices
So, we'll now change the mat_mult() function so that it takes as arguments
a) a pointer to the first element of the first source matrix,
b) a pointer to the first element of the second source matrix,
c) a count of the number of rows in the matrices, and
d) a count of the number of columns in the matrices
and we'll make the function use these values in its matrix multiply.

First off, we change the function so as to add the four new arguments...

#include <stdlib.h>

float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(Arows * Acols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < Arows; ++row)
{
for (col = 0; col < Acols; ++col)
{
*(resultset + (row * Acols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}
Next, change the code so that it uses the new nRows and nCols arguments
instead of the old Arows and Acols macros.

#include <stdlib.h>

float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = A[row][col]*B[row][col];
}
}
return resultset;
}
Next, change the function to use the two argument matrices

#include <stdlib.h>

float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) =
*(matrixA + (row * nCols) + col) *
*(matrixB + (row * nCols) + col);
}
}

return resultset;
}
Finally, let's add the driver again...

#include <stdlib.h>

float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) =
*(matrixA + (row * nCols) + col) *
*(matrixB + (row * nCols) + col);
}
}

return resultset;
}
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3

float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

#include <stdio.h>

int main(void)
{
float *Results;
int row, col;

/* Sanity check our array bounds */
if ((Arows != Brows) || (Acols != Bcols))
{
printf("Gaak - our arrays aren't of the same size\n");
return EXIT_FAILURE;
}

/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult(&A[0][0],&B[0][0],Arows,Acols)) == NULL)
{
printf("Gaak - we ran into an error\n");
return EXIT_FAILURE;
}

/* Print out the result set */
for (row = 0; row < Arows; ++row)
{
printf("[%d]\t",row);
for (col = 0; col < Acols; ++col)
{
printf("%f\t",*(Results + (row * Acols) + col));
}
printf("*\n");
}
printf("End of results\n");

/* Free the allocated space */
free(Results);

return EXIT_SUCCESS;
}

We could make some further "style" changes (optimizing some common
sub-expressions, making some allocation parameters more robust, etc.), but
we don't really have to. So, we're done this generalization.

Next change: multiply matrices of different sizes

HTH
--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
Oct 9 '08 #18

P: n/a
Thankyou all. Sorry if it seemed like i was ignoring, Im sure you know
how hard it is to take everything in when you are stressed and
confused!
>
* *#include <stdlib.h>

* *float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
* *{
* * *float *resultset;
* * *int row, col;

* * */* allocate space for the result set, point resultset at the space */
* * *if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
* * * *return NULL; /* first error condition */

* * */* at this point, resultset points at a space big enough for our
* * *entire
* * * * results table. Now, let's initialize it */
* * *for (row = 0; row < nRows; ++row)
* * *{
* * * *for (col = 0; col < nCols; ++col)
* * * *{
* * * * **(resultset + (row * nCols) + col) = 0.0;
* * * *}
* * * }

* * */* matrix multiply A and B to result in resultset */
* * *for (row = 0; row < nRows; ++row)
* * *{
* * * *for (col = 0; col < nCols; ++col)
* * * *{
* * * * * *(resultset + (row * nCols) + col) =
* * * * * * **(matrixA + (row * nCols) + col) *
* * * * * * **(matrixB + (row * nCols) + col);
* * * *}
* * * }

* * *return resultset;
* *}

* #define Arows 3
* #define Acols 3
* #define Brows 3
* #define Bcols 3

* float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
* float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

* #include <stdio.h>

* int main(void)
* {
* * float *Results;
* * int row, col;

* * /* Sanity check our array bounds */
* * if ((Arows != Brows) || (Acols != Bcols))
* * {
* * * printf("Gaak - our arrays aren't of the same size\n");
* * * return EXIT_FAILURE;
* * }

* * /* try matrix multiplication - exit EXIT_FAILURE on failure */
* * if ((Results = mat_mult(&A[0][0],&B[0][0],Arows,Acols)) == NULL)
* * {
* * * printf("Gaak - we ran into an error\n");
* * * return EXIT_FAILURE;
* * }

* * /* Print out the result set */
* * for (row = 0; row < Arows; ++row)
* * {
* * * printf("[%d]\t",row);
* * * for (col = 0; col < Acols; ++col)
* * * {
* * * * *printf("%f\t",*(Results + (row * Acols) + col));
* * * }
* * * printf("*\n");
* * }
* * printf("End of results\n");

* * /* Free the allocated space */
* * free(Results);

* * return EXIT_SUCCESS;
* }
When I try to compile this, i get " error C2440: '=' : cannot convert
from 'void *' to 'float *' " from the line
((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
The error is surely coming from the
resultset = malloc(nRows * nCols * sizeof(float))
part. My understanding is that before that particular line, resultset
is a pointer to a memory block big enough to hold a float.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)
Oct 10 '08 #19

P: n/a
Adam Chapman wrote:
Thankyou all. Sorry if it seemed like i was ignoring, Im sure you know
how hard it is to take everything in when you are stressed and
confused!
>>
#include <stdlib.h>

float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */

/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}

/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) =
*(matrixA + (row * nCols) + col) *
*(matrixB + (row * nCols) + col);
}
}

return resultset;
}

#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3

float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

#include <stdio.h>

int main(void)
{
float *Results;
int row, col;

/* Sanity check our array bounds */
if ((Arows != Brows) || (Acols != Bcols))
{
printf("Gaak - our arrays aren't of the same size\n");
return EXIT_FAILURE;
}

/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult(&A[0][0],&B[0][0],Arows,Acols)) == NULL)
{
printf("Gaak - we ran into an error\n");
return EXIT_FAILURE;
}

/* Print out the result set */
for (row = 0; row < Arows; ++row)
{
printf("[%d]\t",row);
for (col = 0; col < Acols; ++col)
{
printf("%f\t",*(Results + (row * Acols) + col));
}
printf("*\n");
}
printf("End of results\n");

/* Free the allocated space */
free(Results);

return EXIT_SUCCESS;
}

When I try to compile this, i get " error C2440: '=' : cannot convert
from 'void *' to 'float *' " from the line
>((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)

The error is surely coming from the
>resultset = malloc(nRows * nCols * sizeof(float))

part. My understanding is that before that particular line, resultset
is a pointer to a memory block big enough to hold a float.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)
malloc returns a void * which in C should convert to (alost) everything
automagically. It does not in C++ (it requres a cast, so it seems likely
you're operating your compiler in C++ mode.

Bye, Jojo
Oct 10 '08 #20

P: n/a
On Oct 10, 1:39*pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
Adam Chapman wrote:
Thankyou all. Sorry if it seemed like i was ignoring, Im sure you know
how hard it is to take everything in when you are stressed and
confused!
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;
/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */
/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) =
*(matrixA + (row * nCols) + col) *
*(matrixB + (row * nCols) + col);
}
}
return resultset;
}
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
#include <stdio.h>
int main(void)
{
float *Results;
int row, col;
/* Sanity check our array bounds */
if ((Arows != Brows) || (Acols != Bcols))
{
printf("Gaak - our arrays aren't of the same size\n");
return EXIT_FAILURE;
}
/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult(&A[0][0],&B[0][0],Arows,Acols)) == NULL)
{
printf("Gaak - we ran into an error\n");
return EXIT_FAILURE;
}
/* Print out the result set */
for (row = 0; row < Arows; ++row)
{
printf("[%d]\t",row);
for (col = 0; col < Acols; ++col)
{
printf("%f\t",*(Results + (row * Acols) + col));
}
printf("*\n");
}
printf("End of results\n");
/* Free the allocated space */
free(Results);
return EXIT_SUCCESS;
}
When I try to compile this, i get " error C2440: '=' : cannot convert
from 'void *' to 'float *' " from the line
((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
The error is surely coming from the
resultset = malloc(nRows * nCols * sizeof(float))
part. My understanding is that before that particular line, resultset
is a pointer to a memory block big enough to hold a float.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
I can't see what would be seen as " void * " *in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)

malloc returns a void * which in C should convert to (alost) everything
automagically. It does not in C++ (it requres a cast, so it seems likely
you're operating your compiler in C++ mode.

Bye, Jojo- Hide quoted text -

- Show quoted text -
that looks very likely, as I am using Visual C++ for the first time! I
changed the file name extension to .c rather than .cpp but apparently
that's not enough.
Oct 10 '08 #21

P: n/a
On Oct 10, 2:08*pm, Adam Chapman
<adam.chap...@student.manchester.ac.ukwrote:
On Oct 10, 1:39*pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:


Adam Chapman wrote:
Thankyou all. Sorry if it seemed like i was ignoring, Im sure you know
how hard it is to take everything in when you are stressed and
confused!
>#include <stdlib.h>
>float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
>{
>float *resultset;
>int row, col;
>/* allocate space for the result set, point resultset at the space */
>if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
>return NULL; /* first error condition */
>/* at this point, resultset points at a space big enough for our
>entire
>results table. Now, let's initialize it */
>for (row = 0; row < nRows; ++row)
>{
>for (col = 0; col < nCols; ++col)
>{
>*(resultset + (row * nCols) + col) = 0.0;
>}
>}
>/* matrix multiply A and B to result in resultset */
>for (row = 0; row < nRows; ++row)
>{
>for (col = 0; col < nCols; ++col)
>{
>*(resultset + (row * nCols) + col) =
>*(matrixA + (row * nCols) + col) *
>*(matrixB + (row * nCols) + col);
>}
>}
>return resultset;
>}
>#define Arows 3
>#define Acols 3
>#define Brows 3
>#define Bcols 3
>float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
>float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
>#include <stdio.h>
>int main(void)
>{
>float *Results;
>int row, col;
>/* Sanity check our array bounds */
>if ((Arows != Brows) || (Acols != Bcols))
>{
>printf("Gaak - our arrays aren't of the same size\n");
>return EXIT_FAILURE;
>}
>/* try matrix multiplication - exit EXIT_FAILURE on failure */
>if ((Results = mat_mult(&A[0][0],&B[0][0],Arows,Acols)) == NULL)
>{
>printf("Gaak - we ran into an error\n");
>return EXIT_FAILURE;
>}
>/* Print out the result set */
>for (row = 0; row < Arows; ++row)
>{
>printf("[%d]\t",row);
>for (col = 0; col < Acols; ++col)
>{
>printf("%f\t",*(Results + (row * Acols) + col));
>}
>printf("*\n");
>}
>printf("End of results\n");
>/* Free the allocated space */
>free(Results);
>return EXIT_SUCCESS;
>}
When I try to compile this, i get " error C2440: '=' : cannot convert
from 'void *' to 'float *' " from the line
>((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
The error is surely coming from the
>resultset = malloc(nRows * nCols * sizeof(float))
part. My understanding is that before that particular line, resultset
is a pointer to a memory block big enough to hold a float.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
I can't see what would be seen as " void * " *in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)
malloc returns a void * which in C should convert to (alost) everything
automagically. It does not in C++ (it requres a cast, so it seems likely
you're operating your compiler in C++ mode.
Bye, Jojo- Hide quoted text -
- Show quoted text -

that looks very likely, as I am using Visual C++ for the first time! I
changed the file name extension to .c rather than .cpp but apparently
that's not enough.- Hide quoted text -

- Show quoted text -
Ah, seemed to work after building project rather than building
solution. Thanks guys
Oct 10 '08 #22

P: n/a
Adam Chapman wrote:
On Oct 10, 1:39 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
>Adam Chapman wrote:
>>Thankyou all. Sorry if it seemed like i was ignoring, Im sure you
know how hard it is to take everything in when you are stressed and
confused!
>>>#include <stdlib.h>
>>>float *mat_mult(float *matrixA, float *matrixB, int nRows, int
nCols) {
float *resultset;
int row, col;
>>>/* allocate space for the result set, point resultset at the space
*/ if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
return NULL; /* first error condition */
>>>/* at this point, resultset points at a space big enough for our
entire
results table. Now, let's initialize it */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) = 0.0;
}
}
>>>/* matrix multiply A and B to result in resultset */
for (row = 0; row < nRows; ++row)
{
for (col = 0; col < nCols; ++col)
{
*(resultset + (row * nCols) + col) =
*(matrixA + (row * nCols) + col) *
*(matrixB + (row * nCols) + col);
}
}
>>>return resultset;
}
>>>#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 3
>>>float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
>>>#include <stdio.h>
>>>int main(void)
{
float *Results;
int row, col;
>>>/* Sanity check our array bounds */
if ((Arows != Brows) || (Acols != Bcols))
{
printf("Gaak - our arrays aren't of the same size\n");
return EXIT_FAILURE;
}
>>>/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult(&A[0][0],&B[0][0],Arows,Acols)) == NULL)
{
printf("Gaak - we ran into an error\n");
return EXIT_FAILURE;
}
>>>/* Print out the result set */
for (row = 0; row < Arows; ++row)
{
printf("[%d]\t",row);
for (col = 0; col < Acols; ++col)
{
printf("%f\t",*(Results + (row * Acols) + col));
}
printf("*\n");
}
printf("End of results\n");
>>>/* Free the allocated space */
free(Results);
>>>return EXIT_SUCCESS;
}
>>When I try to compile this, i get " error C2440: '=' : cannot
convert from 'void *' to 'float *' " from the line
>>>((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
>>The error is surely coming from the
>>>resultset = malloc(nRows * nCols * sizeof(float))
>>part. My understanding is that before that particular line,
resultset is a pointer to a memory block big enough to hold a float.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)

malloc returns a void * which in C should convert to (alost)
everything automagically. It does not in C++ (it requres a cast, so
it seems likely you're operating your compiler in C++ mode.

Bye, Jojo- Hide quoted text -

- Show quoted text -

that looks very likely, as I am using Visual C++ for the first time! I
changed the file name extension to .c rather than .cpp but apparently
that's not enough.
Indeed. You need /TC rather than /TP

Bye, Jojo
Oct 10 '08 #23

P: n/a
On October 10, 2008 08:25, in comp.lang.c, Adam Chapman
(ad**********@student.manchester.ac.uk) wrote:
Thankyou all. Sorry if it seemed like i was ignoring, Im sure you know
how hard it is to take everything in when you are stressed and
confused!
No problem. I understand how difficult it can be to absorb both a critique
of your own work, and an unsolicited solution. I hope they helped, btw.
>#include <stdlib.h>

float *mat_mult(float *matrixA, float *matrixB, int nRows, int nCols)
{
float *resultset;
int row, col;

/* allocate space for the result set, point resultset at the space */
if ((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)
[snip]
When I try to compile this, i get " error C2440: '=' : cannot convert
from 'void *' to 'float *' " from the line
As others have pointed out, a C compiler (with the proper definition of
malloc() ) doesn't have a problem with this line, and you are using a C++
compiler (wrong language) instead.
>((resultset = malloc(nRows * nCols * sizeof(float))) == NULL)

The error is surely coming from the
>resultset = malloc(nRows * nCols * sizeof(float))

part. My understanding is that before that particular line, resultset
is a pointer to a memory block big enough to hold a float.
No. Prior to this statement, the resultset variable is an uninitialized
pointer. That is to say, before the malloc(), resultset is a variable that
will hold a pointer, and resultset does not (yet) contain a valid pointer
value.

As an analogy, you can think of
char MyString[10];
as a variable that will hold a string, but does not yet hold one. Once you
put a \0-terminated sequence of characters into MyString will it then
contain a string.

Similarly, prior to the malloc(), resultset only reserves the space for a
pointer; it does not yet /contain/ a pointer.

Once the malloc() completes successfully, resultset will contain a pointer
that points to a space large enough to hold (at least) one float. Actually,
because of the value we gave to malloc() as its argument, resultset will
contain a pointer that points to a space large enough to hold
(nRows * nCols) floats.
The above line tries to make resultset a pointer to a larger memory
block, big enough for the array we are making.
Yes.
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)
malloc() returns a (void *), which the C language will properly convert to a
(float *).

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
Oct 10 '08 #24

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
[...]
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)
No, malloc returns void*, not void, which is a very different thing.

One of the most important aspects of programming is knowing how to
find out things like this on your own. You should have some sort of
reference material, such as a book, online documentation, a web site,
the C standard, etc. in which you could look up the description of the
malloc function. It would tell you that it's declared in <stdlib.h>
as:

void *malloc(size_t size);

(Note that reading the system header files is not a good source of
information; they're intended for the compiler, not for human readers,
and they're typically loaded with system-specific stuff that you
probably don't need to care about.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 10 '08 #25

P: n/a
On Oct 10, 6:52 pm, Keith Thompson <ks...@mib.orgwrote:
Adam Chapman <adam.chap...@student.manchester.ac.ukwrites:

[...]
I can't see what would be seen as " void * " in that expression
though. Could it be that malloc returns a void type (i.e. nothing?)

No, malloc returns void*, not void, which is a very different thing.

One of the most important aspects of programming is knowing how to
find out things like this on your own. You should have some sort of
reference material, such as a book, online documentation, a web site,
the C standard, etc. in which you could look up the description of the
malloc function. It would tell you that it's declared in <stdlib.h>
as:

void *malloc(size_t size);

(Note that reading the system header files is not a good source of
information; they're intended for the compiler, not for human readers,
and they're typically loaded with system-specific stuff that you
probably don't need to care about.)
Plus the standard doesn't require them to be actual files, so they
might not exist as readable files by the system user.
Oct 10 '08 #26

P: n/a
Hello again,

I was wondering about the way the mat_mult function returns a pointer:

float *mat_mult(float *matrixA, float *matrixB, int aRows, int aCols,
int bRows, int bCols) {
float *resultset;
...
...
return resultset;
}

In the return statement, is resultset seen by the compiler as a
pointer or a variable?
Also, I have done a little modification to make the matrix cross
product. This involves multiplying a row of matrix A by a column of
matrix B to get the (row,col) element of the resulting matrix. (code):

#include <stdio.h>
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int aRows, int
aCols, int bRows, int bCols) // why a pointer??????? as C functions
cannot return arrays without language trickery, the function will
return a pointer to the first element of the results array.
{
float *resultset;
int row, col, idx;

//The product AB has as many rows as A and as many columns as B.
if (aCols!=bRows) return NULL; // if matrices are incompatible for
multiplication
/* allocate space for the result set, point resultset at the
space */
if ((resultset = malloc(aRows * bCols * sizeof(float))) ==
NULL)
return NULL; /* first error condition */
/* at this point, resultset points at a space big enough for our
entire results table. Now, let's initialize it */
for (row = 0; row < aRows; ++row)
{
for (col = 0; col < bCols; ++col)
{
*(resultset + (row * bCols) + col) = 0.0;
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < aRows; ++row)
{
for (col = 0; col < bCols; ++col)
{
for(idx = 0; idx < bCols; ++idx)
{
*(resultset + (row * bCols) + col) +=
*(matrixA + (row * bCols) + idx) *
*(matrixB + (idx * bCols) + col);
}
}
}
return resultset;
}
#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 2

float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
//float B[Brows][Bcols]={ {1,0,0}, {0,0,0}, {0,0,0} };
float B[Brows][Bcols]={ {9,8}, {6,5}, {3,2} };

#include <stdio.h>
int main(void)
{
float *Results;
int row, col;
/* Sanity check our array bounds */
if ((Arows != Brows) || (Acols != Bcols))
{
printf("Gaak - our arrays aren't of the same size\n");
return EXIT_FAILURE;
}
/* try matrix multiplication - exit EXIT_FAILURE on failure */
if ((Results = mat_mult(&A[0][0],&B[0]
[0],Arows,Acols,Brows,Bcols)) == NULL) //The product AB has as many
rows as A and as many columns as B.
{
printf("Gaak - we ran into an error\n");
return EXIT_FAILURE;
}
/* Print out the result set */
for (row = 0; row < Arows; ++row)
{
printf("[%d]\t",row);
for (col = 0; col < Bcols; ++col)
{
printf("%f\t",*(Results + (row * Bcols) + col));
}
printf("*\n");
}
printf("End of results\n");
for(;;);

It all worked great when both matrices were size 3x3, but when I set
matrix B to have 3 rows and two columns, as above, nodisplay appears.
Strange because no error messages come up. The output matrix size
should be 3 rows x 2 columns, which im sure I coded for.
Oct 14 '08 #27

P: n/a
Adam Chapman wrote:
Hello again,

I was wondering about the way the mat_mult function returns a pointer:

float *mat_mult(float *matrixA, float *matrixB, int aRows, int aCols,
int bRows, int bCols) {
float *resultset;
...
...
return resultset;
}

In the return statement, is resultset seen by the compiler as a
pointer or a variable?
It sees it as a variable, because it /is/ a variable.
Also, I have done a little modification to make the matrix cross
product. This involves multiplying a row of matrix A by a column of
matrix B to get the (row,col) element of the resulting matrix. (code):

#include <stdio.h>
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int aRows, int
aCols, int bRows, int bCols)
I would have thought defining a struct:

struct Matrix { int rows; int cols; float *content; };

and passing it by address:

float *mat_mult( struct Matrix *a, struct Matrix *b ) ...

would have been clearer.
for (row = 0; row < aRows; ++row)
{
for (col = 0; col < bCols; ++col)
{
*(resultset + (row * bCols) + col) = 0.0;
Why not

resultset[row * bCols + col] = 0.0;

IMAO, the `a[i]` notation is often clearer than the equivalent `*(a + i)`.
}
}
/* matrix multiply A and B to result in resultset */
for (row = 0; row < aRows; ++row)
{
for (col = 0; col < bCols; ++col)
{
for(idx = 0; idx < bCols; ++idx)
Are you sure that's right? You're iterating 0..bCols twice.
{
*(resultset + (row * bCols) + col) +=
*(matrixA + (row * bCols) + idx) *
*(matrixB + (idx * bCols) + col);
Or
resultset[row * bCols + col] +=
matrixA[row * bCols + idx] * matrixB[idx * BCols + col];

--
'It changed the future .. and it changed us.' /Babylon 5/

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN

Oct 14 '08 #28

P: n/a
Chris Dollin <ch**********@hp.comwrites:
Adam Chapman wrote:
>Hello again,

I was wondering about the way the mat_mult function returns a pointer:

float *mat_mult(float *matrixA, float *matrixB, int aRows, int aCols,
int bRows, int bCols) {
float *resultset;
...
...
return resultset;
}

In the return statement, is resultset seen by the compiler as a
pointer or a variable?

It sees it as a variable, because it /is/ a variable.
>Also, I have done a little modification to make the matrix cross
product. This involves multiplying a row of matrix A by a column of
matrix B to get the (row,col) element of the resulting matrix. (code):

#include <stdio.h>
#include <stdlib.h>
float *mat_mult(float *matrixA, float *matrixB, int aRows, int
aCols, int bRows, int bCols)

I would have thought defining a struct:

struct Matrix { int rows; int cols; float *content; };

and passing it by address:

float *mat_mult( struct Matrix *a, struct Matrix *b ) ...

would have been clearer.
struct Matrix *mat_mult( struct Matrix *a, struct Matrix *b ) ...

would be even neater, though your function is the major component
needed to make the latter.

I suggested going one step further and making the type opaque and
adding get and set functions. That way, if a systems ever comes along
that actually dislikes the rule bending being done one can fix it with
a few re-writes in "private" functions.

--
Ben.
Oct 14 '08 #29

P: n/a
On Oct 14, 1:36*pm, Chris Dollin <chris.dol...@hp.comwrote:
Adam Chapman wrote:
Hello again,
I was wondering about the way the mat_mult function returns a pointer:
float *mat_mult(float *matrixA, float *matrixB, int aRows, int aCols,
int bRows, int bCols) * *{
* * *float *resultset;
* * *...
* * *...
* * *return resultset;
* * *}
In the return statement, is resultset seen by the compiler as a
pointer or a variable?

It sees it as a variable, because it /is/ a variable.
Also, I have done a little modification to make the matrix cross
product. This involves multiplying a row of matrix A by a column of
matrix B to get the (row,col) element of the resulting matrix. (code):
#include <stdio.h>
#include <stdlib.h>
* *float *mat_mult(float *matrixA, float *matrixB, int aRows, int
aCols, int bRows, int bCols) *

I would have thought defining a struct:

* * struct Matrix { int rows; int cols; float *content; };

and passing it by address:

* * float *mat_mult( struct Matrix *a, struct Matrix *b ) ...

would have been clearer.
* * *for (row = 0; row < aRows; ++row)
* * *{
* * * *for (col = 0; col < bCols; ++col)
* * * *{
* * * * **(resultset + (row * bCols) + col) = 0.0;

Why not

* * resultset[row * bCols + col] = 0.0;

IMAO, the `a[i]` notation is often clearer than the equivalent `*(a + i)`..
* * * *}
* * * }
* * */* matrix multiply A and B to result in resultset */
* * *for (row = 0; row < aRows; ++row)
* * *{
* * * *for (col = 0; col < bCols; ++col)
* * * *{
for(idx = 0; idx < bCols; ++idx)

Are you sure that's right? You're iterating 0..bCols twice.
Looks funny but it is right. This is what makes it a cross rather than
dot product. I have checked the resultys with Matlab
Still No idea why it doesn't like matrices of different sizes, cant
see anything wrong in the code myself
Oct 14 '08 #30

P: n/a
On Oct 14, 1:50*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Chris Dollin <chris.dol...@hp.comwrites:
Adam Chapman wrote:
Hello again,
I was wondering about the way the mat_mult function returns a pointer:
float *mat_mult(float *matrixA, float *matrixB, int aRows, int aCols,
int bRows, int bCols) * *{
* * *float *resultset;
* * *...
* * *...
* * *return resultset;
* * *}
In the return statement, is resultset seen by the compiler as a
pointer or a variable?
It sees it as a variable, because it /is/ a variable.
Also, I have done a little modification to make the matrix cross
product. This involves multiplying a row of matrix A by a column of
matrix B to get the (row,col) element of the resulting matrix. (code):
#include <stdio.h>
#include <stdlib.h>
* *float *mat_mult(float *matrixA, float *matrixB, int aRows, int
aCols, int bRows, int bCols) *
I would have thought defining a struct:
* * struct Matrix { int rows; int cols; float *content; };
and passing it by address:
* * float *mat_mult( struct Matrix *a, struct Matrix *b ) ...
would have been clearer.

* struct Matrix *mat_mult( struct Matrix *a, struct Matrix *b ) ...

would be even neater, though your function is the major component
needed to make the latter.

I suggested going one step further and making the type opaque and
adding get and set functions. *That way, if a systems ever comes along
that actually dislikes the rule bending being done one can fix it with
a few re-writes in "private" functions.

--
Ben.- Hide quoted text -

- Show quoted text -
I was thinking a structure type would be better too, because the
matrix dimensions would be easier to track (i.e. not lose).

Has anybody tried it with:

#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 2
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8}, {6,5}, {3,2} };

It doesn't display anything when I run it, but no idea why.
Also Chris, I like the look of the [] notation. It wasn't mentioned in
the book I'm reading but looks similar to what Im used to using in
Matlab.
Oct 14 '08 #31

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:

I'll comment only on un-commented on parts...
<snip>
/* at this point, resultset points at a space big enough for our
entire results table. Now, let's initialize it */
for (row = 0; row < aRows; ++row)
{
for (col = 0; col < bCols; ++col)
{
*(resultset + (row * bCols) + col) = 0.0;
}
}
There is no need to use nested loops and an index multiplication:

for (idx = 0; idx < aRows * bCols; ++idx)
resultset[idx] = 0;

will do just fine. However, I'd be inclined to include this setting
to zero in the loops that follow.

<snip>
/* Sanity check our array bounds */
if ((Arows != Brows) || (Acols != Bcols))
{
printf("Gaak - our arrays aren't of the same size\n");
return EXIT_FAILURE;
}
<snip>
printf("End of results\n");
for(;;);
<snip>
It all worked great when both matrices were size 3x3, but when I set
matrix B to have 3 rows and two columns, as above, nodisplay appears.
Strange because no error messages come up. The output matrix size
should be 3 rows x 2 columns, which im sure I coded for.
You need to fix this use of a loop the "hold the output window open".
In the case of mismatched sizes, I see your error message. I suspect
you just don't see it because of the "early return".

There is a way to run your program so you see its output with any need
for endless loops. I don't know it, but I know it is possible!

--
Ben.
Oct 14 '08 #32

P: n/a
Adam Chapman <ad**********@student.manchester.ac.ukwrites:
On Oct 14, 1:50*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>Chris Dollin <chris.dol...@hp.comwrites:
Adam Chapman wrote:
>Hello again,
>I was wondering about the way the mat_mult function returns a pointer:
>float *mat_mult(float *matrixA, float *matrixB, int aRows, int aCols,
int bRows, int bCols) * *{
* * *float *resultset;
* * *...
* * *...
* * *return resultset;
* * *}
>In the return statement, is resultset seen by the compiler as a
pointer or a variable?
It sees it as a variable, because it /is/ a variable.
>Also, I have done a little modification to make the matrix cross
product. This involves multiplying a row of matrix A by a column of
matrix B to get the (row,col) element of the resulting matrix. (code):
>#include <stdio.h>
#include <stdlib.h>
>* *float *mat_mult(float *matrixA, float *matrixB, int aRows, int
aCols, int bRows, int bCols) *
I would have thought defining a struct:
* * struct Matrix { int rows; int cols; float *content; };
and passing it by address:
* * float *mat_mult( struct Matrix *a, struct Matrix *b ) ...
would have been clearer.

* struct Matrix *mat_mult( struct Matrix *a, struct Matrix *b ) ...

would be even neater, though your function is the major component
needed to make the latter.

I suggested going one step further and making the type opaque and
adding get and set functions. *That way, if a systems ever comes along
that actually dislikes the rule bending being done one can fix it with
a few re-writes in "private" functions.

--
Ben.- Hide quoted text -

- Show quoted text -
Try not to quote this sort of stuff.
I was thinking a structure type would be better too, because the
matrix dimensions would be easier to track (i.e. not lose).

Has anybody tried it with:

#define Arows 3
#define Acols 3
#define Brows 3
#define Bcols 2
float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
float B[Brows][Bcols]={ {9,8}, {6,5}, {3,2} };

It doesn't display anything when I run it, but no idea why.
Yes. Explained elsewhere.
Also Chris, I like the look of the [] notation. It wasn't mentioned in
the book I'm reading but looks similar to what Im used to using in
Matlab.
'pointer[index] = value' is the norm. Please name and shame the book
that somehow manages to avoid mentioning it -- others need to know
what books to avoid.

--
Ben.
Oct 14 '08 #33

P: n/a
On Thu, 09 Oct 2008 17:24:31 -0400, Lew Pitcher
<lp******@teksavvy.comwrote:
On October 9, 2008 16:36, in comp.lang.c, Adam Chapman
(ad**********@student.manchester.ac.uk) wrote:
<snipped>
First off, in C, you cannot return an array. You can either return a struct
(or union) that /contains/ an array, or you can return a pointer to the
first element of an array. That's it.
Yes. And the same for passing as an argument, and assignment.
Secondly, arrays are contigiously allocated space. Elements of an array of
* type name[size];
can either be referenced by
* name[index]
or
* *(name+index)
Yes.
A two-dimensional array can be thought of as a one-dimensional array, each
element of which is a one-dimensional array.

So, elements of an array of
* type name[n_rows][n_cols];
can either be referenced as
* name[row][col]
or as
* *(name + (row * n_cols) + col)

See how, as a pointer expression, the compiler /needs/ to know the size of
the inner one-dimensional array?
No. name[row][col] will actually be implemented by machine code that
does something like baseof_name + (row * n_cols + col) * sizeof_elem,
but your last C expression will instead 'access' name[row*n_cols+col],
which is a putative whole row most likely far out of bounds.

What one can do is create a 1-D array in C and _treat it manually_ as
2-D (or more generally any higher rank):
type name [ nrow * ncol ]; /* NOT [nrow] [ncol] */
... name [ row * ncol + col ] ...
or
type * name = malloc (nrow*ncol * sizeof (type) );
or the clc-preferred
type * name = malloc (nrow*ncol * sizeof *name );
then either way
if( name == NULL ) some_error_handling;
... name [row * ncol + col ] ...

This is effectively what you did elsethread. But your code also
changed the algorithm to elementwise multiplication, not the usual
mathematical definition of mat_mult which the OP had coded, which
is, assuming correct space already allocated AND C[*][*] ZEROED:
assert( Acols == Brows && Crows == Arows && Ccols == Bcols );
for( i = 0; i < Arows /* or Crows */ ; i ++ )
for( j = 0; j < Bcols /* or Ccols */; j++ )
for( k = 0; k < Acols /* or Brows */; k++ )
C[i][j] += A[i][k] * B[k][i];
Similarly, [3-D case] <snipped>
OK, now in /your/ code below, you don't build a multi-dimensional array.
Instead, you build a *tree* of pointers. Since the dimensions are unknown
at compile time, compile-time shortcuts (like array subscripting) aren't
going to work. You have to dereference each pointer and pointer-to-pointer
to get to the data underneath.
Yes, but see below.
I'm going to ignore a lot of things below (like testing malloc() for
success, and size mismatches, and the like) and try to cut to the heart of
the matter
float **d;

d is an unitialized pointer to a pointer to a float.
* * int i, j, k;
d = malloc(Arows * sizeof *d);

d now points to space for three pointers.
*d is permitted to be a pointer to a float
*
*d which is identically d[0], and in addition d[1] and d[2] .
for(i=0; i<Arows; i++)
{
d[i] = malloc(Bcols * sizeof *d[i] );

Since you don't have multiple dimensions to contend with, you can get away
with
* d[i]
being equivalent to
* *(d+i)
This works for this code, here, but /will not/ work for your later use as
access to a multi-dimensional array
Yes it will, see below.
each of the three spaces that d can access now points to some space. The
size of the space allocated for each of those elements is three times the
size of a pointer-to-float (d is a pointer-to a pointer-to a float, so *d
resolves to be a pointer-to a float. Since *d is the same as *(d+0), and
*(d+0) is the same as d[0], then d[0] resolves to a pointer-to a float, and
consequently so does d[i].) This is important, because you asked malloc()
to allocate some space for you based on /this size/. You didn't get the
space for three floatingpoint numbers; you got what you asked for - the
space for three pointers.
No, sizeof *d[i] is the size of a float, and Bcols * that is 3 floats,
as desired. Remember that *d[i] is the same as d[i][0] . And as the
(unevaluated) operand of sizeof, it's the same as d[0][0].
>
for(j=0; j<Bcols; j++)
{
d[i][j]=0;

First off, you can't access your pointer-tree in this manner. It is not a
multi-dimensional array, but is a tree of pointers and
pointers-to-pointers.
Yes he can. It is a tree of pointers, but pointers and arrays are
closely linked in C -- though not identical, as people sometimes
oversimplify. d[i] (for valid i) is a pointer to float, which in fact
points to space large enough for 3 floats, so d[i][j] (for valid j)
can access those 3 floats 'just like' subscripting.

Actually it works the other way in the abstract semantics. x[i] is
DEFINED to be implemented as *(x+i). If x is an array, it 'decays' (is
converted) to a pointer to the first element of the array; then x+i
computes a pointer to the i'th (0-origin) element and *(x+i) accesses
it. OTOH if x is already a pointer to the first element of an array,
x+i and *(x+i) work exactly the same way. In practice a compiler will
usually optimize cases where x is an array and hence has a known
static or auto=frame-relative location, but that's only optimization;
it still must produce the correct, hence equivalent, semantics.

See section 6 of the FAQ, at usual places and http://c-faq.com/ .
Secondly, you haven't allocated space for the floatingpoint values yet, so
trying to assign anything other than a pointer value is futile and an
error.
Yes he did; the same d[i] = malloc ... you already commented on.
Thirdly (and not too consequentially), 0 is not a floatingpoint value.
However 0.0 is. The good news is that, had the *left-hand-side of the
statement correctly resolved to a floatingpoint data type, C would have
converted your integer 0 to floatingpoint 0.0 for you.
Yes. Or more precisely the LHS is a variable (or precisely lvalue) of
a specific floating-point type namely float, and the int value 0 is
implicitly converted to that type giving the float value 0.0f.
>
for(k=0; k<Acols; k++)
{
d[i][j]+=A[i][k]*B[k][j];

}
printf("%0f * ", d[i][j]);
}
Aside: %0f doesn't accomplish anything different from %f. This is
unlike Fortran, where Fw means use exactly w chars while C %wf means
_at least_ w chars but more if needed; in a recent change to Fortran
F0 means use as many chars as needed, which is the same as %f in C.
printf("\n");
}
return d;

No. You are returning a pointer. A pointer to an automatic variable that
disappears /with/ the return. You don't want to do this.
You already corrected this; it's to malloc'ed space.

- formerly david.thompson1 || achar(64) || worldnet.att.net
Oct 20 '08 #34

This discussion thread is closed

Replies have been disabled for this discussion.