arguments are reversed for a C function
Asked Answered
D

5

6

I have a function that multiply two matrices A and B then prints the result. I got two different outputs when running the program in two similar ways.

first:

    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));

the output was the exact multiplication of

A * B

second:

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

the output was the exact multiplication of

B * A

I want to know why the arguments has been reversed ?!

(as the 'mat_mul_1' function is a black box)

Demotic answered 9/11, 2011 at 7:41 Comment(0)
W
8

Did you expect that the first read_mat(f) would be evaluated first?

C offers no such guarantees. The compiler is free to emit code that evaluates the arguments in any order it chooses.

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

Wrongful answered 9/11, 2011 at 7:43 Comment(3)
Could u tell me why would the compiler change the order of the arguments? as i see that it's better to always evaluate it from left to right as it's already orderedDemotic
no actually it's not necessarily "better". For example, hypothetically, it may be faster to push stuff on the stack left to right and evaluate the results bottom up ( so essentially in reverse ). the point is that if read order matters you should EXPLICITLY read the file out.Faenza
@M.ElSaka: The compiler internally converts an expression into a kind of binary tree structure, where every operand forms a "leaf". It can then evaluate this tree starting at the left-most leaf or the right-most one. Which that is better performance-wise on a specific platform isn't obvious, if it matters at all. This is the reason why it is unspecified behavior.Vilhelmina
V
2

The reason why is as others have already pointed out, the order of evaluation of function parameters is unspecified behavior, and therefore should not be relied upon. But there is another, possibly severe issue here:

The function read_mat could be accessing static resources, such as static/global variables, and then return their values. Like this:

static int x;

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

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

The actual result of the function will vary depending on the order of evaluation.

(This snippet is taken from an interview test I use when hiring C programmers. I ask what the output of this code is, and the correct answer is "2 1" or "1 2". The question tests whether the C programmer knows of the concepts static initialization and order of evaluation.)

Vilhelmina answered 9/11, 2011 at 9:54 Comment(0)
S
0

It's because of the order parameters to the function are evaluated:

print_mat(mat_mul_1(A, B));

will call mat_mul_1(A, B), where A is the first matrix in the file and B is the second. In your second case:

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

I'm guessing(since it's not specified by the standard) that, on your system, is calling the second read_mat() first, and will thus call mat_mul_1(B, A);

Septuplicate answered 9/11, 2011 at 7:44 Comment(0)
C
0

The reason being is that the right-most read_mat(f) is called before the left-most one, and you're therefore reading the first structure into what you would presume to be B. Therefore A and B are reversed.

I kind of make sense of it in that arguments are pushed on the stack in reverse when they're passed to a function, therefore they're evaluated from right to left.

I'm not sure there's any standard defining what must be evaluated first.

Calderon answered 9/11, 2011 at 7:45 Comment(0)
B
0

Your code has undefined behaviour because the FILE pointed to by f is modified by both the first and the second read_mat(f) and no sequence point exists between these two modifications.

Brainwashing answered 9/11, 2011 at 7:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.