¿No se necesita un punto y coma (';') después de una declaración de función en C ++?

174

Recientemente tomé una prueba de programación intermedia, y una de las preguntas que me equivoqué fue la siguiente:

No se necesita un punto y coma (';') después de una declaración de función.

Verdadero o falso.

Elegí "falso" (y corrígeme si me equivoco porque siento que me estoy volviendo loco), una declaración de función es lo que escribes antes de la definición (en la parte superior del código) para que el compilador conozca la función llame incluso antes de llamarlo, y una definición de función es lo que constituye la función como un todo.

Es decir,

Declaración:

int func();

Definición:

int func() {
  return 1;
}

¿No debería ser falsa la respuesta a esto?

Logan
fuente
41
Una definición es también una declaración. Pero diría que su respuesta fue correcta.
216
Es una pregunta difícil y no influye en la capacidad de nadie para programar bien.
phonetagger
40
Siempre encuentro las preguntas, que resultan en negativos dobles, confusas. En mi opinión, tales preguntas están diseñadas para hacer tropezar a los estudiantes. ¿Por qué no se pudo formular la pregunta de la siguiente manera: "Siempre se necesita un punto y coma (';') después de una declaración de función. Verdadero o Falso"? : /
Algirdas Preidžius
18
@phonetagger Toda esta confusión muestra cuán mal redactada está la pregunta.
François Andrieux
34
Hanlon's Razor sugiere que el autor de la prueba mezcló "declaración" y "definición".
Sneftel

Respuestas:

161

Puede tener una situación en la que declara y define la función en un solo paso, es decir, si incluye la definición de la función en el punto donde la declara. Así que técnicamente supongo que cierto es correcto. Pero la pregunta está redactada de tal manera que la habría respondido de la manera que usted lo hizo.

jwismar
fuente
10
Yo diría que cierto no es correcto por la razón que diste. Si hay casos en que se necesita un punto y coma, entonces es falso (o no es cierto). Verdadero es lo absoluto para mí, si hay casos claros en los que se necesita, no se puede decir verdadero.
I Funball
16
@IFunball Buen argumento. Estúpidas lenguas nativas. La frase "No se necesita un punto y coma (';') después de una declaración de función" se puede leer como "No se necesita (nunca) un punto y coma (';') después de una declaración de función" o como "Un punto y coma (';' ) no es (siempre) necesario después de una declaración de función ". Si calificar la afirmación como verdadera o falsa depende de elegir una interpretación. Hablando estrictamente, la pregunta no está clara y, por lo tanto, no tiene una respuesta clara.
Peter - Restablece a Monica
66
@IFunball Es porque "declaración", sin contexto adicional y sin declaración de que estamos abogando por el lenguaje, se entiende comúnmente como "una declaración no definitoria". La pregunta fue injusta.
ligereza corre en órbita
2
Cualquier pregunta del examen que no esté clara para alguien que conozca el contenido que se está probando tiene errores.
Nat
2
Parece que necesitamos agregar una cláusula de comportamiento indefinido al idioma inglés
Nick Mertin
147

Además de lo de "una definición es también una declaración", lo siguiente es C ++ legal:

int f(), g();

Esto declara dos funciones fy g, ambas sin argumentos y con un tipo de retorno de int, pero la definición de fno es seguida (inmediatamente) por un punto y coma. Del mismo modo, esto es legal:

int f(), i = 42;

Pero, de hecho, no está permitido omitir el punto y coma por completo en estos casos, por lo que sería algo sorprendente si se tomara como ejemplo de una declaración sin un punto y coma siguiente. De hecho, lo siguiente es ilegal:

void *p, f() {}

Aparte de una (mera) declaración de función, una definición de función no se puede combinar con ninguna otra declaración o definición para el mismo especificador de tipo . (Si esto fuera legal, definiría a void *py a void f() {}).

En cualquier caso, esto parece ser un tipo de pregunta "gotcha" que no debería estar en una prueba de programación intermedia.

(Ah, por cierto, por favor, no escriba código como int f(), i = 42;).

Arne Vogel
fuente
2
También es posible usar un typedef para definir un tipo de función, y luego usarlo para declarar muchas funciones a la vez, por ejemplo, typedef int fooProc(int); fooProc a,b.c.d.e;no estoy seguro de por qué los encabezados estándar para compiladores basados ​​en disqueteras no lo hicieron en el día, ya que creo que habría permitido que los archivos de encabezado fueran mucho más pequeños y, por lo tanto, más rápidos de procesar.
supercat
También considere int f(int(&g)(),int(*h)()){return g()+h();}Esto tiene tres declaraciones de funciones, una de las cuales es seguida por una llave abierta, otra por una coma y una tercera por un paréntesis cercano.
David Hammen
1
@DavidHammen: Eso no declara estrictamente funciones que no sean int f(stuff). Incluso en el ámbito de la función, ges una variable automática de tipo referencia a función , y hes un puntero para funcionar .
Peter Cordes
83

Las otras respuestas y comentarios señalan varias de las muchas formas en que esta es una pregunta horrible, engañosa y mal escrita. Pero hay otro problema que nadie más ha identificado todavía. La pregunta es:

No se necesita un punto y coma (';') después de una declaración de función. Verdadero o falso.

OK, veamos una declaración de función:

int func();       /* */
/*           ^       */
/*           |       */
/* That whitespace is "after the function declaration". */

Todo eso es la declaración . La declaración no es int func()y luego sigue a ;. La declaración es int func();y luego es seguida por espacios en blanco.

Entonces, la pregunta es: ¿se necesita un punto y coma después de la declaración ? Por supuesto no. La declaración ya tiene un punto y coma que la terminó. Un punto y coma después de la declaración no tendría sentido. Por el contrario, int func(); ;sería un punto y coma después de una declaración de función .

La pregunta seguramente tenía la intención de hacer la pregunta "verdadero o falso: el último token en una declaración de función siempre es un punto y coma" Pero esa no es la pregunta que escribieron, porque el autor del cuestionario no estaba pensando claramente sobre el problema.

Mi consejo es evitar por completo las pruebas de lenguaje de programación. Son bastante horribles.


Dato curioso, mientras estamos en el tema. En C #, estos son todos legales:

class C {}
class D {};
struct E {}
struct F {};

En C #, una declaración de clase o estructura puede terminar en punto y coma, o no, a su discreción. Esta pequeña y extraña característica se agregó para beneficio de los programadores de C / C ++ que vienen a C # y que la tienen en la punta de los dedos y que las declaraciones de tipo terminan en un punto y coma sin sentido; El equipo de diseño no quería castigarlos por tener este hábito. :-)

Eric Lippert
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Samuel Liew
25

También puede declarar una función como esta:

int func(){
    return 1;
}

La declaración es muy ambigua. La respuesta correcta debería ser: depende de cómo declare la función.

De todos modos, también habría elegido falso, y tal vez puedas informar la pregunta a alguien.

Luca Corsini
fuente
3
De todos modos, no pongas la cosa a nivel personal. Lo importante es que entendiste cómo funciona una definición de declaración de función, así que no te preocupes demasiado, solo asegúrate de que la pregunta al menos se verificará y continuará
Luca Corsini
11
Absolutamente. Honestamente, aprendí más acerca de la definición de declaración de función al equivocarme la pregunta de lo que hubiera podido haber respondido correctamente.
Logan
1
@Logan no te preocupes demasiado. Si sabes cómo escribir y leer una función, eso es todo lo que necesitas. Personalmente odio este tipo de preguntas que 1. no están bien definidas 2. evalúan su conocimiento teórico de la sintaxis. Para mí es como la memoria muscular. Cuando escribo cada dígito va sin esfuerzo a la tecla que se supone que debe ir, pero si me das una prueba sobre qué teclas debería presionar un dígito, estaría completamente desesperado sin un teclado para realizar físicamente la acción ...
bolov
2
... Escribir una sintaxis común (por ejemplo, como una función) se convertirá en una segunda naturaleza para usted. Y cuando lo estropees porque cambiaste de idioma, bueno ... el resaltado de inteligencia y sintaxis crea soluciones rápidas y eficientes. Invierte tu tiempo y energía en algo más útil.
bolov
20

No se necesita un punto y coma (';') después de una declaración de función.

Verdadero o falso.

Cierto . No se necesita un punto y coma después de cualquier declaración. Ni después de ninguna definición. Ni después de ninguna declaración.

Muchos tipos de declaración tienen que terminar con un punto y coma, como lo especifica la sintaxis en la sección 7 [dcl.dcl]. Pero nunca hay necesidad de escribir un segundo después de eso.

Marc van Leeuwen
fuente
1
Veo que Eric Lippert ya discutió este punto. Supongo que todos los votos positivos me hicieron pasarlo por alto. Siéntase libre de emitir sus votos allí.
Marc van Leeuwen
Casi cualquier pregunta que haga, "X siempre es verdad: ¿verdadero o falso?" va a tener la respuesta "falso" Diablos, no hay necesidad de tener un punto y coma en ningún lado ; el compilador puede quejarse y negarse a compilar su programa, pero ese no es el fin del mundo; No lo llamaría una necesidad fundamental . ;)
Quuxplusone
@Quuxplusone si el compilador rechaza su programa, su programa no tiene ninguna declaración de función en él :)
Ben Millwood
6

Esto depende de si estamos declarando o definiendo la función. Si estamos declarando la función, necesitamos incluir el punto ;y coma ( ), y si estamos definiendo la función, el punto y coma no es necesario.

Una declaración es así:

int add(int, int);

Y una definición es así:

int add(int a, int b)
{
    // ...
}
Rocx En Ruff
fuente
10
El problema con esta respuesta es que sugiere que las definiciones y la declaración son mutuamente excluyentes. De hecho, cada definición es una declaración; Las definiciones son un subconjunto de declaraciones.
MSalters
6

Aunque estoy de acuerdo con casi todas las otras respuestas, afirmando que la pregunta está redactada de manera muy ambigua y que su respuesta es técnicamente correcta, permítame darle una perspectiva diferente:

Así es como siempre los he llamado:

void func();  // The function prototype

...

void func()
{
    // The function definition
}

Supongo que la pregunta se hizo con esta terminología en mente.

Definición y declaración son el mismo concepto a mis ojos. "Defino x = y" == "Declaro x = y".

Pero, por supuesto, hay una gran diferencia entre el prototipo de la función (en la parte superior) y la definición real de la función.

Opifex
fuente
Para mí, su prototipo es la declaración basada en cómo lo aprendí (aunque tampoco digo que esté equivocado), pero también esperaría que un prototipo especifique el número y el tipo de argumentos, o sea nulo, pero espero que haya omitido eso para ser breve.
David S
David S: Sí, por supuesto, también contendría el número y el tipo de argumentos, pero de hecho los omití por brevedad (tenga en cuenta que tampoco hay argumentos en la declaración de la función real). Sin embargo, realmente no estoy de acuerdo cuando dices que la declaración de función completa se llama prototipo. Cito Wikipedia: "un prototipo de función o interfaz de función es una declaración de una función que especifica el nombre de la función y la firma de tipo (aridad, tipos de datos de parámetros y tipo de retorno), pero omite el cuerpo de la función".
Opifex
@DavidS: en C ++, las declaraciones de funciones son siempre prototipos (o definiciones), y void func();es exactamente equivalente a void func(void);. Esto es muy diferente de C , donde void func();no le dice nada al compilador sobre los argumentos, y no es lo mismo que void func(void);. Un prototipo o definición posterior es una buena idea, de lo contrario, la persona que llama tiene que aplicar las promociones arg predeterminadas (por ejemplo, flotante -> tipos enteros dobles y estrechos a int. Las mismas reglas que para argumentos a funciones variadas).
Peter Cordes
Mis disculpas, terminé aquí mirando algo relacionado con C y no noté el cambio de idioma. No eliminaré mi comentario en aras de la claridad, pero considérelo retraído.
David S
6

Es una pena que la pregunta que tomaste no diga "directamente después". Podríamos, por ejemplo, escribir esto:

int func()  /* My function */ ;

O podría escribir:

int func()
int a = 42;

En el primer caso, el punto y coma no está directamente después de la declaración, pero eso estaría bien.

En el segundo caso hay un punto y coma "después" de la declaración, pero no directamente después.

Creo que Eric Lippert tiene la idea correcta en su respuesta .

Es como decir "¿debería haber un punto después del final de una oración en inglés?". Podría decirse que una oración ya tiene un punto al final (de lo contrario no sería una oración) y, por lo tanto, no debería haber un punto después de la oración.

Nick Gammon
fuente
44
Agradable. Terminando esa oración con un período extra. Veo lo que hiciste alli.
David S
2
int func() int a=42;no compila Necesitas una coma, no otra int. Vea la respuesta de @ Arne publicada un día antes de esto. Lo único nuevo en esta respuesta es el último párrafo, con la analogía de las oraciones en inglés.
Peter Cordes
1
No dije el segundo ejemplo compilado. Estaba señalando que decir que se necesitaba un punto y coma "después" de la declaración era ambiguo. Mi ejemplo tenía un punto y coma después de la declaración, pero no se compila.
Nick Gammon
1
Este mismo problema ocurre en los mensajes de error; un ejemplo favorito de C # es " Un parámetro de parámetros debe ser el último parámetro en una lista de parámetros formales ". Ahora, supongamos que en su lugar dije "Un frob debe ser el último gloob en una lista de gloob". ¿Significa esto (1) que cada lista global tiene exactamente un punto de vista al final, como cada pregunta tiene exactamente un signo de interrogación al final, (2) una lista global puede tener cualquier número de ranas, pero si tiene una o más ranas? , el último elemento debe ser un frob, como un número par puede tener cualquier número de 02468, pero uno de los debe ser el último, o ...
Eric Lippert
... (3) una lista global puede tener cero o una rana, y si tiene una, ¿aparece al final? Si no conoce el contexto, creo que (1) es la explicación más sensata, pero en el caso del "parámetro de parámetros", (3) es la explicación correcta. Muchas descripciones informales de elementos del lenguaje de programación tienen una propiedad que mis amigos técnicos editores llaman "COIK" - Borrar solo si se conoce. Si aún no comprende completamente el material, una descripción del mismo es inútil para usted, pero si ya lo comprende completamente, ¡no necesita la descripción!
Eric Lippert
4

Puede usar ;solo para prototipos.

M7off
fuente
4

Es una pregunta difícil, pero usaron la palabra declaración que significa algo como esto:

int example();

Entonces es cierto en este caso.

Si hubieran usado la palabra implementación, entonces habría sido falso.

dark_3nergy
fuente
2

Semicolon (;) se usa para decirle al compilador que después de este punto y coma (;) comienza una nueva instrucción.

Así que creo que el punto y coma (;) se requiere solo durante una declaración de función. Entonces, según yo, la respuesta será verdadera.

Jatinder
fuente
Sin embargo, las declaraciones no son declaraciones.
HolyBlackCat
pero después de la declaración de función, estamos ejecutando una nueva línea de código usando el compilador. así que creo que antes de ejecutar una nueva línea de compilador de código, tengo que saber dónde termina la línea de código anterior, solo entonces un compilador puede generar código nativo (es decir, 0101).
Jatinder
2

Cuando las funciones se definen antes de main () :

  • No necesita punto y coma porque la función ya está definida

Cuando las funciones se definen después de main () :

  • Necesita punto y coma porque está creando prototipos de esa función y le dice al compilador que la función se cierra.
shiv shah
fuente