458,084 Members | 1,207 Online 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
33 Replies

 P: n/a On Oct 9, 11:57*am, Ben Bacarisse #include #include int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols; int A={1,2,3,4,5,6,7,8,9}; int B={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

 P: n/a Adam Chapman Adam Chapman 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 #include #include 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={1,2,3,4,5,6,7,8,9}; int B={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; 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

 P: n/a On Oct 9, 1:49*pm, Ben Bacarisse #include #include 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={1,2,3,4,5,6,7,8,9}; int B={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; 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

 P: n/a Adam Chapman #include #include //double A, B; int Arows=3, Acols=3, Brows=3, Bcols=3; int A={1,2,3,4,5,6,7,8,10}; int B={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 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 #include #include #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

 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 #include #include #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 #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 #include #include #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); for(;;); } mat_mult() { float **d; int i, j, k; d = malloc(Arows * sizeof *d); for(i=0; i

 P: n/a Adam Chapman #include #include #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); 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 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. Thecompiler 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 afile-duration static variable. /This/ local variable is the one thatthefunction 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 #include #include #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); 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

 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 So now I have #include #include #include #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? :-) 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 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 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 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 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 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 Thanks Keith, although your suggestions have brought up a lot oferrors.Here is my current code:#include #include #include #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} > #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 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 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 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 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 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 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,&B,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 * *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 * 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,&B,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 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 ourentireresults 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 3float 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 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,&B,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" 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 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 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,&B,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 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 >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 >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,&B,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" wrote: >Adam Chapman wrote: >>Thankyou all. Sorry if it seemed like i was ignoring, Im sure youknow how hard it is to take everything in when you are stressed andconfused! >>>#include >>>float *mat_mult(float *matrixA, float *matrixB, int nRows, intnCols) {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 ourentireresults 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 >>>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,&B,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: '=' : cannotconvert 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 memoryblock, big enough for the array we are making.I can't see what would be seen as " void * " in that expressionthough. 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, soit 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 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; 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 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 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 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 #include 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 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,&B ,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 #include 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 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 apointer 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 crossproduct. This involves multiplying a row of matrix A by a column ofmatrix B to get the (row,col) element of the resulting matrix. (code):#include #include float *mat_mult(float *matrixA, float *matrixB, int aRows, intaCols, 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 #include * *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 #include * *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 /* 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. /* Sanity check our array bounds */ if ((Arows != Brows) || (Acols != Bcols)) { printf("Gaak - our arrays aren't of the same size\n"); return EXIT_FAILURE; } 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. 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 Chris Dollin 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 apointer 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 crossproduct. This involves multiplying a row of matrix A by a column ofmatrix B to get the (row,col) element of the resulting matrix. (code): >#include #include >Â* Â*float *mat_mult(float *matrixA, float *matrixB, int aRows, intaCols, 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 componentneeded to make the latter.I suggested going one step further and making the type opaque andadding get and set functions. Â*That way, if a systems ever comes alongthat actually dislikes the rule bending being done one can fix it witha 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 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] 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, and in addition d and d . for(i=0; i for(j=0; j for(k=0; k

### This discussion thread is closed

Replies have been disabled for this discussion.

### Similar topics

Browse more C / C++ Questions on Bytes 