* in front of function name?

P

pemo

Hi
Why put * in front of the function name in the declaration?

int (*write)(struct inode *, struct file *, const char *, int);

thanks
from Peter ([email protected])

The dec reads as:

write is a function pointer - and it should be set to point to a function
that returns an int, and that takes 4 parameters:

a struct inode *, a struct file *, a const char *, and an int
 
V

Vladimir S. Oka

yong said:
It means that return type is pointer.

No it does not. (That would've been: int *write(/* params */);)

The other reply (which didn't quote context) was right. It declares
`write` as pointer to function with 4 parameters as described above.

Consider using `cdecl`.
 
V

Vladimir S. Oka

Vladimir said:
No it does not. (That would've been: int *write(/* params */);)

The other reply (which didn't quote context) was right. It declares
`write` as pointer to function with 4 parameters as described above.

Which returns an `int`.
Consider using `cdecl`.

I should have pasted it's output in the first place. :-/

--
BR, Vladimir

She always believed in the old adage -- leave them while you're looking
good.
-- Anita Loos, "Gentlemen Prefer Blondes"
 
M

Micah Cowan

Hi
Why put * in front of the function name in the declaration?

int (*write)(struct inode *, struct file *, const char *, int);

This does not declare a function; it declares a /pointer/ to a
function. write is a pointer to a function that takes four arguments
and returns int.
 
J

John Bode

Hi
Why put * in front of the function name in the declaration?

int (*write)(struct inode *, struct file *, const char *, int);

thanks
from Peter ([email protected])

This declares write as a pointer to a function taking 4 arguments and
returning an int. As to *why* you want to do this, there are a couple
of reasons:

1. You can pass a pointer to a function as a parameter to another
function; this is known as a callback, and is useful in a number of
contexts. The canonical example is the qsort() library function, which
can sort 1D arrays elements of any type. Here's how it's used:

/*
* prototype for qsort() as found in stdlib.h
*
* void qsort(void *base, size_t count, size_t size, int (*cmp)(const
void *, const void *));
*/
#include <stdlib.h>
#include <string.h>

int compareInts(const void *arg1, const void *arg2)
{
int *a = arg1;
int *b = arg2;

if (*a < *b)
return -1;
else if (*a > *b)
return 1;
else
return 0;
}

int compareMyStructs(const void *arg1, const void *arg2)
{
MyStruct *a = arg1;
MyStruct *b = arg2;

/*
* Assume the key value for MyStruct is a character string
*/
char *key1 = a->getKey();
char *key2 = b->getKey();

if (strcmp(a, b) < 0)
return -1;
else if (strcmp(a, b) > 0)
return 1;
else
return 0;
}

int main(void)
{
int iArr[20];
MyStruct sArr[30];

...

qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0],
compareInts);
qsort(sArr, sizeof sArr/sizeof sArr[0], sizeof sArr[0],
compareMyStructs);

...

return 0;
}

The signal() library function does something similar; you pass it a
pointer to a function you want executed every time a particular signal
is raised:

void handleInterrupt(sig_atomic_t sig)
{
gInterrupt = 1;
}

int main(void)
{
signal(SIGINT, handleInterrupt);
...
}

2. With function pointers, you can implement a primitive form of
polymorphism, where you can refer to a generic "write" function in your
logic that resolves to one of several different functions based at
runtime. One project I did many years ago involved writing parsers for
a set of data files. I created a lookup table that was keyed by file
type and contained pointers to the actual parse functions, and a
function that performed the actual lookup. It was structured somewhat
like this:

extern void parseGraFile(char *fileName);
extern void parsePWaveFile(char *fileName);
....

struct parseTable {
char *fileType;
void (*parse)(char *fileName);
};

static struct parseTable theTable[] = {{"GRA", parseGraFile}, {"PWV",
parsePWaveFile}, ...}

/*
* The following declaration reads as "lookup is a function returning a
pointer to a function
* taking a char * parameter and returning void"
*/
void (*lookup(char *fileType))(char *fileName)
{
size_t tableCount = sizeof theTable/sizeof theTable[0];
size_t i;

for (i = 0; i < tableCount; i++)
{
if (!strcmp(fileType, theTable.fileType))
return theTable.parse;
}

return NULL;
}

char *typeFromName(char *fileName)
{
/* parse the file type out of the file name and return it */
}

void parseFiles(const char **fileList, const size_t numFiles)
{
size_t i;

for (i = 0; i < numFiles; i++)
{
char *type;
void (*parser)(char *fileName);

type = typeFromName(fileList);
parser = lookup(type);
if (parser)
{
parser(fileList);
}
else
{
/* handle unrecognized file type */
}
}
}

Basically, the right parsing function would be called based on the file
type. The advantage to this approach is that you don't have to hack
the main application logic every time a new file type is added or
removed; you just update the lookup table.
 
D

Dave Thompson

On 5 Mar 2006 06:25:56 -0800, "John Bode" <[email protected]>
wrote:
This declares write as a pointer to a function taking 4 arguments and
returning an int. As to *why* you want to do this, there are a couple
of reasons:

1. You can pass a pointer to a function as a parameter to another
function; this is known as a callback, and is useful in a number of
contexts. The canonical example is the qsort() library function, which
can sort 1D arrays elements of any type. Here's how it's used:

/*
* prototype for qsort() as found in stdlib.h
*
* void qsort(void *base, size_t count, size_t size, int (*cmp)(const
void *, const void *));
*/
#include <stdlib.h>
#include <string.h>

int compareInts(const void *arg1, const void *arg2)
{
int *a = arg1;
int *b = arg2;
These need to be const int * to avoid a constraint violation and
diagnostic. And should be anyway, since a comparison routine should
not be changing the things it compares, at least not simple things.

int compareMyStructs(const void *arg1, const void *arg2)
{
MyStruct *a = arg1;
MyStruct *b = arg2;
ditto.

/*
* Assume the key value for MyStruct is a character string
*/
char *key1 = a->getKey();
char *key2 = b->getKey();
Perhaps ditto. And while it is certainly possible to have function
pointers in a struct, unless they vary, it would be more common to
have something more like:
const char *key1 = MyStruct_getKey (a); /* etc. */

Or even:
/*unconst*/ char key1 [KEY_SIZE], ...
MyStruct_getKey (a, key1); ...
if (strcmp(a, b) < 0)
return -1;
else if (strcmp(a, b) > 0)
return 1;
else
return 0;

The qsort comparator is only required to return <0/0/>0, not
specifically -1/0/+1, so you can just return strcmp (a, b).

<snip rest>

- David.Thompson1 at worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top