What type of cast does *( char** )
accomplish?
It seems to create a pointer to a pointer ("double pointer") with the **
. But the *
outside the parentheses confuses me... Below is the cast in context:
void mem_test ( void )
{
void* m1;
void* m2;
...
m1 = 0;
while ( ( m2 = malloc( 10001 ) ) != 0 )
{
*( char** ) m2 = m1; // what does this cast mean?
m1 = m2;
}
...
}
Another confusing variant of it appears in the following snippet. What does the cast accomplish in this scenario, and is it different from the one above?
void mpenter ( void ); // a function with no parameters and no return value
...
uchar* code;
...
*( void ( ** ) ( void ) ) ( code - 8 ) = mpenter; // what does this cast mean?
What is the proper name for this type of cast? I.e. what should I be searching for to learn more about it?
mem_test
Let's dissect this step-by-step. To make it easy, assume we're on a 64-bit architecture where pointers are 8 bytes in size.
m2 = malloc( 10001 )
assigns m2
to a freshly allocated block of memory.(char **) m2
says "let's pretend the first 8 bytes of memory at address m2
is a char*
, and point at that -- resulting in a char**
"*(char **) m2
dereferences the above, resulting in an l-value to a char*
(in C speak). Remember l-values are writable.
char*
, i.e. char*&
*(char **) m2 = m1;
writes the value of m1
into the l-value created above.Another way to write that code would be:
char* pCurrentBuffer;
char* pPreviousBuffer;
pPreviousBuffer = NULL;
while ( ( pCurrentBuffer = malloc( 10001 ) ) != NULL )
{
char** ppPreviousBuffer = (char**)pCurrentBuffer;
*ppPreviousBuffer = pPreviousBuffer;
pPreviousBuffer = pCurrentBuffer;
}
Surprise(!), in the end, it creates a linked list. (technically it's a reversed linked-list because they are all previous pointers instead of next pointers, but I am joking)
mpenter
This is casting the 8 bytes at address code - 8
to a pointer-to-function-pointer, so that it can assign the address of function mpenter
into that location.
void (*)(void)
is a pointer to a function that takes no parameters and returns void
.void (**)(void)
is a pointer to a function-pointer of the above type.mpenter
into that l-value (i.e. the 8 bytes of memory at address code - 8
)It's unusual to take a negative offset from a pointer, but if code
is pointing into the middle of a struct of some kind, it may be legitimate (in some loose sense of the word).