¿El proceso de retorno convierte / convierte el tipo requerido en un resultado de acuerdo con el estándar C, o solo se admite en ciertas implementaciones?

Me di cuenta que

float f; [..] printf("%i\n", f); 

no es razonable

pero

 printf("%i\n", (int)f); 

es

pero también

 int func(float f) { return f; } 

está bien en

 printf("%i\n", func(f)); 

Es esa conversión / conversión que se realiza mediante el proceso de devolución o la función admitida por el estándar, o lo ideal es que lo necesite

 int func(float f) { return (int) f; } 

?

La conversión es estándar. La parte relevante de la norma ISO C99 se encuentra en la sección 6.8.6.4, párrafo 3:

Si la expresión tiene un tipo diferente del tipo de retorno de la función en la que aparece, el valor se convierte como si se asignara a un objeto que tiene el tipo de retorno de la función.

Entonces se convierte implícitamente, de la misma manera que está en esta asignación:

 float f = 3.0f; int i; i = f; 

Las conversiones permitidas son:

  • el tipo de retorno tiene un tipo aritmético calificado o no calificado y la expresión tiene un tipo aritmético;
  • el tipo de retorno tiene una versión calificada o no calificada de una estructura o tipo de unión compatible con el tipo de expresión;
  • el tipo de retorno y la expresión son punteros a versiones calificadas o no calificadas de tipos compatibles, y el tipo de retorno tiene todos los calificadores del tipo de expresión;
  • uno de los tipos o expresiones de retorno es un puntero a un objeto o tipo incompleto y el otro es un puntero a una versión de void calificada o no calificada, y el tipo de retorno tiene todos los calificadores del tipo de expresión;
  • el tipo de retorno es un puntero y la expresión es una constante de puntero nula; o
  • el tipo de retorno tiene el tipo _Bool y la expresión es un puntero.

(Su ejemplo coincide con el primero, tanto int como float son tipos aritméticos)

Generalmente, cuando una expresión tiene un tipo numérico determinado, y su contexto espera un tipo numérico diferente, la conversión apropiada sucederá automáticamente. Esto se aplica en casos tales como:

 void f(float); void g(long); int i = 3; f(i); /*function call, with a prototype in scope*/ g(i); /*ditto*/ double d = i; /*assignment*/ 

Este principio también se aplica a la expresión instrucción de return .

Este principio no se aplica a funciones variadas como printf . La razón es que las conversiones adecuadas dependen de la cadena de formato, y el comstackdor no está obligado a analizar la cadena de formato; de hecho, si el formato no es un literal de cadena, el comstackdor generalmente no puede analizarlo. Así que todos los lanzamientos son necesarios en la siguiente llamada a printf :

 int i = 3; float f = 1.5; printf("%ld %f %d\n", (long)i, (double)i, (int)f); 

Sin embargo, debido a las promociones (las char y short se promocionan a int , float se promueve a double ) y al hecho de que %c espera un int , no se necesitan conversiones en la siguiente llamada a printf :

 char c = 'a'; float f = 1.5; printf("%c %d %f", c, c, f);