Reading CMU's OS Course Home Page, they say:
"It is a good idea to be familiar with C conventions. For example, it is not generally the case that a void * is a pointer. If seeing a void * parameter, or a void ** parameter, in a function prototype would be confusing, this would be a good area to look into."
I honestly have no idea what they mean by this, what is a void *
if not a pointer?
CodePudding user response:
One case where void *
is not a pointer involves passing data to a callback function. Imagine some library gives you a function which does some useful work, and calls your function (callback) in the middle of that work.
// useful_header.h
int do_useful_work(int data1, int data2, int (*callback)());
You call this function like this:
// your_code.c
int my_callback()
{
...
return 42;
}
int main()
{
int useful_result = do_useful_work(2, 3, my_callback);
}
What if you want to pass data to your callback? The company which provides do_useful_work
doesn't know which data your callback wants to get. So it provides the most generic thing - void *
. Your callback interprets it as a pointer to your struct
.
// useful_header.h
int do_useful_work(int data1, int data2, int (*callback)(void *), void *user_data);
// your_code.c
struct MyData
{
int x, y, z;
};
int my_callback(void *pointer)
{
struct MyData *data = pointer;
...
return data->x data->y data->z 42;
}
int main()
{
struct MyData data = {5, 6, 7};
int useful_result = do_useful_work(2, 3, my_callback, &data);
}
This has an edge-case: what if your callback wants to receive only a small item (of type int
), and not a whole struct
? Then you could interpret the pointer as int
.
// your_code.c
int my_callback(void *not_really_pointer)
{
int data = (int)not_really_pointer;
...
return data 42;
}
int main()
{
int useful_result = do_useful_work(2, 3, my_callback, (void *)5);
}
Here, the void *
argument is not really a pointer - it's a number, which is passed using void *
type because C enforces type-checking.
Having said that, this is an example of sloppy coding; making a struct
with one element would be clearer here.