es f (void) obsoleto en C moderno y C++ [duplicado]


Esta pregunta ya tiene una respuesta aquí:

Actualmente estoy refactorizando / ordenando algún antiguo código de C usado en un proyecto de C++, y regularmente veo funciones como:

int f(void)

Que tendería a escribir como:

int f()

¿Hay alguna razón para no reemplazar (void) con () en todo el código base para mejorar la consistencia, o hay una diferencia sutil entre los dos que no conozco? Más específicamente, si una función miembro virtual en C++ se describe como:

virtual int f(void)

Y una clase derivada incluye a función miembro:

int f()

¿Es esto una anulación válida? Además, ¿es probable que encuentre algún problema de enlazador basado en firmas casi idénticas?

Author: Derek, 2009-01-06

6 answers

En C, la declaración int f(void) significa una función que devuelve int que no toma parámetros. La declaración int f() significa una función que devuelve int que toma cualquier número de parámetros. Por lo tanto, si tiene una función que no toma parámetros en C, la primera es el prototipo correcto.

En C++, creo que int f(void) está en desuso, y se prefiere int f(), ya que significa específicamente una función que no toma parámetros.

 96
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-27 08:47:07

Para agregar a la respuesta de Chris, usar int f() es una mala práctica en C, en mi experiencia, ya que se pierde la capacidad del compilador para comparar la declaración de la función con su definición, para asegurarse de que se llamará correctamente.

Por ejemplo, el siguiente código cumple con los estándares C:

#include <stdio.h>
void foo();
void bar(void) {
    foo();
}
void foo(int a) {
    printf("%d\n", a);
}

Pero resulta en un comportamiento indefinido, ya que a no se pasó a foo.

En C++, hay dos versiones de foo: una que no toma argumentos y otra que toma un int. Tan bar termina llamando a la versión indefinida, lo que resultaría en un error de enlazador (suponiendo que no hay otras definiciones de foo en ningún lugar).

 21
Author: Zach Hirsch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-06 12:48:24

Las respuestas anteriores son bastante correctas, pero estoy enlazando a la excelente página de David Tribble, ya que da una gran explicación sobre este y muchos otros temas.

Lo más destacado:

C distingue entre una función declarado con una lista de parámetros vacía y una función declarada con un lista de parámetros que consiste solo en anular. El primero es un no tipificado función tomando un número no especificado de argumentos, mientras que este último es un función prototipada tomando no argumento.

C++, por otro lado, no hace distinción entre los dos declarations and considers them both para significar una función que toma no argumento.

Para el código que está destinado a ser compilado como C o C++, el mejor la solución a este problema es siempre declarar funciones sin tomar parámetros con un prototipo de vacío explícito.

Los prototipos de funciones vacías son función obsoleta en C99 (ya que estaban en C89).

Editar: Después de mirar el estándar, quizás vale la pena señalar que la sintaxis func(void) es no obsoleta en C++, pero comúnmente se considera más un modismo de estilo C. Creo que la mayoría de los programadores de C++ que he encontrado prefieren la lista de parámetros vacía.

Edición 2: Adición de una cita del estándar C++, sección 8.3.5, párrafo 2:

"Si la cláusula parameter-declaration-clause está vacía, la función no toma argumentos. La lista de parámetros (void) es equivalente a la lista de parámetros vacía. A excepción de este caso especial, void no será un tipo de parámetro (aunque los tipos derivados de void, como void*, pueden)."

No se menciona que cualquiera de las formas está obsoleta. Gracias de nuevo al excelente sitio web del Sr. Tribble por indicarme la sección correcta del estándar.

 17
Author: Dan Olson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-01 12:44:53

Tl; dr: use void.

Dada la compatibilidad con versiones anteriores en C++, y el poco de ambigüedad identificado a continuación, afirmo que vamos todo el camino de vuelta a KnR y ANSI C para una respuesta concluyente:

int getline(void);
int copy(void)

Dado que las versiones especializadas de getline y copy no tienen argumentos, lógica sugeriría que sus prototipos al principio del archivo debe ser getline() y copy(). Pero para la compatibilidad con programas C antiguos el estándar toma una lista vacía como un estilo antiguo declaración, y desactiva toda comprobación de lista de argumentos; la palabra void debe usarse para una lista explícitamente vacía. [Kernighan y Richie, el lenguaje de programación C, 1988, Pgs 32-33]

Y..

El significado especial de la lista de argumentos vacía pretende permitir programas C antiguos para compilar con nuevos compiladores. Pero es una mala idea úsalo con nuevos programas. Si la función toma argumentos, declare ellos; si no toma argumentos, uso nulo [ibid, Pg. 73]

EDITAR: Dividió el resto en una discusión separada aquí: ¿Especificar el uso de void en la declaración de una función que no toma argumentos aborda el Análisis Más Molesto?

 2
Author: kmiklas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:46:37

C11 N1570 borrador estándar

void f() está en desuso, void f(void) recomendado:

6.11.6 Declaradores de función :

1 El uso de declaradores de función con paréntesis vacíos (no el parámetro prototype-format declaradores de tipo) es una característica obsoleta.

Introducción:

2 Ciertas características son obsoletas, lo que significa que pueden ser consideradas para retirada en revisiones futuras de esta Norma Internacional. Se mantienen porque de su uso generalizado, pero su uso en nuevas implementaciones (para la implementación características) o nuevos programas (para el lenguaje [6.11] o características de la biblioteca [7.31]) se desaconseja.

Discusión detallada: https://stackoverflow.com/a/36292431/895245

C++11 N3337 borrador estándar

Ni void f(void) ni void f() están en desuso.

void f(void) existe por compatibilidad con C. Anexo C "Compatibilidad" C. 1. 7 Cláusula 8: declaradores :

8.3.5 Change: En C ++ , una función declarada con una lista de parámetros vacía no toma argumentos. En C, un vacío lista de parámetros significa que el número y el tipo de los argumentos de la función son desconocidos.

Dado que void f() está obsoleto en C y void f(void) recomendado, void f(void) existirá mientras C++ quiera mantener la compatibilidad.

void f(void) y void f() son lo mismo en C++. Así que el más largo void f(void) solo tiene sentido si te importa escribir código que compile tanto en C como en C++, lo que probablemente no valga la pena.

Discusión detallada: https://stackoverflow.com/a/36835303/895245

 1
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:46:37

En C++, int f(void) es de hecho una declaración obsoleta que es 100% equivalente a int f(). It es la misma firma. El void en este contexto es tan significativo como, por ejemplo, los espacios en blanco. Eso también significa que están sujetos a la Regla de Una Definición (no sobrecargan) y Derived::f(void) anula Base::f().

No te metas con cosas como f(const void), sin embargo. No hay mucho consenso sobre lo que significa ese tipo de rareza.

 -1
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-06 08:13:49