Variable declaration syntax

M

Michael Mair

Just before Christmas Chris Torek gave me some great advice about closures in C:
<http://groups.google.co.nz/[email protected]&output=gplain>

It includes this declaration of a function pointer variable called fp:
void (*fp)(void *);

What does the syntax above mean? I can only digest it as void * fp,
i.e. fp is a pointer to void.

fp is a pointer to a function returning void with a parameter list
consisting of a void *.

example:

void do_naught (void *);
void do_aught (void *);

.....

if (bla)
fp = do_aught;
else
fp = do_naught;

.....

/* Call the appropriate function through fp */
(*fp)(address);

.....

(*fp)(another_one);

.....

Advantage: You have not to ask for "bla" all the time but set
fp to the function you need.

If you have problems with C declarations such as
int (*p)[10];
vs
int *p[10];
you could search for the program cdecl which does nothing but
translate gibberish<->english where gibberish are C declarations.


Cheers
Michael
 
M

Mike Wahler

Adam Warner said:
Hi all,

Just before Christmas Chris Torek gave me some great advice about closures in C:
<http://groups.google.co.nz/[email protected]&outp
ut=gplain>

It includes this declaration of a function pointer variable called fp:
void (*fp)(void *);

What does the syntax above mean? I can only digest it as void * fp,
i.e. fp is a pointer to void.

'fp' is a pointer to a function which takes a single argument of type
'void *', and does not return a value. Search the web for a utility
called 'cdecl', which can take a declaration and tell you what
it means.


-Mike
 
A

Adam Warner

Hi Michael Mair,
fp is a pointer to a function returning void with a parameter list
consisting of a void *.

Thanks, I've finally grokked the syntax! As demonstrated below:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

unsigned int uinc1 (int x) { return ++x; }

unsigned int uinc2 (int x) { return x+=2; }

int main() {
//seed random number generator, portably
struct tm epoch;
epoch.tm_year=27; epoch.tm_mon=9-1; epoch.tm_mday=4; epoch.tm_isdst=-1;
epoch.tm_hour=0; epoch.tm_min=0; epoch.tm_sec=0;
clock_t current_clock=clock();
time_t current_time=time(&current_clock);
time_t time_since_epoch=mktime(&epoch);
double diff=difftime(current_time, time_since_epoch);
unsigned int seed=(unsigned int) diff;
printf("Seed is %u\n", seed);
srand(seed);

unsigned int (* fp) (int);
//Note: The pseudo random number generator may be poor
if (rand()%2==0) fp=uinc1; else fp=uinc2;
unsigned int sum=fp(1);
printf("Sum is %u\n", sum);

return 0;
}

BTW I found cdecl was packaged for Debian.

Regards,
Adam
 
J

john_bode

Adam said:
Hi all,

Just before Christmas Chris Torek gave me some great advice about closures in C:
It includes this declaration of a function pointer variable called fp:
void (*fp)(void *);

What does the syntax above mean? I can only digest it as void * fp,
i.e. fp is a pointer to void.

Here's how I break things like this down:

fp -- fp
*fp -- is a pointer
(*fp)() -- to a function
(*fp)(void *) -- taking a void * parameter
void (*fp)(void *) -- and returning void

C follows a "declaration mimics use" paradigm; namely, the declaration
of an object should look as much as possible like how it's actually
referenced in the code. For example, if you have a 10-element array of
int, you'd access the i'th element as a. So, the declaration should
look like this:

int a[10];

The type of a is "10-element array of int". However, the type
specifier "int" says nothing about the "array-ness" of a. To convey
this additional information, C uses "declarators". In the declaration
above, a[10] is the declarator, and a is the actual variable being
declared.

Similarly for pointers:

int *a;

a is a pointer to int; the "pointer-ness" is specified in the
declarator *a. Note that this is why

int* a, b;

doesn't work the way people expect -- the * indirection operator is
associated with the identifer a, *not* the type specifier int. This
also applies in typedefs:

typedef int (*foo)(int x, double y);

This declares foo as a synonym for the type "pointer to function taking
one int and one double parameter and returning int".


Operator precedence matters in declarators. There is a huge difference
between

int *a[10]; // 10-element array of pointers to int

and

int (*a)[10]; // Pointer to 10-element array of int

Similarly with function declarators:

int *f(void); // f is a function taking no parameters returning int *

vs.

int (*f){void); // f is a pointer to a function taking no parameters
and returning int

If you wanna get totally nuts:

f -- f
*f -- is a pointer
(*f)[10] -- to a 10-element array
*(*f)[10] -- of pointers
(*(*f)[10])() -- to functions
(*(*f)[10])(int x) -- taking a single int parameter
*(*(*f)[10])(int x) -- returning pointers
double *(*(*f)[10])(int x) -- to double.

And it would be called as

double *dp = (*(*f))(n);

Actually, C allows you to elide the dereference operator when calling a
function through a pointer, so the call looks like a normal function
call (i.e., given a function pointer f, you can write either (*f)(n) or
f(n) when you call it). But that means the above call could be written
as

double db = (*f)(n);

which I think just looks ugly.

So when you're confronted with a hairy declaration, just follow these
steps:

0. Separate the declarator from the type specifier and qualifiers;
1. Find the identifier in the declarator;
2. Work from the identifier out, observing rules of operator
precedence (subscript [] and function call () operators are evaluated
before the indirection * operator, unless expliticly grouped by
parens);
3. Apply type specifier and qualifiers.

If you don't have one, get a copy of the C language grammar (a good C
reference will have it as an appendix; I use Harbison & Steele's "C: A
Reference Manual", 5th ed.) and trace through declarator syntax.
Things will suddenly make a lot more sense.
 
C

Chris McDonald

If your system has the utility 'cdecl', you may find that to be of some
assistance, too.

______________________________________________________________________________
Dr Chris McDonald E: (e-mail address removed)
Computer Science & Software Engineering W: http://www.csse.uwa.edu.au/~chris
The University of Western Australia, M002 T: +618 6488 2533
Crawley, Western Australia, 6009 F: +618 6488 1089
 
A

Adam Warner

Hi john_bode,
C follows a "declaration mimics use" paradigm; namely, the declaration
of an object should look as much as possible like how it's actually
referenced in the code. For example, if you have a 10-element array of
int, you'd access the i'th element as a. So, the declaration should
look like this:

int a[10];

The type of a is "10-element array of int". However, the type
specifier "int" says nothing about the "array-ness" of a. To convey
this additional information, C uses "declarators". In the declaration
above, a[10] is the declarator, and a is the actual variable being
declared.

Similarly for pointers:

int *a;

a is a pointer to int; the "pointer-ness" is specified in the
declarator *a. Note that this is why

int* a, b;

doesn't work the way people expect -- the * indirection operator is
associated with the identifer a, *not* the type specifier int.


Thanks! I've printed out your post for later reference.

This part of C's declaration syntax borders upon insanity. I don't care
what *a is, I want to know the type of a itself! I only grokked what was
going on when I started writing "int *a" as "int * a", i.e. a itself is a
pointer to int. And now I know why no one writes that--because it breaks
down with the additional "declaration mimics use" paradigm.

Anybody would think the compiler's supposed to be omnipotent. How the heck
does "**a" mimic use if the majority of the time I'm only following the
first pointer, or passing a itself? It's an extra layer in the declaration
syntax that shouldn't be there!

Understand this explains a _lot_. I know why I've got to start writing
"int *a" instead of "int* a" or "int * a". In a saner world one would
actually declare the type of a variable instead of also having to second
guess how it should look when used.

Have fun,
Adam
 
J

john_bode

Adam said:
Hi john_bode,
C follows a "declaration mimics use" paradigm; namely, the declaration
of an object should look as much as possible like how it's actually
referenced in the code. For example, if you have a 10-element array of
int, you'd access the i'th element as a. So, the declaration should
look like this:

int a[10];

The type of a is "10-element array of int". However, the type
specifier "int" says nothing about the "array-ness" of a. To convey
this additional information, C uses "declarators". In the declaration
above, a[10] is the declarator, and a is the actual variable being
declared.

Similarly for pointers:

int *a;

a is a pointer to int; the "pointer-ness" is specified in the
declarator *a. Note that this is why

int* a, b;

doesn't work the way people expect -- the * indirection operator is
associated with the identifer a, *not* the type specifier int.


Thanks! I've printed out your post for later reference.


You might want to go with something a little more authoritative. ;-)

Seriously, get H&S, 5th edition, and study the grammar in Appendix B.
Declarations in C aren't quite as arbitrary as they appear at first
blush, but it helps to know *why* they are structured the way they are.
This part of C's declaration syntax borders upon insanity. I don't care
what *a is, I want to know the type of a itself! I only grokked what was
going on when I started writing "int *a" as "int * a", i.e. a itself is a
pointer to int. And now I know why no one writes that--because it breaks
down with the additional "declaration mimics use" paradigm.

Oh, yeah, declarators eat the big one. It took me over 10 years of
programming in C before I actually *understood* how they worked; it was
almost like getting an electric shock when I finally got it. Even now,
I read "int *a" as "a is a pointer to type int," instead of the more
correct "a is type pointer to int."

Yet more declarator fun (I think this is legit):

double (*(*(*(*f)(int x))[20])(double y, char (*z)(int h)))[100];

I think "insane" pretty much covers it.
Anybody would think the compiler's supposed to be omnipotent. How the heck
does "**a" mimic use if the majority of the time I'm only following the
first pointer, or passing a itself? It's an extra layer in the declaration
syntax that shouldn't be there!

It all has to do with the base type of the object. If you have an
object like

int **a;

then to get at the actual int value, you must use **a (or *a, or
a[j], depending). Of course, if you're only dealing with the
pointer itself, you're not going to be doing any dereferencing (such as
when you pass it to a function or something). But you still have to
declare it in terms of the base type.
Understand this explains a _lot_. I know why I've got to start writing
"int *a" instead of "int* a" or "int * a". In a saner world one would
actually declare the type of a variable instead of also having to second
guess how it should look when used.

Have fun,
Adam

Well, you don't *have* to write "int *a" instead of "int* a" or "int *
a"; it just more accurately reflects what's happening in the grammar.
 
K

Keith Thompson

Yet more declarator fun (I think this is legit):

double (*(*(*(*f)(int x))[20])(double y, char (*z)(int h)))[100];

I think "insane" pretty much covers it.

I don't think any language has a declaration syntax that would make
that legible. The right thing to do with something like that is to
break it up into multiple typedefs with painfully obvious names.
 
T

thesushant

(*fp ) indicates its a pointer to function and the argument u r passing
is of void pointer type and the return type is void ..
 

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

Forum statistics

Threads
474,159
Messages
2,570,883
Members
47,415
Latest member
SharonCran

Latest Threads

Top