¿Cuál es la diferencia entre function () y function (void)?

27

He oído que es una buena práctica escribir funciones que no reciben nada como un parámetro como este:

int func(void);

Pero escuché que la forma correcta de expresar eso es así:

int func();

¿Cuál es la diferencia entre estas dos declaraciones de funciones en C y C ++?

Oso pardo
fuente
55
Este es un duplicado de miles de otras preguntas en la red del sitio, entre otras stackoverflow.com/questions/18167390/…
Lars Viklund
@LarsViklund es solo un duplicado si hay una pregunta en este sitio. No puedo encontrar uno, así que independientemente de lo que esté en SO, este no es un duplicado. Probablemente valga la pena mantener esta pregunta como una señal, si nada más.
1
@LightnessRacesinOrbit discutimos en el chat y decidimos mantenerlo con algunas ediciones.

Respuestas:

17

C y C ++ son diferentes a este respecto.

C 2011 estándar en línea

6.7.6.3 Declaradores de funciones (incluidos los prototipos)
...
10 El caso especial de un parámetro de tipo sin nombre voidcomo único elemento en la lista especifica que la función no tiene parámetros.
...
14 Una lista de identificadores declara solo los identificadores de los parámetros de la función. Una lista vacía en un declarador de función que forma parte de una definición de esa función especifica que la función no tiene parámetros. La lista vacía en un declarador de función que no forma parte de una definición de esa función especifica que no se proporciona información sobre el número o los tipos de los parámetros. 145)

En resumen, una lista de parámetros vacía en una declaración de función indica que la función toma un número no especificado de parámetros, mientras que una lista de parámetros vacía en una definición de función indica que la función no toma parámetros.

T foo( void ); // declaration, foo takes no parameters
T bar();       // declaration, bar takes an *unspecified* number of parameters

T foo( void ) { ... } // definition, foo takes no parameters
T bar() { ... }       // definition, bar takes no parameters

En lo que respecta a C, nunca debe usar una lista de identificadores vacía en una declaración o definición de función. Si una función no está destinada a tomar ningún parámetro, especifíquelo utilizando voiden la lista de parámetros.

Estándar en línea de C ++

8.3.5 Funciones [dcl.fct]
...
4 La cláusula-declaración-parámetro determina los argumentos que se pueden especificar, y su procesamiento, cuando se llama a la función. [ Nota: la cláusula-declaración-parámetro se usa para convertir los argumentos especificados en la llamada a la función; ver 5.2.2. - nota final ] Si la cláusula-declaración-parámetro está vacía, la función no toma argumentos. Una lista de parámetros que consta de un único parámetro sin nombre de tipo no dependiente voides equivalente a una lista de parámetros vacía. Excepto en este caso especial, un parámetro no tendrá tipo cv void. Si la cláusula-declaración-parámetrotermina con puntos suspensivos o un paquete de parámetros de función (14.5.3), el número de argumentos será igual o mayor que el número de parámetros que no tienen un argumento predeterminado y no son paquetes de parámetros de función. Donde sintácticamente correcto y donde "..." no es parte de un declarador abstracto , ", ..." es sinónimo de "...". [ Ejemplo: la declaración
    int printf(const char*, ...);
declara una función que se puede llamar con diferentes números y tipos de argumentos.
    printf("hello world");
    printf("a=%d b=%d", a, b);
Sin embargo, el primer argumento debe ser de un tipo que se puede convertir a un const char*- ejemplo final ] [ Nota: El encabezado estándar <cstdarg>contiene un mecanismo para argumentos con el acceso pasado usando los puntos suspensivos (ver 5.2.2 y 18.10). - nota final ]

En el caso de C ++, una lista de parámetros vacía en una declaración o una definición indica que la función no toma argumentos, y es equivalente a usar una lista de parámetros de void.

John Bode
fuente
35

En C, una función con una lista de parámetros vacía ()puede tomar cualquier cosa por sus argumentos. Literalmente cualquier cosa. Esto generalmente se usa para implementar una función que puede tomar un número variable de argumentos , aunque en estos días se considera preferible usar la sintaxis de puntos suspensivos más explícitos (...)para estas funciones.

En C, una función con la lista de parámetros (void)explícitamente no toma nada para sus argumentos. Eso significa que el compilador puede decirle que cometió un error si intenta pasar algo.

En C ++, estas declaraciones de funciones son equivalentes. Una lista de parámetros en blanco significa "sin parámetros" igual que lo voidhace.

Ixrec
fuente
Re: "Esto se usa generalmente para implementar una función que puede tomar un número variable de argumentos": ¿Está seguro de esto? No creo haber visto un programa que use listas explícitas de parámetros para declaraciones directas de funciones no variables y ()para las variables. ¿Tiene un ejemplo de un programa que utiliza esta convención?
ruakh
44
La función variadic de CA debe definirse con la ...sintaxis y debe tener al menos un parámetro con nombre. La definición de dicha función ()provoca un comportamiento indefinido, y el cuerpo de la función no puede utilizar las macros definidas <stdarg.h>para leer los valores de los parámetros. Este ha sido el caso desde el estándar 1989/1990.
Keith Thompson
@KeithThompson: Esta pregunta, y esta respuesta, están hablando de predeclaraciones, no de definiciones de funciones.
ruakh
3
@ruakh: una función variadic debe declararse y definirse utilizando la ...sintaxis para evitar comportamientos indefinidos.
Keith Thompson