initialising array of unknown size (newbie)

A

Adam Chapman

Adam said:
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
The error is surely coming from the
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.
 
A

Adam Chapman

Adam said:
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
 
J

Joachim Schmitz

Adam said:
Adam said:
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
 
L

Lew Pitcher

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.
The error is surely coming from the


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. ------
 
K

Keith Thompson

Adam Chapman said:
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.)
 
V

vippstar

[...]
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.
 
A

Adam Chapman

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.
 
C

Chris Dollin

Adam said:
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` 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];
 
B

Ben Bacarisse

Chris Dollin said:
It sees it as a variable, because it /is/ a variable.


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.
 
A

Adam Chapman

Adam said:
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` 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
 
A

Adam Chapman

  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.

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.
 
B

Ben Bacarisse

I'll comment only on un-commented on parts...
/* 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!
 
B

Ben Bacarisse

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.
 
D

David Thompson

On October 9, 2008 16:36, in comp.lang.c, Adam Chapman
([email protected]) wrote:
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[j] += A[k] * B[k];
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


d is an unitialized pointer to a pointer to a float.


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 = malloc(Bcols * sizeof *d );


Since you don't have multiple dimensions to contend with, you can get away
with
  d
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.) 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 is the size of a float, and Bcols * that is 3 floats,
as desired. Remember that *d is the same as d[0] . And as the
(unevaluated) operand of sizeof, it's the same as d[0][0].
for(j=0; j<Bcols; j++)
{
d[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 (for valid i) is a pointer to float, which in fact
points to space large enough for 3 floats, so d[j] (for valid j)
can access those 3 floats 'just like' subscripting.

Actually it works the other way in the abstract semantics. x 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 = 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[j]+=A[k]*B[k][j];

}
printf("%0f   ", d[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.
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top