¿Existe alguna diferencia entre foo(void) y foo() en C++ o C?
Considere estas dos definiciones de funciones:
void foo() { }
void foo(void) { }
¿Hay alguna diferencia entre estos dos? Si no, ¿por qué está void
ahí el argumento? ¿Razones estéticas?
Cª : _
void foo()
significa "una funciónfoo
que toma un número no especificado de argumentos de tipo no especificado"void foo(void)
significa "una funciónfoo
que no toma argumentos"
En C++ :
void foo()
significa "una funciónfoo
que no toma argumentos"void foo(void)
significa "una funciónfoo
que no toma argumentos"
Por lo tanto, al escribir foo(void)
, logramos la misma interpretación en ambos idiomas y hacemos que nuestros encabezados sean multilingües (aunque generalmente necesitamos hacer algunas cosas más con los encabezados para que sean verdaderamente multilingües; es decir, envolverlos en un extern "C"
si estamos compilando C++).
Me doy cuenta de que su pregunta se refiere a C++, pero cuando se trata de C, la respuesta se puede encontrar en K&R , páginas 72-73:
Además, si una declaración de función no incluye argumentos, como en
double atof();
esto también significa que no se debe suponer nada acerca de los argumentos de atof; toda la verificación de parámetros está desactivada. Este significado especial de la lista de argumentos vacía tiene como objetivo permitir que los programas C más antiguos se compilen con nuevos compiladores. Pero es una mala idea usarlo con programas nuevos. Si la función toma argumentos, declararlos; si no requiere argumentos, utilice void.
Borrador del estándar C++11 N3337
No hay diferencia.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
Anexo C "Compatibilidad" C.1.7 Cláusula 8: declarantes dice:
8.3.5 Cambio: En C++, una función declarada con una lista de parámetros vacía no toma argumentos. En C, una lista de parámetros vacía significa que se desconoce el número y el tipo de argumentos de la función.
Ejemplo:
int f(); // means int f(void) in C ++ // int f( unknown ) in C
Justificación: esto es para evitar llamadas a funciones erróneas (es decir, llamadas a funciones con el número o tipo de argumentos incorrectos).
Efecto sobre la característica original: cambio a la semántica de una característica bien definida. Esta característica fue marcada como "obsoleta" en C.
8.5.3 funciones dice:
4. La cláusula de declaración de parámetros determina los argumentos que se pueden especificar y su procesamiento cuando se llama a la función. [...] Si la cláusula-declaración-de-parámetro está vacía, la función no toma argumentos. La lista de parámetros (nula) es equivalente a la lista de parámetros vacía.
C99
Como lo menciona C++ 11, int f()
no especifica nada sobre los argumentos y es obsoleto.
Puede conducir a un código de trabajo o a UB.
He interpretado el estándar C99 en detalle en: https://stackoverflow.com/a/36292431/895245
En C, se utiliza un vacío en una referencia de función vacía para que el compilador tenga un prototipo y ese prototipo "no tenga argumentos". En C++, no es necesario decirle al compilador que tiene un prototipo porque no puede omitirlo.
A partir de C23 , C ha adoptado la semántica de C++ para declaraciones de funciones con listas de parámetros vacías.
En C++ y C23:
void foo()
significa "una funciónfoo
que no toma argumentos".void foo(void)
significa "una funciónfoo
que no toma argumentos".
Las declaraciones de funciones que no son prototipo se han eliminado del lenguaje C.
Este cambio fue introducido por la propuesta N2841: No hay declaradores de funciones sin prototipos , que tiene el resumen:
Esto elimina el soporte obsoleto para declaradores de funciones sin prototipos. En cambio , la antigua sintaxis para declaradores de funciones sin prototipos recibe la semántica de C++ .
Citando el borrador actual del estándar C23 ( N3096 , Anexo M.2 Quinta Edición):
Los principales cambios en esta quinta edición (
__STDC_VERSION__
202311L
) incluyen
...
- Las declaraciones de funciones obligatorias cuya lista de parámetros esté vacía se tratarán de la misma manera que una lista de parámetros que solo contiene un
void;
Tanto en C como en C++, void foo()
ahora void foo(void)
son exactamente equivalentes.