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;
}
2 Answers 2
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 (...) { ... }
-
\$\begingroup\$ arithmetic such as (cmatrix+ptrsize) can't be done with void*. \$\endgroup\$Ganesh– Ganesh2011年03月26日 23:48:42 +00:00Commented 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\$Jonathan Leffler– Jonathan Leffler2011年03月27日 02:49:02 +00:00Commented 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 ascalloc
. 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– Snowbear2011年03月27日 08:16:17 +00:00Commented Mar 27, 2011 at 8:16 -
\$\begingroup\$ @Ganesh, got your point, updated my answer \$\endgroup\$Snowbear– Snowbear2011年03月27日 08:23:24 +00:00Commented 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– AndersK2015年01月26日 07:01:50 +00:00Commented Jan 26, 2015 at 7:01
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.
-
\$\begingroup\$ does C even have references? I thought that was limited to C++. Was it added to the latest standard? \$\endgroup\$greatwolf– greatwolf2011年03月29日 21:44:16 +00:00Commented Mar 29, 2011 at 21:44
-
\$\begingroup\$ As far I know no references for C, only pointers. \$\endgroup\$bcsanches– bcsanches2011年03月30日 14:13:17 +00:00Commented Mar 30, 2011 at 14:13
Explore related questions
See similar questions with these tags.