visual variable tipos tipo tiempo son solucionar sirven sirve significan sencillos que punteros puntero principales para operadores operaciones los long funciones estructura error ejercicios ejemplos ejecucion dim definicion decimales datos cuáles cursores con como cambiar cadenas arreglos aritmetica apuntadores c macros printf clang c11

c - tiempo - tipos de variables vba



Tipos de punteros incompatibles que pasan en la macro_Generic (2)

El siguiente código genera 2 advertencias que se describen en el título de la pregunta.

#include <stdio.h> static void _print_f(float *f){printf("float : %f/n", *f);} static void _print_i(int *i) {printf("int : %d/n", *i);} #define print(num) _Generic((num), / int* : _print_i(num), / float* : _print_f(num)) int main(void) { print((&(int){10})); print((&(float){10.f})); return 0; }

SALIDA:

int : 10 float : 10.000000

Lo sé, esta macro podría escribirse como la siguiente:

#define print(num) _Generic((num), / int* : _print_i, / float* : _print_f)(num)

y en ese caso, no habrá ninguna advertencia, sin embargo, mi ejemplo es un fragmento ficticio que escribí para demostrar el problema. En mi base de código real elegí la solución anterior, porque algunos otros "valores predeterminados" pero los argumentos específicos de tipo deben pasarse a la función seleccionada.

Entonces, la pregunta es: incluso si la macro funciona como debería y la salida es exactamente lo que espero, ¿por qué se generan las advertencias?

Banderas y Medio Ambiente:

/* Mac OS X 10.9.4 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) */ cc -Wall -v -g -std=c11 -fmacro-backtrace-limit=0 -I/usr/local/include -c -o build/tmp/main.o main.c

Actualización 1:

¡Olvidé pegar el rastreo completo! Aquí está el primero:

main.c:39:11: warning: incompatible pointer types passing ''int *'' to parameter of type ''float *'' [-Wincompatible-pointer-types] print((&(int){10})); ^~~~~~~~~~~~ main.c:31:23: note: expanded from macro ''print'' float* : _print_f(num)) ^ main.c:26:29: note: passing argument to parameter ''f'' here static void _print_f(float *f){printf("float : %f/n", *f);} ^

Y aquí está el segundo:

main.c:40:11: warning: incompatible pointer types passing ''float *'' to parameter of type ''int *'' [-Wincompatible-pointer-types] print((&(float){10.f})); ^~~~~~~~~~~~~~~~ main.c:30:23: note: expanded from macro ''print'' int* : _print_i(num), / ^ main.c:27:27: note: passing argument to parameter ''i'' here static void _print_i(int *i) {printf("int : %d/n", *i);} ^

Actualización2:

Hasta que los desarrolladores de clang solucionen este error, aquí hay una fea solución para silenciar las advertencias, que funcionarán si todas las claves en la lista de assoc son tipos, O todos son punteros a tipos; y fallará si los tipos Y los punteros a los tipos también están en las teclas:

/* HACK: re-casting pointers to mute warnings */ #define print(num) _Generic((num), / int* : _print_i((int*)num), / float* : _print_f((float*)num))


Esto no es un error en Clang, pero desafortunadamente lo que requiere el estándar C11. Todas las ramas de una expresión primaria _Generic deben ser expresiones válidas y, por lo tanto, válidas en todas las circunstancias. El hecho de que solo una de las ramas sea evaluada, no está relacionado con esto.

Su versión alternativa es lo que C11 prevé para situaciones como esta: elija la función (y no la llamada evaluada) como resultado del tipo de expresión genérica, y aplique esa función a los argumentos.


CORRECCIÓN: Esto no es (por lo que puedo decir) un error en clang, sino una interpretación correcta de cómo se supone que debe comportarse _Generic . Solo se evalúa una de las asociaciones genéricas en una expresión de selección genérica , pero todas deben ser expresiones válidas. ( _Generic no actúa como una macro.)

Ver la respuesta de Jens Gustedt .

Esto definitivamente parece un error en el sonido. Estoy razonablemente seguro de que su código es válido C11. Veo lo mismo con la versión 3.4 en Linux Mint.

He reunido una demostración ligeramente simplificada :

#include <stdio.h> static void print_i(int i) { puts("int"); } static void print_ip(int *i) { puts("int*"); } #define print(num) _Generic((num), / int : print_i(num), / int* : print_ip(num)) int main(void) { int i = 10; print(i); print(&i); }

La salida es correcta, pero recibo las siguientes advertencias:

c.c:12:11: warning: incompatible integer to pointer conversion passing ''int'' to parameter of type ''int *''; take the address with & [-Wint-conversion] print(i); ^ & c.c:8:23: note: expanded from macro ''print'' int* : print_ip(num)) ^ c.c:4:27: note: passing argument to parameter ''i'' here static void print_ip(int *i) { puts("int*"); } ^ c.c:13:11: warning: incompatible pointer to integer conversion passing ''int *'' to parameter of type ''int''; remove & [-Wint-conversion] print(&i); ^~ c.c:7:22: note: expanded from macro ''print'' int : print_i(num), / ^ c.c:3:25: note: passing argument to parameter ''i'' here static void print_i(int i) { puts("int"); } ^ 2 warnings generated.