2012-06-18 15 views
10

considere el siguiente código en C:necesita ayuda para entender este código de bucle en C

void main() 
{ 
    int a=0; 

    for(printf("\nA"); a; printf("\nB")); 

    printf("\nC"); 
    printf("\nD");  
} 

Cuando compilo usando Turb C++ versión 3.0 y gcc-4.3.4, me sale el siguiente como la salida de los dos casos:

A 
C 
D 

Sin embargo, si compilar el código siguiente:

void main() 
{ 
    for(printf("\nA"); 0; printf("\nB")); 

    printf("\nC"); 
    printf("\nD"); 
} 

la salida por gcc-4.3.4 es la misma que en el pre caso vious pero Turbo C++ 3.0 genera el siguiente resultado:

A 
B 
C 
D 

En primer lugar, no tengo ni idea de lo que está pasando aquí! Además, ¿cómo es que la salida del compilador gcc es la misma para ambos códigos, pero en el caso del compilador turboC++ 3.0, la salida es diferente? Por favor alguien puede arrojar algo de luz?

EDIT:

En realidad alguien se le preguntó esta pregunta en una entrevista para una empresa de TI y al no poder dar la respuesta, el entrevistador dio esta explicación. Pero creo que esto es estúpido. ¿Cómo puede pedirle a alguien que use un "error" como si fuera una "facilidad" proporcionada por el idioma? Para que se le llame "facilidad" y "técnica", ya sea que pasemos 0 como un literal en la segunda expresión o una variable cuyo valor es 0, el resultado debería haber sido el mismo.

¿Me equivoco al concluir que el entrevistador fue muy tonto al hacer una pregunta como esa y que muestra su incompetencia?

+5

Esta es una diferencia interesante en los compiladores, pero ¿por qué en el mundo usarías ese tipo de bucle 'for' en primer lugar? – JAB

+0

Me parece que has malentendido por completo la sintaxis del ciclo "for" en C? ¡No puedes adivinar cómo escribir cosas en un lenguaje de programación, necesitas un libro o un curso web o algo así! –

+3

@ ThomasPadron-McCarthy En realidad, la sintaxis está bien. No parece tener un buen uso, pero es perfectamente válido, al igual que la frase "Mi frío es un dedo del pie" es perfectamente válida sintácticamente, pero es una frase sin sentido. La primera parte, 'printf (" \ nA ")', se ejecutará al comienzo del bucle; la expresión centinela, que hace que el ciclo deje de ejecutarse cuando se evalúa como falso/0, es un 'a' para el primero (que == 0) y un' 0' literal para el segundo; [cont.] – JAB

Respuesta

12

La salida TCC para el segundo ejemplo es incorrecta.

de la norma C99:

La declaración

para (cláusula-1;expresión-2;expresión-3)declaración

se comporta de la siguiente manera: La expresión expression-2 es la expresión de control que se evalúa antes de cada ejecución del cuerpo del bucle. La expresión expresión-3 se evalúa como una expresión vacía después de cada ejecución del cuerpo del bucle. [...]

Obviamente, no hay iteraciones aquí, así expresión-3 nunca debe ser ejecutado.

Del mismo modo, en la norma C90 (o al menos en un draft that I found), que dice:

Excepto por el comportamiento de una sentencia continue en el cuerpo del bucle, el comunicado

 for ( expression-1 ; expression-2 ; expression-3) statement 

y la secuencia de declaraciones

 expression-1 ; 
    while (expression-2) { 
       statement 
       expression-3 ; 
    } 

son equivalentes.

+0

Eso lo tenía en mente. Eliminaré mi respuesta. – Jack

+0

Obviamente, Turbo C++ 3.0 es anterior a C99 por 8 años. Podría ser una extraña técnica de optimización. –

+0

@HristoIliev: ver mi respuesta actualizada ... –

3

Turbo C++ 3.0 fue lanzado en la década de 1990, y fue seguido muy rápidamente con un lanzamiento de 3.1.

Supongo que su compilador antiguo tenía una serie de errores que se actualizaron rápidamente. Además, podría tener , no, tales errores, pero puede haber emitido un ensamblaje optimizado que falla bajo las nuevas arquitecturas de revestimiento de tuberías.

En cualquier caso, es garantizado que Turbo C++ 3.0 se no se admite en su plataforma actual. Cuando se trata de un compilador que no recibe soporte porque la plataforma se creó casi 20 años después, no se puede culpar por emitir el programa incorrecto.

+0

AFAIK, los cambios en cosas como la canalización de CPU deben ser transparentes para el programador. –

1

la semántica de for es que la primera expresión se evalúa (inicializador), luego se evalúa la segunda expresión (terminador), luego si el terminador se evalúa como no cero se ejecuta el cuerpo del para, luego la tercera expresión (avance) se evalúa y vuelve a evaluar el terminador.

Como no tiene cuerpo, esa parte no tiene expresiones evaluadas. Basado en esto, el bucle debe ser ejecutado como sigue:

printf("\nA"); 
a; // yields 0 -> terminate loop 

Este es de hecho lo que sucede.

En el segundo ejemplo, el mismo debería ocurrir (como está para gcc) como 0 evalúa a 0.

Es posible que Turbo C++ - ver la constante 0 - intentó realizar alguna tipo de optimización de desenrollado de bucle (y no lo hizo correctamente)

+0

Casi pensé que la historia de desenrollar plausible, hasta que me di cuenta de que no era 'i <0', sino simplemente' 0', lo que no es un objetivo probable para la optimización de desenrollado de bucle. – lvella

2

La salida de gcc es correcta.

La salida de Turbo C++ 3.0 en el primer caso es correcta.

La salida de TurboC++ 3.0 en el segundo caso es incorrecta.

Parece que ha encontrado una caja de borde, que conduce a la generación de código incorrecto, en el compilador de Turbo C++ 3.0.

A para-stmt en C o C++ tiene la sintaxis general

para (inicialización; prueba; reinicialización) STMT

las inicializaciones se llevan a cabo una vez, antes de que comience el bucle. La prueba se realiza en la parte superior del ciclo. Si la prueba es verdadera, se realiza el stmt, y luego las reinicializaciones, y el bucle se repite.

En su caso, printf ("\ nA") es la inicialización, a (o 0) es la prueba, printf ("\ nB") es la reinicialización, y el stmt está vacío.

Deberías haber visto la A (y lo hiciste). La prueba debería haber fallado en la primera pasada, lo que significa que nunca debiste haber visto el stmt (pero no lo sabes), y nunca deberías haber visto el B. Aquí es donde Turbo C++ 3.0 se equivocó en el segundo examen.

Cuestiones relacionadas