¿Por qué una declaración vacía funciona para definiciones con argumentos int pero no para argumentos flotantes?

4 minutos de lectura

avatar de usuario
compilador

Pensé que la diferencia es que declaration no tiene tipos de parámetros…

¿Por qué funciona esto?

int fuc();

int fuc(int i) {
  printf("%d", i);
  return 0;
}

pero esto falla al compilar:

int fuc();

int fuc(float f) {
  printf("%f", f);
  return 0;
}

con el mensaje:

error: tipos en conflicto para ‘fuc’. nota: un tipo de argumento que tiene una promoción predeterminada no puede coincidir con una declaración de lista de nombres de parámetros vacía

  • ¿Qué dice el compilador cuando falla al compilar el segundo ejemplo?

    – xappymah

    30 de marzo de 2011 a las 3:39

  • @xappymah, de gcc error: conflicting types for ‘fuc’. note: an argument type that has a default promotion can’t match an empty parameter name list declaration

    – John LaRooy

    30 de marzo de 2011 a las 5:05

  • Relacionado: stackoverflow.com/questions/12643202/…

    – Ciro Santilli Путлер Капут 六四事

    25 de abril de 2016 a las 9:09

avatar de usuario
ataúd de jerry

Una declaración:

int f();

… le dice al compilador que algún identificador (fen este caso) nombra una función y le dice el tipo de retorno de la función, pero no no especificar el número o tipo(s) de parámetro(s) que la función pretende recibir.

Un prototipo:

int f(int, char);

…es por lo demás similar, pero también especifica el número/tipo de parámetro(s) que la función debe recibir. Si no toma ningún parámetro, usa algo como int f(void) para especificar eso (ya que dejar los paréntesis vacíos es una declaración). Una definición de función de nuevo estilo:

int f(int a, char b) { 
    // do stuff here...
}

…también actúa como un prototipo.

Sin un prototipo en el ámbito, el compilador aplica promociones predeterminadas a los argumentos antes de llamar a la función. Esto significa que cualquier char o short ascendió a inty cualquier float es ascendido a double. Por lo tanto, si declara (en lugar de prototipo) una función, no no quiero especificar alguna char, short o float parámetro: llamar a tal cosa daría/dará un comportamiento indefinido. Con banderas predeterminadas, el compilador bien puede rechazar el código, ya que básicamente no hay forma de usarlo correctamente. Es posible que pueda encontrar algún conjunto de indicadores del compilador que le permitan aceptar el código, pero sería bastante inútil, ya que no puede usarlo de todos modos…

  • Interesante, no sabía de estas promociones antes. Aparentemente C tiene algo llamado las promociones de argumento por defecto (C99 6.5.2.2.6). ¡Hay tantas rarezas ocultas en el lenguaje C! Me pregunto por qué agregaron este “parche” increíblemente feo al estándar en lugar de hacer cumplir los prototipos. De todos modos, las “futuras extensiones del lenguaje” del grupo de trabajo de C sugieren que toda esta basura se eliminará del estándar, si alguna vez hacen una nueva versión del mismo.

    – Lundin

    30 de marzo de 2011 a las 6:57

  • Mantuvieron las promociones predeterminadas más o menos por necesidad: los prototipos fueron un nuevo invento durante la estandarización C original. Requerir prototipos habría roto esencialmente el 100% del código y los compiladores existentes…

    – Jerry Ataúd

    30 de marzo de 2011 a las 12:59

  • La forma en que lo expresa parece sugerir que un prototipo no es una declaración (sin tipos de argumento -> declaración, con tipos de argumento -> prototipo).

    – undur_gongor

    11 de mayo de 2015 a las 8:37

  • @undur_gongor: Bueno, un prototipo también declara la función, por supuesto, pero sí, parece que entendiste la distinción que estaba tratando de hacer.

    – Jerry Ataúd

    11 mayo 2015 a las 14:06

prototipo = declaración directa, para que pueda usarla antes de decirle al compilador lo que hace. Todavía tiene parámetros, sin embargo.

¡Útil en muchos aspectos!

  • Si prototype = forward declarationEntonces, ¿cuál es la diferencia entre forward declaration y declaration??

    – compilador

    30 de marzo de 2011 a las 3:42

  • La declaración directa viene antes de la declaración real. declaración hacia adelante = void hi(); declaración = void hola(){ printf(“hola”); }

    – ultifinito

    30 de marzo de 2011 a las 3:44

avatar de usuario
mu es demasiado corto

los declaración int fuc(float); le dice al compilador que existe una función fuc que toma un float y devuelve un int.

los definición int fuc(float f) { /*...*/ } le dice al compilador qué fuc en realidad es y también proporciona la declaración también.

La diferencia entre una declaración y una definición es la diferencia entre decir que existe un sombrero azul talla 6 y entregarle a alguien un sombrero azul talla 6: la declaración dice que existe tal cosa, la definición dice que esta cosa aquí es la cosa en cuestión.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad