tags:

views:

93

answers:

5

In a C function declaration, I have seen this parameter definition:

void *userData

so, what exactly is that? My guess: the void says it can be anything arbitrary, or even nothing. Almost similar to id of objective-c. It just allows to pass in whatever data structure you like.

The star in front of userData says, that the argument must be passed in by reference.

So when using this stuff in the function body, typically it must be casted and dereferenced. So if I pass in an pointer to SomeClass instance, I would get that like this:

SomeClass *myObj = (SomeClass*)userData;

In the case I had nothing special to pass along, I would provide NULL as argument.

Are my assumptions correct? Or did I get something wrong?

+3  A: 

A void * is a pointer to a structure of unknown type. You can think of it as "a pointer to anything". It's not the same as Objective-C's id type, which is the type of any object. An id looks like this:

typedef struct objc_object {
  Class isa;
} *id;

Typically in Objective-C (and I'm sure in C too) a framework might use some callback to tell you something. That callback will often take a parameter containing data that you give it - perhaps the object that started the action, and that needs to know that something's happened. A void * parameter lets the framework define a callback without depending on your code, so you can put anything you like into the callback. (Of course that means you also have to ensure that you cast your void *userData back into the appropriate type.)

Frank Shearar
+1  A: 

Without seeing the actual code I'm guessing the parameter belongs to a function which takes a callback? If so it is probably a piece of context which, as you say, you can set to whatever you want. When the function invokes your callback it will pass this context along, which means you don't need a global to store this data.

Skurmedel
Based on its name, I would guess it's more likely intended to be a block of user-managed data, not a function.
RickNotFred
+3  A: 

void * means pointer to anything. So, you could pass anything "by reference" via void * argument. userData parameter name suggests (but is only a suggestion so it may vary across various APIs), that this argument is some arbitrary user-supplied data. That is, function in question will do nothing with it, just store, and give you it back some time. For example, in GTK+ you can attach a callback to some event. You can pass your own data to g_signal_connect as user_data argument, and in event handler, GTK+ will pass you your data back:

GtkWidget *button = gtk_button_new ();
const char *data = "Hello World;)";
g_signal_connect (button, "clicked", on_clicked, data);
(...)
void on_clicked (GtkWidget *widget, void * data)
{
    const char *text = (const char *)data;
    printf ("%s\n", text); // will print "Hello World;)"
}
el.pescado
A: 

Your understanding is essentially correct, although it is called a pointer not a reference. This is usually a mechanism for letting users "extend" a data structure by passing in a block of any type of data. An example I have seen this used is for nodes of a tree display in a GUI. The GUI framework adds the void pointer so that when a user clicks a node of this tree, you can pull more meaningful information about the node than just its name into your calling routine. Since only you know what type of data would be meaningful to your application, the type is simply a void*.

Also note that you are almost always responsible for managing the memory for userData.

RickNotFred
+1  A: 

void * is a pointer to any data type.

Note that it is not necessarily the right size for a pointer to a function.

James Curran
A void * is the right size to hold a memory address and a pointer to a function is just a memory address. It will always fit.
Daniel Stutzbach
James Curran
@James Curran: On those compilers, all pointers were either near or far, depending on where in memory they needed to point to. It doesn't matter what was stored at that location. With certain compilation settings, near pointers were used by default and functions were in far memory, so I see where you might get your impression. However, you could arrange for some functions to be in near memory and put some data in far memory or make far pointers the default. In any case, near and far pointers were never compliant with the C standard and I'm glad modern compilers do not include them.
Daniel Stutzbach
James Curran
Finally, the basic point (void* is for data only) is *in the standard* (6.2.2.3 - "A pointer to void may be converted to or from a pointer to any uncomplete or object type." Note "function" is not mentioned)
James Curran
You're right. I was looking at "A pointer to an object or to void may be cast to a pointer to a function", but reading more closely that's in an annex of common extensions. Thank you for teaching me something new. Want to update your answer to note that many compilers allow storing pointers to functions in a void pointer as an extension? (including all compilers for modern computers). Another counterexample would be embedded systems where functions are in ROM that has a completely separate address space. Changing your answer will also allow me to change my vote. :)
Daniel Stutzbach