At some memory allocation I find this. But I don't understand it.
char * mem_alloc()
{
char *point;
char *a;
point = (char *)malloc(block_num);
a = *(char**) point;
return a;
}
At some memory allocation I find this. But I don't understand it.
char * mem_alloc()
{
char *point;
char *a;
point = (char *)malloc(block_num);
a = *(char**) point;
return a;
}
char * mem_alloc()
In my experience, functions returning a pointer are almost always a sign of flawed program design. Such a pointer could point at the following:
In this case, it points to dynamic memory, so we can likely assume poor program design and likely memory leaks to go with it.
point = (char *)malloc(block_num);
This code means that whoever wrote it is confused over how malloc works and how void pointers work. The result of malloc should never be typecasted, see this and this. The urge to typecast means that the programmer is confused about the C language, and/or that they are trying to compile C code on a C++ compiler.
"block_num" is suspicious, if this is a global, non-constant variable, then the program design is poor.
a = *(char**) point;
This means, take the address of point, which is pointing at uninitialized memory on the heap, then pretend that point is a pointer-to-pointer and thereby treat the garbage contents of the heap as if it was a pointer. Then return this pointer, pointing out at a random location in in la-la land, to the caller. And while doing so, create a memory leak.
This seems to set a to point's value(which is an address).
a = *(char**) point;
The above statement is typecasting point to - "pointer to a pointer" in `(char**) point' part.
After this you have * for de-reference which changes it to
value of(pointer to a pointer)
=> pointer.
Thus the value(rather address) stored in point gets copied in a.
I am still not sure why this kind of code is written.
The code you posted is silly - are you sure it's complete?
"point" and "a" are both pointers.
"a" is initialized to "point" ... but "point" is completely uninitialized. Bad things will happen if the caller tries to use the return value "a".
Here's another example:
struct Point {
int x;
int y;
};
...
char * mem_alloc (int size)
{
return (char *)malloc (size);
}
...
Point *my_point = (Point *)mem_alloc (sizeof (struct Point));
...
This snippet is also silly ... but hopefully it illustrates a bit of what might be the rationale behind the code you're looking at...
a
contains the value stored at the location pointed by point
. Since point
is uninitialized, it's pointing at a random location which contains random value and hence now a
is pointing to random value which it was to begin with.
So the code is a no-op.
If you look at the concept of malloc
, it always returns the base address of the allocated memory space,the actual syntax of the malloc
function is
Syntax:
pointer_to_store_base_add_of_mem = (data_type_of_allocated_memory)malloc(size_of_array)
In the above example you have allocated the character type of memory,hence you have used (char*) and in block_num you have given the size of the character array,and point pointer stores the base address of the allocated memory.
Looking at the code chenyoufu123 posted in a comment on Lundin's answer:
ptr = (char *)malloc(block_num * size);
for(k=0; k<block_num-1; k++) {
*((char **)(ptr + k*size)) = ptr + (k+1) * size;
}
*((char **)(ptr + k*size)) = NULL;
That is still bad code, but not completely senseless as the original code from the question. In particular together with the remark that it is used to create a linked list from another comment.
The situation is - assuming that the code is "correct" - that you have a
struct Node
{
struct Node *next;
/* More members */
};
and size_t size = sizeof(struct Node);
(the names will be different, probably). Then
ptr = (char *)malloc(block_num * size);
allocates memory for block_num
contiguous struct Node
s. One would usually allocate that as
struct Node *ptr = malloc(block_num * sizeof *ptr);
The loop
for(k=0; k<block_num-1; k++) {
*((char **)(ptr + k*size)) = ptr + (k+1) * size;
}
*((char **)(ptr + k*size)) = NULL;
then reinterprets the address k * sizeof(struct Node)
behind the start of the memory block, ptr + k*size
, as a pointer to a pointer (a char**
, but on most PC architectures nowadays, that's not important since all object pointers have the same representation - if it is important, the code is broken anyway) and writes the address of the next sizeof(struct Node)
sized chunk of memory to that location. Since the next
pointer is the first member of struct Node
, that writes the address of the next struct Node
in the list to the next
pointer of the current struct Node
. Finally, the next
pointer of the last struct Node
is set to NULL
.
The usual way of writing this,
struct Node *ptr = malloc(block_num * sizeof *ptr);
int k;
for(k = 0; k < block_um - 1; ++k)
{
ptr[k].next = &ptr[k+1]; // or ptr + (k+1), if you prefer
}
ptr[block_num-1].next = NULL;
is not only clearer, it also has the advantage of working on platforms where char*
and struct Node*
have different sizes or representations.