uso signos reglas puntuacion puntos punto historia ejemplos coma c semicolon freeform

signos - uso de la coma y punto y coma



¿Por qué el compilador no informa que falta un punto y coma? (4)

¿Por qué el compilador no detecta el punto y coma que falta?

Hay tres cosas para recordar.

  1. Las terminaciones de línea en C son solo espacios en blanco ordinarios.
  2. * en C puede ser tanto un operador unario como binario. Como operador unario significa "desreferencia", como operador binario significa "multiplicar".
  3. La diferencia entre operadores unarios y binarios se determina a partir del contexto en el que se ven.

El resultado de estos dos hechos es cuando analizamos.

temp = *a /* Oops, missing a semicolon here... */ *a = *b;

El primero y el último * se interpretan como unarios, pero el segundo * se interpreta como binario. Desde una perspectiva de sintaxis, esto se ve bien.

Solo después de analizar cuando el compilador intenta interpretar los operadores en el contexto de sus tipos de operandos, se ve un error.

Tengo este sencillo programa:

#include <stdio.h> struct S { int i; }; void swap(struct S *a, struct S *b) { struct S temp; temp = *a /* Oops, missing a semicolon here... */ *a = *b; *b = temp; } int main(void) { struct S a = { 1 }; struct S b = { 2 }; swap(&a, &b); }

Como se ve en, por ejemplo, ideone.com, esto da un error:

prog.c: In function ''swap'': prog.c:12:5: error: invalid operands to binary * (have ''struct S'' and ''struct S *'') *a = *b; ^

¿Por qué el compilador no detecta el punto y coma que falta?

Nota: Esta pregunta y su respuesta están motivadas por esta pregunta . Si bien hay otras preguntas similares a esta, no encontré nada que mencione la capacidad de forma libre del lenguaje C, que es lo que está causando esto y los errores relacionados.


Algunas buenas respuestas anteriores, pero las elaboraré.

temp = *a *a = *b;

Este es en realidad un caso de x = y = z; donde a x e y les asigna el valor de z .

Lo que está diciendo es que the contents of address (a times a) become equal to the contents of b, as does temp .

En resumen, *a *a = <any integer value> es una declaración válida. Como se señaló anteriormente, el primer * desreferencia un puntero, mientras que el segundo multiplica dos valores.


C es un lenguaje de forma libre . Eso significa que puede formatearlo de muchas maneras y seguirá siendo un programa legal.

Por ejemplo, una declaración como

a = b * c;

podría escribirse como

a=b*c;

o como

a = b * c ;

Entonces, cuando el compilador vea las líneas

temp = *a *a = *b;

piensa que significa

temp = *a * a = *b;

Por supuesto, esa no es una expresión válida y el compilador se quejará de eso en lugar del punto y coma faltante. La razón por la que no es válida es porque a es un puntero a una estructura, por lo que *a * a intenta multiplicar una instancia de estructura ( *a ) con un puntero a una estructura ( a ).

Si bien el compilador no puede detectar el punto y coma faltante, también informa el error totalmente no relacionado en la línea incorrecta. Es importante notar esto porque no importa cuánto mire la línea donde se informa el error, no hay ningún error allí. A veces, problemas como este necesitarán que mire las líneas anteriores para ver si están bien y sin errores.

A veces incluso tiene que buscar en otro archivo para encontrar el error. Por ejemplo, si un archivo de encabezado está definiendo una estructura lo último que hace en el archivo de encabezado, y falta el punto y coma que termina la estructura, entonces el error no estará en el archivo de encabezado sino en el archivo que incluye el archivo de encabezado.

Y a veces empeora: si incluye dos (o más) archivos de encabezado, y el primero contiene una declaración incompleta, lo más probable es que el error de sintaxis se indique en el segundo archivo de encabezado.

Relacionado con esto está el concepto de errores de seguimiento . Algunos errores, generalmente debido a la falta de punto y coma en realidad, se informan como errores múltiples . Es por eso que es importante comenzar desde la parte superior al corregir errores, ya que corregir el primer error puede hacer que desaparezcan varios errores.

Esto, por supuesto, puede llevar a corregir un error a la vez y a recompilaciones frecuentes que pueden ser engorrosas en proyectos grandes. Sin embargo, reconocer estos errores de seguimiento es algo que viene con la experiencia, y después de verlos varias veces es más fácil desenterrar los errores reales y corregir más de un error por recompilación.


La mayoría de los compiladores analizan los archivos de origen en orden e informan la línea donde descubren que algo está mal. Las primeras 12 líneas de su programa en C podrían ser el comienzo de un programa en C válido (sin errores). Las primeras 13 líneas de su programa no pueden. Algunos compiladores notarán la ubicación de las cosas que encuentran que no son errores en sí mismos, y en la mayoría de los casos no desencadenarán errores más adelante en el código, pero podrían no ser válidos en combinación con otra cosa. Por ejemplo:

int foo; ... float foo;

La declaración int foo; por sí solo estaría perfectamente bien. Del mismo modo, la declaración float foo; . Algunos compiladores pueden registrar el número de línea donde apareció la primera declaración, y asociar un mensaje informativo con esa línea, para ayudar al programador a identificar casos en los que la definición anterior sea realmente errónea. Los compiladores también pueden mantener los números de línea asociados con algo como un do , que se puede informar si el while asociado no aparece en el lugar correcto. Sin embargo, en los casos en que la ubicación probable del problema sería inmediatamente anterior a la línea donde se descubre el error, los compiladores generalmente no se molestan en agregar un informe adicional para la posición.