Tengo una función, mag, en un archivo mag.c que calcula la magnitud de una matriz.
#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; }Me gustaría que aceptara matrices dobles y dobles largas. He leído en otro lugar (por ejemplo , aquí ) que si un argumento no coincide con la declaración de la función, se convertirá implícitamente al tipo correcto. Escribí una función test.c para probar esto.
#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; }Sin embargo, esto produjo un error.
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);Declarar la matriz como un doble largo permite que la función funcione correctamente. También intenté cambiar el tipo de argumento en el archivo de encabezado, pero devolvió -nan. ¿Hay alguna manera fácil de hacer que la función mag acepte argumentos dobles y dobles largos, o sería más simple hacer 2 funciones separadas? (Si necesito hacer funciones separadas para argumentos dobles y dobles largos, necesitaría hacer esto para muchos archivos).
... se convertirá implícitamente al tipo correcto. Escribí una función test.c para probar esto.
Esto funciona para algunos argumentos como double convertido en long double , pero no double * convertido en long double * .
C tiene _Generic solo para este tipo de programación. Use mag(arr, len) _Generic((arr) ... para dirigir la selección de código.
Recomiendo usar también funciones 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; }Producción
2.459675 5.500000Tiene razón en que un argumento de función se convertirá implícitamente al tipo esperado, si es posible. Sin embargo, esta conversión implícita no irá tan lejos como para convertir el objeto o la matriz a la que apunta el argumento de la función. Solo convertirá el argumento de la función en sí (es decir, el puntero).
Por lo tanto, en C, tendrá que crear dos funciones separadas, o hacer algo feo, como crear una sola función que tome un void * como argumento, que se interpretará como un long double * o un double * dependiendo de la valor de un argumento adicional:
#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; }Sin embargo, no vale nada que C ++ (pero no C) tenga la solución ideal para lo que desea lograr. En ese idioma, puede hacer una plantilla de función única:
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; } En esta función, el tipo de datos T puede ser un double o un long double (o cualquier otro tipo de datos, siempre que se compile el código). El compilador creará automáticamente una versión double y/o long double de la función para usted, según sea necesario.