аргументы обращены для функции C - PullRequest
6 голосов
/ 09 ноября 2011

У меня есть функция, которая умножает две матрицы A и B, а затем печатает результат.Я получил два разных вывода при запуске программы двумя похожими способами.

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

На выходе было точное умножение

A * B

секунда:

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

результат был точным умножением

B * A

Я хочучтобы знать, почему аргументы были изменены на противоположные?!

(так как функция 'mat_mul_1' - это черный ящик)

Ответы [ 5 ]

8 голосов
/ 09 ноября 2011

Вы ожидали, что первое read_mat(f) будет оцениваться первым?

C не дает таких гарантий. Компилятор может свободно генерировать код, который оценивает аргументы в любом порядке по своему выбору.

Порядок оценки обозначения функции, фактические аргументы и подвыражения в фактических аргументах не определены, но есть точка последовательности до фактического звонка.

2 голосов
/ 09 ноября 2011

Причина, по которой, как уже отмечали другие, порядок оценки параметров функции - неопределенное поведение, и поэтому на него не следует полагаться. Но здесь есть еще одна, возможно, серьезная проблема:

Функция read_mat может получать доступ к статическим ресурсам, таким как статические / глобальные переменные, и затем возвращать их значения. Как это:

static int x;

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

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

Фактический результат функции будет зависеть от порядка оценки.

(Этот фрагмент взят из собеседования, которое я использую при приеме на работу программистов на Си. Я спрашиваю, каков вывод этого кода, и правильный ответ - «2 1» или «1 2». Вопрос проверяет, знает ли программист C о понятиях статической инициализации и порядке вычисления.)

0 голосов
/ 09 ноября 2011

Ваш код имеет неопределенное поведение, потому что FILE, на который указывает f, изменяется как первым, так и вторым read_mat(f), и между этими двумя модификациями не существует точки последовательности.

0 голосов
/ 09 ноября 2011

Причина в том, что самый правый read_mat(f) вызывается перед самым левым, и поэтому вы читаете первую структуру в то, что вы могли бы считать B. Поэтому A и B меняются местами.

Я как бы понимаю, что аргументы помещаются в стек в обратном порядке при передаче в функцию, поэтому они вычисляются справа налево.

Я не уверен, что существует какой-либо стандарт, определяющий, что должно быть оценено в первую очередь.

0 голосов
/ 09 ноября 2011

Это из-за того, что параметры порядка для функции оцениваются:

print_mat(mat_mul_1(A, B));

вызовет mat_mul_1(A, B), где A - первая матрица в файле, а B - вторая. Во втором случае:

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

Я предполагаю (поскольку это не указано в стандарте), что в вашей системе вызывает второй read_mat() первый и, таким образом, вызывает mat_mul_1(B, A);

...