Looking at the chenyoufu123 code posted in the Lundin comment, reply:
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;
This is still bad code, but not completely pointless, like the source code from the question. In particular, along with the comment that it is used to create a linked list from another comment.
The situation - assuming the code is "correct" - you have
struct Node { struct Node *next; };
and size_t size = sizeof(struct Node); (names will be different, maybe). Then
ptr = (char *)malloc(block_num * size);
allocates memory for block_num adjacent struct Node s. You can usually distinguish this as
struct Node *ptr = malloc(block_num * sizeof *ptr);
Cycle
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) at the beginning of the memory block, ptr + k*size , as a pointer to a pointer (a char** , but on most PC architectures these days it doesnβt matter, since all object pointers have the same representation - if this is important, the code is violated anyway) and writes the address of the next sizeof(struct Node) memory size to this place. Since the next pointer is the first member of the struct Node , which writes the address of the next struct Node to the list, the next pointer of the current struct Node . Finally, the next pointer of the last struct Node set to NULL .
The usual way to record
struct Node *ptr = malloc(block_num * sizeof *ptr); int k; for(k = 0; k < block_um - 1; ++k) { ptr[k].next = &ptr[k+1];
not only clearer, but also has the advantage of working on platforms where char* and struct Node* have different sizes or representations.