Function declarations

B

BartC

I have a C code generator that likes to insert lots of parentheses in type
declarations (rather than truly understand how they work).

But when declaring a function returning a pointer:

int (*fn) (void);

int (*fn) (void ) {return NULL;}

the prototype works, but not the definition (it's a syntax error). How do I
have to change the latter to make it compile?

Everywhere else the extra parentheses don't seem to be a problem.


Thanks.
 
K

Keith Thompson

BartC said:
I have a C code generator that likes to insert lots of parentheses in type
declarations (rather than truly understand how they work).

But when declaring a function returning a pointer:

int (*fn) (void);

int (*fn) (void ) {return NULL;}

the prototype works, but not the definition (it's a syntax error). How do I
have to change the latter to make it compile?

Everywhere else the extra parentheses don't seem to be a problem.

That's not a valid function definition.

Your first line declares an object `fn` of pointer-to-function type,
which is perfectly valid.

The declaration part of the function definition (the part outside
{...}) declares a pointer-to-function type. A function definition
has to declare something of function type, not pointer type.

You could drop the parentheses:

int fn(void) { return 0; }

Note that I've changed the return expression, since NULL is normally
used for pointers.

Or you might have something like this:

int func(void) { return 0; }
int (*fn)(void) = func;

I can't tell which of these would suit your purposes.
 
H

Heikki Kallasjoki

I have a C code generator that likes to insert lots of parentheses in type
declarations (rather than truly understand how they work).

But when declaring a function returning a pointer:

int (*fn) (void);

int (*fn) (void ) {return NULL;}

the prototype works, but not the definition (it's a syntax error). How do I
have to change the latter to make it compile?

That's not a function returning a pointer: that's a pointer to a
function (returning int):

$ cdecl
int (*fn) (void);
declare fn as pointer to function that expects (void) returning int;

int *fn(void) { ... } will (of course) work.
 
B

Ben Bacarisse

BartC said:
I have a C code generator that likes to insert lots of parentheses in
type declarations (rather than truly understand how they work).

But when declaring a function returning a pointer:

int (*fn) (void);

That's not what the above does. It declares (and, at file scope,
tentatively defines) a pointer to a function.
int (*fn) (void ) {return NULL;}

Returning NULL is peculiar but fits with what you say you intended.
the prototype works, but not the definition (it's a syntax error). How
do I have to change the latter to make it compile?

The latter, just like the former, declares a pointer, not a function.
You'd make it work by giving it a suitable initialiser:

int (*fn)(void) = f; /* for some f of the right type, of course */

but it seems that you intended to write a prototype and a definition of
a function that returns a pointer:

int *fn(void);
int *fn(void) { return NULL; }
Everywhere else the extra parentheses don't seem to be a problem.

They aren't a problem here either, it's just that you've mistaken what
they mean.

There *is* a symmetry problem with C's function definitions: you can use
a typedef of a function type to declare functions but not to define
them. For example, if you want to declare a whole bunch of functions of
the same type, it's easy:

typedef int binary_operator(int, int);

binary_operator add, sub, mul, div, rem, mod, exp;

and the typedef comes in hand if you have (as is likely) a table of
pointers to such functions. But when you come to define them, you can't
use the typedef name -- you have to repeat the types:

int add(int a, int b) { return a + b; }

It would be nice if you could use the typedef and add just the parameter
names. However, the "obvious" syntax is wrong:

binary_operator add(a, b) { return a + b; }

because binary_operator look like (well, is) the return type and not the
function type. You'd need a new form of function definition, maybe:

binary_operator add = (a, b) { return a + b; }

which, at least, looks like an initialiser. Far too fiddly to parse, I
imagine, and the use cases are too rare to register on the committee's
radar.
 
B

BartC

BartC said:
I have a C code generator that likes to insert lots of parentheses in type
declarations (rather than truly understand how they work).
int (*fn) (void);

int (*fn) (void ) {return NULL;}

OK, the replies are telling me these are both wrong! For what I'd intended
anyway.

The parentheses I insert automatically are needed to distinguish between:

int *a[]; // array of pointer to int
int *(a[]); // also array of pointer to int
int (*a)[]; // pointer to array of int

The code generator isn't clever enough to insert only when necessary.

However, playing with CDECL, and using the last example above as return
value from the function (as I want to see how parentheses work when they are
actually needed), I ended up with:

int (*fn(void ))[];
int (*fn(void ))[] {return 0;};

This last example is especially intriguing; I've never seen "[]" between a
function parameter list and the opening "{" before!

What this telling me though, is the parameter list needs to be taken inside
the declaration and be attached to the name, so I will experiment with that.
Maybe I can get to keep my parentheses.
 
B

Ben Bacarisse

BartC said:
BartC said:
I have a C code generator that likes to insert lots of parentheses
in type declarations (rather than truly understand how they work).
int (*fn) (void);

int (*fn) (void ) {return NULL;}

OK, the replies are telling me these are both wrong! For what I'd
intended anyway.

The parentheses I insert automatically are needed to distinguish between:

int *a[]; // array of pointer to int
int *(a[]); // also array of pointer to int
int (*a)[]; // pointer to array of int

The code generator isn't clever enough to insert only when necessary.

I don't think that will be a problem.
However, playing with CDECL, and using the last example above as
return value from the function (as I want to see how parentheses work
when they are actually needed), I ended up with:

int (*fn(void ))[];
int (*fn(void ))[] {return 0;};

This last example is especially intriguing; I've never seen "[]"
between a function parameter list and the opening "{" before!

What this telling me though, is the parameter list needs to be taken
inside the declaration and be attached to the name, so I will
experiment with that. Maybe I can get to keep my parentheses.

You can keep (or add) as many parentheses as you want but I suspect your
trouble is that you are adding them in a way that alters the intended
meaning.

The parameter list must be "syntactically attached" to the name but it
can be separated from it by redundant parentheses:

int f(void);
int (f)(void);
int ((f))(void);

are all the same. The rules for reading C types help here: you read
from the name outwards respecting balanced parentheses but otherwise
always reading to the right before reading to the left. You stop
reading to the right or to the left when you reach an opening or closing
bracket (or the end of declaration). In other words you read from the
inside out always finishing off a parenthesised part before moving on.
When you hit the ')' at the end of a parameter list, you can say "and
returning", otherwise just don't vocalise it:

int (*fn(void))[];
^ fn is a
^ function taking
^ no arguments
^ and returning
^ (silently change direction[1])
^ a pointer to
^ (silently change direction)
^ an array of
^ (silently change direction)
^ int

(This will look silly without a fixed-width font.)

Functions can't return array types but the syntax (and these rules) let
us know what that would look like. If at the point marked [1] we were
to see []s instead of ')' or ';' like this:

... *fn(void)[] ...

we'd have to say "and returning an array of".
 
A

Agnos

BartC said:
I have a C code generator that likes to insert lots of parentheses in
type declarations (rather than truly understand how they work).

But when declaring a function returning a pointer:

int (*fn) (void);

int (*fn) (void ) {return NULL;}

the prototype works, but not the definition (it's a syntax error).
How do I have to change the latter to make it compile?

Everywhere else the extra parentheses don't seem to be a problem.

You worked for a BIG manufacturer, and now you are nothing but the
throw-away slag on the molten iron of the machines that you assembled?
 
A

Agnos

Keith Thompson wrote:

Who cares what he wrote? Look at his sig(!):
Keith Thompson (The_Other_Keith) (e-mail address removed)
<http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

As far as I care, until he resolves his issues, I ignore his other forays.
 
K

Kaz Kylheku

Just kill the header:

Organization: Aioe.org NNTP Server

Almost nothing of value will be lost.

.... says the twit posting from eternal-september.org, which is another
free NNTP server, scarcely different from aoie.org.
 
A

Armstrong

Kaz said:
... says the twit posting from eternal-september.org, which is another
free NNTP server, scarcely different from aoie.org.

You tell him witch flag is better. I'll help you: wave a flag in a "witch's"
face, and you will KNOW she is a witch! (History shows, such crime).
 

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
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top