¿Hay alguna diferencia entre foo (void) y foo () en C ++ o C?

253

Considere estas dos definiciones de funciones:

void foo() { }

void foo(void) { }

¿Hay alguna diferencia entre estos dos? Si no, ¿por qué está ahí el voidargumento? Razones estéticas?

Aterrizar
fuente
Para C el Q / A está aquí
Antti Haapala

Respuestas:

317

En C :

  • void foo()significa "una función que footoma un número no especificado de argumentos de tipo no especificado"
  • void foo(void)significa "una función fooque no toma argumentos"

En C ++ :

  • void foo()significa "una función fooque no toma argumentos"
  • void foo(void)significa "una función fooque no toma argumentos"

Al escribir foo(void), por lo tanto, logramos la misma interpretación en ambos idiomas y hacemos que nuestros encabezados sean multilingües (aunque generalmente tenemos que hacer algunas cosas más a los encabezados para hacerlos realmente en varios idiomas; es decir, envolverlos en un extern "C"si estamos compilando C ++).

DrPizza
fuente
10
Pero si C ++ hubiera requerido el void, entonces podría haber evitado el problema del "análisis más irritante".
Adrian McCarthy
55
Es cierto, pero hay tantos otros análisis de mierda en C ++ que no tiene sentido hablar de ninguno de ellos.
DrPizza
16
En una pregunta reciente, @James Kanze publicó un dato interesante. Vuelva a publicar aquí para evitar perderlo: las primeras versiones de C no permitían especificar el número de parámetros que una función podría tomar, por void foo()lo tanto, era la única sintaxis para declarar una función. Cuando se introdujeron las firmas, el comité C tuvo que eliminar la ambigüedad del parámetro no de la sintaxis anterior e introducir la void foo(void)sintaxis. C ++ lo tomó por razones de compatibilidad.
Matthieu M.
3
¿Me puede dar un ejemplo de C C90 y más tarde donde usar en void foo()lugar de void foo(void)producirá una diferencia funcional? Es decir, he estado usando la versión sin el vacío durante muchos años y no he visto ningún problema, ¿me estoy perdiendo algo?
chacham15
66
@ chacham15 void foo() { if ( rand() ) foo(5); } compila y ejecuta (causando un comportamiento indefinido a menos que tenga mucha suerte), mientras que void foo(void)con el mismo cuerpo causaría un error de compilación.
MM
39

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();

eso también se entiende que no se debe suponer nada acerca de los argumentos de atof; toda la comprobación de parámetros está desactivada. Este significado especial de la lista de argumentos vacía está destinado a permitir que los programas C más antiguos se compilen con nuevos compiladores. Pero es una mala idea usarlo con nuevos programas. Si la función toma argumentos, declarelos; si no requiere argumentos, use void.

Kyle Cronin
fuente
Pero la pregunta es acerca de las definiciones, en ese caso la regla C relevante es Una lista vacía en un declarador de función que es parte de una definición de esa función especifica que la función no tiene parámetros.
jinawee
9

C ++ 11 N3337 borrador estándar

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: los declarantes dicen:

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 el número y el tipo de los argumentos de la función son desconocidos.

Ejemplo:

int f();
// means int f(void) in C ++
// int f( unknown ) in C

Justificación: Esto es para evitar llamadas de función erróneas (es decir, llamadas de función con el número o tipo de argumentos incorrectos)

Efecto sobre la característica original: Cambio a la semántica de la característica bien definida. Esta característica se marcó como "obsoleta" en C.

8.5.3 funciones dice:

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. [...] Si la cláusula-declaración-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 se menciona en C ++ 11, int f()no especifica nada acerca de los argumentos y es obsoleto.

Puede conducir a código de trabajo o UB.

He interpretado el estándar C99 en detalle en: https://stackoverflow.com/a/36292431/895245

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
2

En C, 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 tiene que decirle al compilador que tiene un prototipo porque no puede omitirlo.

Paul Tomblin
fuente
1
"prototipo" significa la declaración de la lista de argumentos y el tipo de retorno. Digo esto porque "prototipo" me confundió en cuanto a lo que quisiste decir al principio.
Zan Lynx