函数原型typedef可以在函数定义中使用吗?

37

我有一系列具有相同原型的函数,例如:

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

现在,我想简化它们的定义和声明。当然,我可以使用这样的宏:

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

但我希望用C语言,所以我尝试使用存储类别修饰符typedef

typedef int SpFunc(int a, int b);

这个声明似乎可以正常工作:

SpFunc func1; // compiles

但不适用于定义:

SpFunc func1 {
  // ...
}

这会给我以下错误:

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

有没有正确的方法可以做到这一点,或者这是不可能的?根据我对C语言的理解,这应该是可行的,但为什么它不起作用呢?


请注意,gcc理解我想要做的事情,因为如果我写下

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

它告诉我

error: function 'func1' is initialized like a variable

这意味着gcc理解SpFunc是一个函数类型。

2个回答

47

使用typedef定义函数类型是不被允许的。这是明确禁止的——请参考6.9.1/2和相关脚注:

在函数定义中声明的标识符(即函数名)必须具有函数类型,如函数定义的声明部分所指定的那样。

意图是函数定义中的类型类别不能从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

我对此感到担心。谢谢您确认了这一点。这背后是否有任何合理性?在我看来,这是一个有用的功能。 - bitmask
8
函数可以共用一个typedef,但可以有不同命名的参数。这些名称不属于函数签名的一部分,即使声明不在定义的范围内,也可以省略它们。 - Christoph

0

typedef 定义一个类型,而不是头文件(即源代码文本)。如果您需要将头文件的代码分解出来,您必须使用 #define(尽管我不建议这样做)。

([已编辑] 第一个可行的原因是它没有定义原型 - 它正在定义由 typedef 定义的类型的变量,而这不是您想要的。)


1
不,这不是指针类型。那应该是 typedef int (*SpFunc)(int a, int b);。既然声明有效,它就是一个正确的函数类型。问题是为什么我不能用它来定义。 - bitmask
这是对什么的回应?这是页面上唯一提到“header”的地方。 - Jim Balter
@JimBalter:这是对问题的回应。他试图将typedef用作函数头。我说这是不可能的,因为typedef定义了一种类型,而不是一个头文件。 - user541686
在您的回答中,您写道“头文件(即源代码文本)”--这是C语言中使用该词的方式,但与问题无关。现在您说“函数头”...在C语言中没有这样的东西,但是您可能指的是一个函数声明符号。但您仍然完全错了...OP知道SpFunc是一种类型(“这意味着gcc理解SpFunc是一种函数类型”),并且它不能用于定义函数(因为会产生错误)。hsr的问题是为什么不能,如果有其他方法可以做到这一点。正确的答案已由Christoph的评论给出。 - Jim Balter
1
这就是为什么语言语法不能更改以允许 type name {body},如果可能的话,这将是一种理想的变化。你的回答是那些令人烦恼的“为什么我不能这样做”的答案之一,它只是说“你不能这样做”(同时向OP讲授他们已经知道的内容),好像语言定义是宇宙中不可改变的原始事实,没有任何道理。 - Jim Balter
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接