4
\$\begingroup\$

For an interview, I was asked to write code allocate memory for a rows*cols matrix, using a single malloc(). I want your comments about this code that I wrote:

/*
Allots (in effect) space for a matrix of size rows*cols using a single malloc. 
The whole space allotted consists of an array of size 'rows' of float ptrs,
followed by a float array of size  'rows' * 'cols'. 
The float ptrs 1,2..,  are assigned to row no. 1, 2,..  in the matrix that follows.
*/

float** allotMatrix(const size_t &rows, const size_t &cols)
{
    // Compute size of allotment = rows * cols floats + rows float ptrs
    size_t ptrsize = rows * sizeof(float*);
    size_t datasize = rows * cols * sizeof(float);
    size_t matsize =  ptrsize + datasize;

    // Get if possible a memory allotment  of this size. We use char* for convenience
    char* cmatrix = (char*) malloc(matsize);
    if (cmatrix == NULL)
    {
        fprintf(stderr, "Unable to allot memory");
        exit(1);
    }

    memset((void*) cmatrix, 0, matsize);

    // Assign ptrs to data
    float** ptrstart = (float**) cmatrix;
    float* datastart = (float*) (cmatrix + ptrsize);
    for (size_t i = 0; i != rows; ++i)
    {

        *ptrstart =  datastart;
        // Move to next ptr
        ++ptrstart;
        // .. and move to the next data row
        datastart += cols;
    }

    return (float**) cmatrix;
}
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

I would use calloc instead of malloc since you're anyway clearing the matrix after allocation.

void* cmatrix = calloc(1, matsize);
...
//memset((void*) cmatrix, 0, matsize);  this is not needed anymore because of 'calloc'

Also I do not think there is any point in using char* here because. Looks like you're using char* only because it allows you to increment pointers by bytes. I think using float** here would be even more convinient:

float** cmatrix = (float**) calloc(1, matsize);
if (cmatrix == NULL) { ... }
float* datastart = (float*) (cmatrix + rows); // you don't need char pointers here
for (...) { ... }
\$\endgroup\$
5
  • \$\begingroup\$ arithmetic such as (cmatrix+ptrsize) can't be done with void*. \$\endgroup\$
    – Ganesh
    Commented Mar 26, 2011 at 23:48
  • 2
    \$\begingroup\$ There's no guarantee in the C standard that the zeroing that calloc() does creates floating point zeroes. That said, with the IEEE 754 standard, you do get zeroes, and that covers an awful lot of machines these days. \$\endgroup\$ Commented Mar 27, 2011 at 2:49
  • \$\begingroup\$ @Jonathan, I wasn't talking about floating point zeros, OP originally was zeroing the memory with memset and I believe it will behave in the same way as calloc. And I don't know how both these approaches work with floating point zeroz, I just say that one can be replaced with other. \$\endgroup\$
    – Snowbear
    Commented Mar 27, 2011 at 8:16
  • \$\begingroup\$ @Ganesh, got your point, updated my answer \$\endgroup\$
    – Snowbear
    Commented Mar 27, 2011 at 8:23
  • 1
    \$\begingroup\$ not good practice to cast the return value of calloc/malloc, it returns a void* so there is no need to cast \$\endgroup\$
    – AndersK
    Commented Jan 26, 2015 at 7:01
0
\$\begingroup\$

I would not pass rows and cols by reference in this case, most cases it will have the same size as a pointer, no gain using it as reference.

\$\endgroup\$
2
  • \$\begingroup\$ does C even have references? I thought that was limited to C++. Was it added to the latest standard? \$\endgroup\$
    – greatwolf
    Commented Mar 29, 2011 at 21:44
  • \$\begingroup\$ As far I know no references for C, only pointers. \$\endgroup\$
    – bcsanches
    Commented Mar 30, 2011 at 14:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.