如何将C数学运算符(+ - */%)传递给函数result = mathfunc(x,+,y);?

lus*_*oog 5 c

我正在C语言程序中为多精度整数编写一些数学例程,我希望能够轻松编写表达式,但用我自己的函数处理数学运算.所以我想要一些让我这样做的方法:

MPI x=mpi(5),y=mpi(6),z;
z=mpimath(x,+,y);
Run Code Online (Sandbox Code Playgroud)

通过以某种方式对角色进行编码,这在C中是否可行?我知道没有运算符重载所以它必须是函数调用,+-sign不能是函数名的一部分.

lus*_*oog 4

对的,这是可能的。

您可以使用宏连接到您的函数。宏为您提供了对代码物理外观的额外权力。特别是,您可以对参数进行字符串。您可以将任何完整的 C标记作为参数传递给宏。

所以做这样的事情:

#define mpimath(X,F,Y) (mpimath)(X,#F,Y)  /* stringify F */
Run Code Online (Sandbox Code Playgroud)

然后定义您的函数以接受char *参数。这将产生"+"参数的字符串+。通过对宏使用相同的名称,对该函数的调用将被该宏拦截,因此调用如下:

mpimath(p,*,r)   /* macro invocation */
Run Code Online (Sandbox Code Playgroud)

被扩展为

(mpimath)(p,"*",r)   /* function call */
Run Code Online (Sandbox Code Playgroud)

。函数名称周围的括号在这里并不是严格必要的,因为宏不允许递归,它会扩展为正确的东西。但是包装括号也是绕过任何宏定义显式调用函数的方法,因此我发现它有助于自我记录代码以在此处添加它们。

您可以使用类似的方法char *ops="+-*/"; int op=strstr(ops, f)-ops;将字符串映射到一个小整数(*),然后可以使用它来索引函数表。或者您可以取消引用字符串以获取char可以在switch.

MPI mpimath(MPI x, char *f, MPI y){
    switch(*f){
    case '+': //...
              break;
    case '-': //...
              break;
    //etc.
}
Run Code Online (Sandbox Code Playgroud)

或者您可以将取消引用移回宏中。在宏观上看起来有点奇怪。但我认为这使该功能看起来更好。

#define mpimath(X,F,Y) (mpimath)(X,*#F,Y) /* stringify and deref F */

MPI mpimath(MPI x, char f, MPI y){
    switch(f){
    case '+':
    //etc.
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:有关产生此分享您的知识问答对的实际代码的一些详细信息。

将运算符作为 a 传递的动机是char间接产生的,但从来没有以问题中所示的简化形式出现。该函数当前对宏的使用如下所示+

 BIN_MATH_FUNC(+,AV(z)[i],AV(a)[i],AV(w)[i],plusover,plusdomainI,plusdomainD)
Run Code Online (Sandbox Code Playgroud)

并且该宏还直接处理本机类型,例如intdouble。因此,mpi 函数需要适应的框架已经建立,以通过实际的 C 运算符(作为宏参数)来区分操作。所以现实情况不允许使用enum符号。


(*)礼貌地说,这不是一个好方法。该代码依赖编译器将两个字符串压缩到已编译程序的字符串表中的一个位置。这是编译器要做的一种典型的(甚至可以说是显而易见的)优化,但任何标准都不能保证这一点。将字符串文字分配给char *变量并在两个地方使用该变量会更好(尽管更详细)。strstr在对结果进行任何操作之前,您可以(并且可能应该)测试 for `NULL 的结果。