error: no se puede convertir ‘double *’ a ‘char *’ para el argumento ‘1’ a ‘void swap (char *, char *, unsigned int)’

#include  void swap( char* pA, char* pB, unsigned tam) { for( unsigned i = 0; i < tam; i++) { char tmp = *pA; *pA = *pB; *pB = tmp; pA = pA + 1; pB = pB + 1; } } int main(int argc, char** argv) { double a = 1.0; double b = 2.0; printf("linea: %d - antes a(%f) b(%f)\n", __LINE__, a, b); swap(&a, &b, sizeof(double)); //This line gives the error printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b); } 

Cuando llamo al método de intercambio, aparece el mensaje de error en el título, ¿alguna idea de por qué? Vi muchas otras publicaciones con soluciones, pero ninguna de ellas solucionó este problema.

Hay varias formas de escribir una función de intercambio genérico. Si se usará solo para un tipo (por lo que no es necesario que sea genérico), el argumento de tamaño no es necesario y puede pasar punteros del tipo relevante ( double * en la pregunta) e intercambiar utilizando la dirección indirecta.

 extern void double_swap(double *d1, double *d2); void double_swap(double *d1, double *d2) { double d = *d1; *d1 = *d2; *d2 = d; } 

Bien podría haber ventajas para convertir eso en:

 static inline void double_swap(double *d1, double *d2) { double d = *d1; *d1 = *d2; *d2 = d; } 

Esto podría colocarse en un encabezado y usarse con seguridad.

Si se usará para varios tipos, debe usar void * en los argumentos de la función (y size_t para el tamaño del tipo).

 /* ** This declaration belongs in a header if there is more than one ** source file that uses it. If there is only one file, then it ** should be declared and defined as a static function. If the ** header doesn't include any other headers that define size_t, ** it should #include  as that's the smallest header ** that does define size_t. You could make the function static ** inline instead of extern, even if it is in a header. */ extern void generic_swap(void *v1, void *v2, size_t size); /* Implementation 1: Using VLA */ void generic_swap(void *v1, void *v2, size_t size) { char sp[size]; memmove(sp, v1, size); memmove(v1, v2, size); memmove(v2, sp, size); } 

Puedes usar memcpy() si no te importa vivir peligrosamente (probablemente deberías agregar restrict a los tipos de puntero v1 y v2 si lo haces). Una vez más, la función probablemente podría estar static inline con buenos resultados, lo que también se aplica a las otras implementaciones a continuación.

Si no te gusta la idea de que se asignen grandes objetos en la stack, puedes copiar los datos en trozos, pero tienes que trabajar un poco más duro.

 enum { CHUNK_SIZE = 64 }; static inline size_t min_size(size_t x, size_t y) { return (x < y) ? x : y; } /* Implementation 2: Using a fixed size buffer */ void generic_swap(void *v1, void *v2, size_t size) { unsigned char sp[CHUNK_SIZE]; unsigned char *p1 = v1; unsigned char *p2 = v2; size_t chunk; while ((chunk = min_size(size, CHUNK_SIZE)) != 0) { memmove(sp, p1, chunk); memmove(p1, p2, chunk); memmove(p2, sp, chunk); p1 += chunk; p2 += chunk; size -= chunk; } } 

A pesar de todo lo que permite GCC, el estándar C dice que no puede incrementar un void * porque no hay un tamaño conocido para incrementarlo. Es por eso que los punteros se convierten a caracteres unsigned char * . Claramente, puede ajustar el tamaño del trozo para adaptarse a su sistema. Cualquier potencia de 2 en el rango 16..1024 es probablemente utilizable, y se pueden usar otros valores distintos de una potencia de 2 si lo prefiere.

Si no le importa la sobrecarga, puede asignar dinámicamente un búfer:

 /* Implentation 3: Using dynamic memory allocation */ void generic_swap(void *v1, void *v2, size_t size) { char *sp = malloc(size); if (sp != 0) { memmove(sp, v1, size); memmove(v1, v2, size); memmove(v2, sp, size); free(sp); } } 

Si falla la asignación de memoria, el intercambio no se produce. Eso es malo, por lo que puede recurrir al 'búfer de tamaño fijo e intercambio en trozos', pero probablemente sea más rápido que esto de todos modos.

Yo usaría la Implementación 2 en lugar de la Implementación 3; La asignación de memoria dinámica es costosa. Probablemente usaría la Implementación 2 en lugar de la Implementación 1 ya que el costo adicional del bucle es mínimo y el uso de una cantidad fija de stack funciona bien. No he evaluado ninguno de estos para verificar mis afirmaciones. (Si está intercambiando grandes cantidades de datos del tamaño de un megabyte, probablemente debería volver a pensar, use punteros en su lugar. Si solo está intercambiando fragmentos más pequeños, la Implementación 1 es simple y segura).

Con cualquiera de las implementaciones de intercambio genérico, su progtwig principal se convierte en:

 int main(void) { double a = 1.0; double b = 2.0; printf("linea: %d - antes a(%f) b(%f)\n", __LINE__, a, b); generic_swap(&a, &b, sizeof(double)); printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b); return 0; } 

Supongo que al menos la statement de generic_swap() está disponible antes del inicio de main() .

Tenga en cuenta que usar double_swap() o generic_swap() significa que no es necesario realizar generic_swap() en el código. Minimizar los lanzamientos es una buena idea ™.

Véase también Intercambio de elementos de matriz universal en C.

Bueno, su función está esperando un puntero a un carácter para los dos primeros argumentos

 void swap( char* pA, char* pB, unsigned tam) 

Pero estás pasando en punteros a doble

 double a = 1.0; double b = 2.0; swap(&a, &b, sizeof(double)); //This line gives the error 

Lo siguiente le permitiría intercambiar dos dobles, a menos que haya una razón específica por la que está intercambiando un byte a la vez:

 void swap(double *pA, double *pB, unsigned int tam) { double tmp = *pA; *pA = *pB; *pB = tmp; } 

Me sale el mensaje de error en el título? Debido a que está pasando una dirección de doble variable y capturando con char* comstackdor está diciendo

se esperaba ‘char *’ pero el argumento es de tipo ‘double *’.

Por lo tanto, tiene dos formas de typecast la dirección de variable doble como char* o capturar con double* .

Caso 1:

 void swap( double* pA, double* pB, unsigned int tam) { double tmp = *pA; *pA = *pB; *pB = tmp; } int main(int argc, char** argv) { double a = 1.0; double b = 2.0; printf("linea: %d - antes a(%f) b(%f)\n", __LINE__, a, b); swap(&a, &b, sizeof(double)); //This line gives the error printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b); return 0; } 

Caso 2: – La segunda forma es encaminar la dirección de la variable doble como char* enviarla a swap()

 void swap( char *pA, char *pB, unsigned int tam) { for( unsigned i = 0; i < tam; i++) { char tmp = *pA; *pA = *pB; *pB = tmp; pA = pA + 1; pB = pB + 1; } } int main(int argc, char** argv) { double a = 1.0; double b = 2.0; printf("linea: %d - antes a(%f) b(%f)\n", __LINE__, a, b); swap((char*)&a, (char*)&b, sizeof(double)); //typecast &a to (char*)&a printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b); return 0; }