Reputation: 4853
I have the need to allocate memory for an array of pointers to structs. The documentation for malloc()
informs that the return from this function returns a pointer to the first block of memory that was allocated. Well, in my case I called the function like this:
malloc(SIZE_TABLE*sizeof(struct structName*))
The problem being that, since malloc returns a pointer to this memory (containing pointers), it will thus return a 2-star pointer of type structName
.
Instead of having an extra line to assign the 2-star pointer and then dereference it, can you dereference the call itself?
Instead of:
struct structName** temp = malloc(SIZE_TABLE*sizeof(struct structName*))
struct structName* temp2 = *(temp);
Could you do something like:
struct structName* temp2 = *( malloc(SIZE_TABLE*sizeof(struct structName*)) );
I have done little when it comes to 2-star pointers, so if there is a better way to approach this problem (or if I am simply miss-understanding it all), please let me know.
Upvotes: 3
Views: 6698
Reputation: 16726
You need to keep in mind that your malloc allocates SIZE_TABLE pointers to struct structName
, but these struct structName
are not allocated. Even worse: the buffer allocated by malloc is not initialized, so none of the pointers is initialized/valid.
What you need to do:
struct structName ** table = malloc(SIZE_TABLE*sizeof(struct structName*));
size_t i;
for(i = 0; i < SIZE_TABLE; ++i)
table[i] = malloc(sizeof(struct structName));
What you propose:
struct structName * tableEntryAtIndex0 = malloc(SIZE_TABLE*sizeof(struct structName*));
This does not compile, you cannot dereference a void *
.
Either of these two lines would compile:
// Either the way you wanted it
struct structName * tableEntryAtIndex0 = *((struct structName **)malloc(SIZE_TABLE*sizeof(struct structName*)));
// Or with an index to punctuate that a table was malloc-ed (in my opinion better to understand what happens)
struct structName * tableEntryAtIndex0 = ((struct structName **)malloc(SIZE_TABLE*sizeof(struct structName*)))[0];
This still has two problems: first you are losing the pointer to the overall table. So you cannot check it for NULL, you cannot access any other table entry and you cannot free the memory. Second the table was not initialized by malloc, so you are getting a garbage pointer. Now setting tableEntryAtIndex0 to malloc(sizeof(struct structName))
would not help, because this would just modify tableEntryAtIndex0 and not the entry in the table.
Upvotes: 1
Reputation: 2738
No you can not do that directly.
malloc
returns void*
, dereferencing a void*
is undefined, and it will generate a compiler warning.
But you can cast it to different pointer type and then dereference.
The following may work:
struct structName* temp2 = *((struct structName**)malloc(SIZE_TABLE*sizeof(struct structName*)));
But this is a serious memory leak as the original return value of malloc
is lost and is not good practice at all as you are not sure about the return value of malloc
. If it is NULL
dereferencing is not possible.
There is another problem in doing that. The value at the address returned by malloc
is uninitialized, so dereferencing it after casting also lead to undefined behavior.
Always check for NULL
before dereferencing any pointer. and
Always save the return value of malloc
to free
it later.
Upvotes: 5
Reputation: 106012
No you can't. This is because the return value of malloc
is void *
, and it is not known that to which type this void *
get converted in this case. Dereferencing a void *
invokes undefined behavior.
You will also get a warning in most compiler if you do so e.g. for GCC
warning: dereferencing ‘void *’ pointer [enabled by default]
I would not suggest you to cast the return value of malloc
and then dereference it. Better to stick with your first approach.
Upvotes: 3
Reputation: 75688
As others have said, you can dereference it if you add a type cast. But you shouldn't. One reason already mentioned is checking for NULL
. The other is:
malloc
returns in order to be able to free the memory later.Upvotes: 2