c 函数是否可以同时接受双参数和长双参数?
Is it possible for a c function to accept both double and long double arguments?
我在文件 mag.c 中有一个函数 mag,用于计算数组的大小。
#include <math.h>
#include "mag.h"
long double mag(long double arr[], int len){
long double magnitude=0;
for(int i=0;i<len;i++)
magnitude+=pow(arr[i],2);
magnitude=pow(magnitude,0.5);
return magnitude;
}
我希望它接受双精度和长双精度数组。我在别处读过(例如 ),如果参数与函数声明不匹配,它将被隐式转换为正确的类型。我写了一个函数 test.c 来测试这个。
#include <math.h>
#include <stdio.h>
#include "mag.h"
int main(){
double arr1[3]={0.0,1.1,2.2};
printf("%Lf",mag(arr1,3));
return 0;
}
但是,这产生了一个错误
test.c: In function ‘main’:
test.c:7:19: warning: passing argument 1 of ‘mag’ from incompatible pointer type [-Wincompatible-pointer-types]
printf("%Lf",mag(arr1,3));
^~~~
In file included from test.c:3:
mag.h:4:29: note: expected ‘long double *’ but argument is of type ‘double *’
long double mag(long double arr[], int len);
将数组声明为 long double 允许函数正常工作。我还尝试更改头文件中的参数类型,但返回的是 -nan。有没有什么简单的方法可以让 mag 函数同时接受双参数和长双参数,或者制作两个单独的函数会更简单吗? (如果我需要为 double 和 long double 参数创建单独的函数,我需要为很多文件执行此操作。)
你说得对,如果可能的话,函数参数将隐式转换为预期类型。但是,这种隐式转换不会转换函数参数指向的对象或数组。它只会转换函数参数本身(即指针)。
因此,在 C 中,您将不得不创建两个单独的函数,或者做一些丑陋的事情,比如创建一个以 void *
作为参数的函数,该函数将被解释为 long double *
或 double *
取决于附加参数的值:
#include <math.h>
#include <stdbool.h>
long double mag( void *arr, int len, bool is_long )
{
long double magnitude=0;
if ( is_long )
{
//interpret array as "long double"
long double *arr_longdouble = arr;
for( int i=0; i<len; i++ )
magnitude += powl( arr_longdouble[i], 2 );
}
else
{
//interpret array as "double"
double *arr_double = arr;
for( int i=0; i<len; i++ )
magnitude += powl( arr_double[i], 2 );
}
magnitude = powl( magnitude, 0.5 );
return magnitude;
}
但是,C++(但不是 C)拥有您想要完成的目标的理想解决方案是毫无价值的。用那种语言,你可以制作一个 function template:
template <typename T>
T mag( T arr[], int len )
{
T magnitude = 0;
for( int i=0; i<len; i++ )
magnitude += pow( arr[i], 2 );
magnitude = pow( magnitude, 0.5 );
return magnitude;
}
在此函数中,数据类型 T
可以是 double
或 long double
(或任何其他数据类型,只要代码可以编译)。编译器将根据需要自动为您创建一个 double
and/or 一个 long double
版本的函数。
... it will be implicitly converted to the correct type. I wrote a function test.c to test this.
这适用于某些参数,例如 double
转换为 long double
,但不适用于 double *
转换为 long double *
。
C 有 _Generic
就是为了这种编程。使用 mag(arr, len) _Generic((arr) ...
控制代码选择。
我建议还对 long double
个对象使用 long double
函数和 long double
常量。
long double mag_long_double(const long double arr[], int len) {
long double magnitude = 0;
for (int i = 0; i < len; i++)
magnitude += powl(arr[i], 2); // powl
magnitude = sqrtl(magnitude);
return magnitude;
}
double mag_double(const double arr[], int len) {
double magnitude = 0;
for (int i = 0; i < len; i++)
magnitude += pow(arr[i], 2);
magnitude = sqrt(magnitude);
return magnitude;
}
#define mag(arr, len) _Generic((arr), \
long double *: mag_long_double, \
double *: mag_double \
)((arr), (len))
int main(void) {
double arr1[3] = {0.0, 1.1, 2.2};
printf("%f\n",mag(arr1,3));
long double arr2[3] = {0.0, 3.3L, 4.4L}; // Add 'L'
printf("%Lf\n",mag(arr2,3));
return 0;
}
输出
2.459675
5.500000
我在文件 mag.c 中有一个函数 mag,用于计算数组的大小。
#include <math.h>
#include "mag.h"
long double mag(long double arr[], int len){
long double magnitude=0;
for(int i=0;i<len;i++)
magnitude+=pow(arr[i],2);
magnitude=pow(magnitude,0.5);
return magnitude;
}
我希望它接受双精度和长双精度数组。我在别处读过(例如
#include <math.h>
#include <stdio.h>
#include "mag.h"
int main(){
double arr1[3]={0.0,1.1,2.2};
printf("%Lf",mag(arr1,3));
return 0;
}
但是,这产生了一个错误
test.c: In function ‘main’:
test.c:7:19: warning: passing argument 1 of ‘mag’ from incompatible pointer type [-Wincompatible-pointer-types]
printf("%Lf",mag(arr1,3));
^~~~
In file included from test.c:3:
mag.h:4:29: note: expected ‘long double *’ but argument is of type ‘double *’
long double mag(long double arr[], int len);
将数组声明为 long double 允许函数正常工作。我还尝试更改头文件中的参数类型,但返回的是 -nan。有没有什么简单的方法可以让 mag 函数同时接受双参数和长双参数,或者制作两个单独的函数会更简单吗? (如果我需要为 double 和 long double 参数创建单独的函数,我需要为很多文件执行此操作。)
你说得对,如果可能的话,函数参数将隐式转换为预期类型。但是,这种隐式转换不会转换函数参数指向的对象或数组。它只会转换函数参数本身(即指针)。
因此,在 C 中,您将不得不创建两个单独的函数,或者做一些丑陋的事情,比如创建一个以 void *
作为参数的函数,该函数将被解释为 long double *
或 double *
取决于附加参数的值:
#include <math.h>
#include <stdbool.h>
long double mag( void *arr, int len, bool is_long )
{
long double magnitude=0;
if ( is_long )
{
//interpret array as "long double"
long double *arr_longdouble = arr;
for( int i=0; i<len; i++ )
magnitude += powl( arr_longdouble[i], 2 );
}
else
{
//interpret array as "double"
double *arr_double = arr;
for( int i=0; i<len; i++ )
magnitude += powl( arr_double[i], 2 );
}
magnitude = powl( magnitude, 0.5 );
return magnitude;
}
但是,C++(但不是 C)拥有您想要完成的目标的理想解决方案是毫无价值的。用那种语言,你可以制作一个 function template:
template <typename T>
T mag( T arr[], int len )
{
T magnitude = 0;
for( int i=0; i<len; i++ )
magnitude += pow( arr[i], 2 );
magnitude = pow( magnitude, 0.5 );
return magnitude;
}
在此函数中,数据类型 T
可以是 double
或 long double
(或任何其他数据类型,只要代码可以编译)。编译器将根据需要自动为您创建一个 double
and/or 一个 long double
版本的函数。
... it will be implicitly converted to the correct type. I wrote a function test.c to test this.
这适用于某些参数,例如 double
转换为 long double
,但不适用于 double *
转换为 long double *
。
C 有 _Generic
就是为了这种编程。使用 mag(arr, len) _Generic((arr) ...
控制代码选择。
我建议还对 long double
个对象使用 long double
函数和 long double
常量。
long double mag_long_double(const long double arr[], int len) {
long double magnitude = 0;
for (int i = 0; i < len; i++)
magnitude += powl(arr[i], 2); // powl
magnitude = sqrtl(magnitude);
return magnitude;
}
double mag_double(const double arr[], int len) {
double magnitude = 0;
for (int i = 0; i < len; i++)
magnitude += pow(arr[i], 2);
magnitude = sqrt(magnitude);
return magnitude;
}
#define mag(arr, len) _Generic((arr), \
long double *: mag_long_double, \
double *: mag_double \
)((arr), (len))
int main(void) {
double arr1[3] = {0.0, 1.1, 2.2};
printf("%f\n",mag(arr1,3));
long double arr2[3] = {0.0, 3.3L, 4.4L}; // Add 'L'
printf("%Lf\n",mag(arr2,3));
return 0;
}
输出
2.459675
5.500000