【问题标题】:Can a function prototype typedef be used in function definitions?可以在函数定义中使用函数原型 typedef 吗?
【发布时间】:2011-06-02 06:40:31
【问题描述】:

我有一系列具有相同原型的函数,比如说

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 是一个函数类型。

【问题讨论】:

    标签: c typedef function-declaration


    【解决方案1】:

    您不能使用函数类型的 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: 函数可以共享一个 typedef,但具有不同名称的参数 - 这些名称不是函数签名的一部分,如果声明不是定义的一部分,甚至可以省略
    【解决方案2】:

    typedef 定义了一个类型,而不是标题(源代码文本)。如果您需要分解标题的代码,则必须使用#define(尽管我不推荐)。

    ([已编辑] 第一个有效的原因是它没有定义原型——它定义了typedef 定义的类型的变量,这不是你想要的。)

    【讨论】:

    • 不,这不是指针的类型。那将是typedef int (*SpFunc)(int a, int b);。并且由于声明是有效的,它是一个正确的函数类型。问题是为什么我不能用它来定义。
    • 糟糕,抱歉,没有看到缺少星号。谢谢指正。
    • 这是什么反应?这是页面上唯一提到“标题”的地方。
    • @JimBalter:这是对这个问题的回应。他试图使用 typedef 作为函数头。我说这是不可能的,因为 typedef 定义了一个类型,而不是一个标题。
    • 也就是说,它解释了为什么不能将语言语法更改为允许type name {body},如果可能的话,这将是一个可取的更改。你的答案是“为什么我不能这样做”的这些恼人的答案之一,它只是说“你不能这样做”(同时向 OP 讲授他们已经知道的内容),就好像语言定义是一个不可改变的原始事实没有韵律或理由的宇宙。
    猜你喜欢
    • 2014-01-17
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 2015-06-11
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多