是否可以"typedef"(各种)一个函数原型?

teh*_*ftw 6 c typedef function-prototypes

我有多个彼此相似的函数 - 它们接受相同的参数,并返回相同的类型:

double mathFunction_1(const double *values, const size_t array_length);
Run Code Online (Sandbox Code Playgroud)

我已经使用了typedef'd指向那些函数的指针,因为我将它们存储为一个数组,以便在相同的数据上轻松使用它们,映射它们等:

typedef double (* MathFunction_ptr )(const double *, const size_t);

double proxy(MathFunction_ptr mathfun_ptr, const double *values, const size_t array_length);
Run Code Online (Sandbox Code Playgroud)

我想要实现的是与声明和定义函数类似的易用性,就像我已经使用指针一样.


因此,我正在考虑使用类似的typedef来让我更容易编写实际的函数.我尝试这样做:

// declaration
typedef double MathFunction (const double *values, const size_t array_length);
MathFunction mathFunction_2;
Run Code Online (Sandbox Code Playgroud)

以下方法部分起作用.它允许我在声明中"保存一些键击",但是必须完全输入定义.

double mathFunction_2(const double *values, const size_t array_length)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

我通过搜索更多这个问题找到的是:函数原型typedef可以用在函数定义中吗?

然而,它没有提供很多替代方案,只是重申我根据标准禁止在我的其他实验中尝试做的事情.它提供的唯一选择是使用

#define FUNCTION(name) double name(const double* values, size_t array_length)
Run Code Online (Sandbox Code Playgroud)

这听起来很笨(因为我对使用预处理器持谨慎态度和怀疑态度).

我正在尝试做什么的替代方案是什么?


我试过的另外两种方法不起作用(而且,正如我刚才所读,根据C标准6.9.1禁止和绝对错误):

1.这种方法不起作用,因为这意味着我告诉它定义一个变量mathFunction_2(我相信变量被视为一个指针,虽然我还不太了解它),就像一个函数:

MathFunction mathFunction_2
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

2.这种方法不起作用,因为它意味着我告诉它创建一个返回函数的函数(在C语言中不可接受):

MathFunction mathFunction_2()
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

Bas*_*tch 8

您可以使用a typedef 作为签名(另请参阅此内容):

typedef double MathFunction_ty (const double *, const size_t);
Run Code Online (Sandbox Code Playgroud)

然后声明相同签名的几个函数:

MathFunction_ty func1, func2;
Run Code Online (Sandbox Code Playgroud)

或者使用它声明一些函数指针:

MathFunction_ty* funptr;
Run Code Online (Sandbox Code Playgroud)

等......所有这些都在C11中,读取n1570.

但是必须完全输入定义.

当然,因为你需要给一个名字到每个形参(并且这样的名字是不是该函数的类型的一部分)在函数的定义.因此

double func1(const double*p, const size_t s) {
  return (double)s * p[0];
}
Run Code Online (Sandbox Code Playgroud)

double func1(cont double*arr, const size_t ix) {
   return arr[ix];
}
Run Code Online (Sandbox Code Playgroud)

具有相同的类型(MathFunction_ty上面表示的类型),即使它们的形式参数(或形式参数)的命名方式不同.

您可能滥用预处理器并使用丑陋的宏来缩短此类函数的定义:

// ugly code:
#define DEFINE_MATH_FUNCTION(Fname,Arg1,Arg2) \
   double Fname (const double Arg1, const size_t Arg2)
DEFINE_MATH_FUNCTION(func1,p,s) { return (double)s * p[0]; }
Run Code Online (Sandbox Code Playgroud)

我发现这样的代码令人困惑且难以理解.我不建议这样编码,即使它确实可行.但有时我会编写类似的东西(出于其他原因).

(顺便说一句,想象一下,如果C 要求每个第一个正式参数被命名$1,每个第二个正式参数被命名$2等等......;恕我直言,这将使得编程语言更不易读;所以正式参数的名称对人类读者来说很重要,甚至如果系统名称会使编译器的生命更简单)

另请阅读关于 λ演算,匿名函数(C没有它们但C++有lambda表达式),闭包(它们不是 C函数,因为它们具有封闭值,因此混合代码与数据; C++具有std::function-s),回调("模仿"闭包的必要约定)...阅读SICP,它将提高你对C或C++的思考.再看看那个答案.


Typ*_*eIA 3

不幸的是,在 CI 中,不相信有任何方法可以在不使用预处理器宏的情况下完成您所要求的操作,至少我个人同意您的评估,即它们很笨重并且应该避免(尽管这是一个意见问题,并且是开放的)进行辩论)。

在 C++ 中,您可以利用autolambda 中的参数

您在此处显示的示例函数签名实际上并不复杂,我不会担心感知到的重复。如果签名要复杂得多,我会将其视为“代码味道”,您的设计可以改进,并且我会将精力集中在那里,而不是放在缩短声明的语法方法上。这里的情况并非如此。

  • @tehftw 是的,你所做的在我的书中很好。使用“typedef”作为指向与某个签名匹配的函数的指针在 C 中很常见并被接受。并且拥有许多具有相同签名的函数也没有问题,即使您必须将它们全部输入出来很烦人! (2认同)