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\$
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\$
  • \$\begingroup\$ arithmetic such as (cmatrix+ptrsize) can't be done with void*. \$\endgroup\$ – Ganesh Mar 26 '11 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\$ – Jonathan Leffler Mar 27 '11 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 Mar 27 '11 at 8:16
  • \$\begingroup\$ @Ganesh, got your point, updated my answer \$\endgroup\$ – Snowbear Mar 27 '11 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\$ – Anders Jan 26 '15 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\$
  • \$\begingroup\$ does C even have references? I thought that was limited to C++. Was it added to the latest standard? \$\endgroup\$ – greatwolf Mar 29 '11 at 21:44
  • \$\begingroup\$ As far I know no references for C, only pointers. \$\endgroup\$ – bcsanches Mar 30 '11 at 14:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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