2011-11-09 697 views
6

Tengo una función que multiplica dos matrices A y B y luego imprime el resultado. Obtuve dos salidas diferentes cuando ejecuté el programa de dos maneras similares.argumentos invertidos para una función C

primero:

FILE *f; 
    f = fopen("in.txt","r"); 
    struct Mat* A = read_mat(f); 
    struct Mat* B = read_mat(f); 
    print_mat(mat_mul_1(A, B)); 

la salida era la multiplicación exacta de

A * B

Segundo:

FILE *f; 
    f = fopen("in.txt","r"); 
    print_mat(mat_mul_1(read_mat(f), read_mat(f))); 

la salida fue la exacta multiplicación de

B * A

Quiero saber por qué los argumentos se ha invertido?!

(como la función 'mat_mul_1' es un cuadro negro)

Respuesta

8

¿Se esperaba que el primer read_mat(f) serían evaluados en primer lugar?

C no ofrece tales garantías. El compilador puede emitir código que evalúa los argumentos en el orden que prefiera.

el orden de evaluación del designador de función, los argumentos reales, y subexpresiones dentro de los argumentos reales es no especi ed fi, pero hay un punto de secuencia antes de la llamada real.

+0

podría u dime por qué iba a cambiar el compilador el orden de los argumentos? ya que veo que es mejor evaluarlo siempre de izquierda a derecha, ya que ya está ordenado –

+1

en realidad no es necesariamente "mejor". Por ejemplo, hipotéticamente, puede ser más rápido empujar cosas en la pila de izquierda a derecha y evaluar los resultados de abajo hacia arriba (por lo tanto, esencialmente en reversa). el punto es que si el orden de lectura importa, debería leer EXPLICITAMENTE el archivo. –

+1

@ M.ElSaka: el compilador convierte internamente una expresión en un tipo de estructura de árbol binario, donde cada operando forma una "hoja". Luego puede evaluar este árbol comenzando por la hoja más a la izquierda o la más a la derecha. Lo que es mejor para el rendimiento en una plataforma específica no es obvio, si es que importa. Esta es la razón por la cual es un comportamiento no especificado. – Lundin

0

Es a causa de los parámetros de orden a la función se evalúan:

print_mat(mat_mul_1(A, B)); 

se llama mat_mul_1(A, B), donde A es la primera matriz en el archivo y B es el segundo. En el segundo caso:

print_mat(mat_mul_1(read_mat(f), read_mat(f))); 

supongo (ya que no está especificado por la norma) que, en su sistema, está llamando la segunda read_mat() en primer lugar, y por lo tanto se llame mat_mul_1(B, A);

0

La razón El ser es que el más a la derecha read_mat(f) se llama antes que el más a la izquierda y, por lo tanto, se lee la primera estructura en lo que se supone que es B. Por lo tanto, A y B están invertidos.

Tengo algo de sentido en que los argumentos se empujan en la pila en reversa cuando se pasan a una función, por lo tanto se evalúan de derecha a izquierda.

No estoy seguro de que haya algún estándar que defina qué debe primero evaluar.

0

Su código ha indefinido comportamiento porque la FILE apuntado por f se modifica por tanto la primera como la segunda read_mat(f) y no existe ningún punto de la secuencia entre estas dos modificaciones.

2

La razón por la cual es como ya se ha señalado, el orden de evaluación de los parámetros de la función es un comportamiento no especificado, y por lo tanto no debe confiarse en ella. Pero hay otra, posiblemente grave problema aquí:

El read_mat función puede obtener acceso a los recursos estáticos, como las variables estáticas/globales, y luego regresar a sus valores. De esta manera:

static int x; 

int inc (void) 
{ 
    x++; 
    return x; 
} 

printf("%d %d", inc(), inc()); 

El resultado real de la función variará según el orden de evaluación.

(Este fragmento se toma de una prueba de entrevista que uso cuando la contratación de programadores C. Me pregunto lo que la salida de este código es, y la respuesta correcta es "2 1" o "1 2". Las pruebas de interrogación si el programador de C sabe conceptos de la inicialización estática y orden de evaluación.)

Cuestiones relacionadas