Can a function prototype typedef be used in function definitions?
Asked Answered
W

2

37

I have a series of functions with the same prototype, say

int func1(int a, int b) {
  // ...
}
int func2(int a, int b) {
  // ...
}
// ...

Now, I want to simplify their definition and declaration. Of course I could use a macro like that:

#define SP_FUNC(name) int name(int a, int b)

But I'd like to keep it in C, so I tried to use the storage specifier typedef for this:

typedef int SpFunc(int a, int b);

This seems to work fine for the declaration:

SpFunc func1; // compiles

but not for the definition:

SpFunc func1 {
  // ...
}

which gives me the following error:

error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token

Is there a way to do this correctly or is it impossible? To my understanding of C this should work, but it doesn't. Why?


Note, gcc understands what I am trying to do, because, if I write

SpFunc func1 = { /* ... */ }

it tells me

error: function 'func1' is initialized like a variable

Which means that gcc understands that SpFunc is a function type.

Wenn answered 1/1, 2011 at 17:45 Comment(0)
B
47

You cannot define a function using a typedef for a function type. It's explicitly forbidden - refer to 6.9.1/2 and the associated footnote:

The identifier declared in a function definition (which is the name of the function) shall have a function type, as specified by the declarator portion of the function definition.

The intent is that the type category in a function definition cannot be inherited from a typedef:

typedef int F(void); // type F is "function with no parameters
                     // returning int"
F f, g; // f and g both have type compatible with F
F f { /* ... */ } // WRONG: syntax/constraint error
F g() { /* ... */ } // WRONG: declares that g returns a function
int f(void) { /* ... */ } // RIGHT: f has type compatible with F
int g() { /* ... */ } // RIGHT: g has type compatible with F
F *e(void) { /* ... */ } // e returns a pointer to a function
F *((e))(void) { /* ... */ } // same: parentheses irrelevant
int (*fp)(void); // fp points to a function that has type F
F *Fp; //Fp points to a function that has type F
Bohemian answered 1/1, 2011 at 17:51 Comment(2)
I was afraid of this. Thanks for confirming this. Is there any rationale for this? It seems to me like a useful feature.Wenn
@bitmask: functions can share a typedef, but have differently-named arguments - the names are not part of the function signature and can even be omitted if the declaration is not part of the definitionUrbai
S
0

A typedef defines a type, not a header (which is source code text). You have to use #define (although I don't recommend it) if you need to factor out the code for the header.

([Edited] The reason the first one works is that it's not defining a prototype -- it's defining a variable of the type defined by the typedef, which isn't what you want.)

Summerwood answered 1/1, 2011 at 17:48 Comment(9)
No, this is not the type of a pointer. That would be typedef int (*SpFunc)(int a, int b);. And since the declaration is valid it is a proper function type. The question is why I cannot use it for the definition.Wenn
Oops sorry, didn't see the lack of the asterisk. Thanks for the correction.Summerwood
What's this a response to? It's the only mention of "header" on the page.Dominican
@JimBalter: It's a response to the question. He's trying to use a typedef as a function header. I'm saying it's not possible because a typedef defines a type, not a header.Summerwood
In your answer you wrote "header (which is source code text)" -- which is how the word is used in C, but has no bearing on the question. Now you say "function header" ... there's nothing called that in C, but presumably you mean a function declarator. But you're still completely off base ... the OP knows that SpFunc is a type ("Which means that gcc understands that SpFunc is a function type"), and that it can't be used to define a function (because it produces an error). hsr question is why not, and if there's some other way to do it. The correct answer is given by Christoph's comment above.Dominican
That is, it explains why the language syntax can't be changed to allow type name {body}, which would be a desirable change if it were possible. Yours is one of these annoying answers to "why can't I do this" that simply says "you can't do it" (while lecturing the OP on what they already know), as if the language definition were an unchangeable raw fact of the universe with no rhyme or reason.Dominican
P.S. I'm now guessing that by "header (which is source code text)" you weren't referring sensibly to a header file, you meant that, e.g., "int foo(int x)" is "source code text". But that's silly, because all parts of a source program, including "SpFunc" or "SpFunc func1" are "source code text". Of course the identifier "SpFunc" represents a type, but it is not itself a type. And the fact that "SpFunc" represents a type whereas "int foo(int x)" is just a syntax fragment is no reason why "int foo(int x)" could not be replaced with "SpFunc foo", if parameter names were part of the type.Dominican
@JimBalter: Everybody calls the function declarator a function header. Google around and you'll see tons of examples. But I'm not interested in (or even remembering enough for) arguing over a 6-year-old answer. You can keep the downvote. And (IIRC) welcome back to SO...Summerwood
a) I'm somebody and I don't. b) Who's arguing? I explained. Sorry if you can't deal with that. c) I haven't been gone, I just don't waste my time on C questions much any more.Dominican

© 2022 - 2024 — McMap. All rights reserved.