Member 14325983 Ответов: 3

C проблемы увеличения и уменьшения выходного сигнала


Первый вывод printf-11, 11. Второй-10, 20 Почему это 20, а не 21?
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a=10,b=++a;
    printf("%d,%d\n",a,b);
    b=a+--a;
    printf("%d,%d",a,b);
}


Что я уже пробовал:

Я действительно не понимаю, как это работает.

3 Ответов

Рейтинг:
22

k5054

Это имеет отношение к точка следования Я считаю, что и 20, и 21 являются допустимыми ответами, поскольку компилятор свободен выбирать, когда оценивать --a, так что он может либо уменьшаться a до или после добавления. Единственное, что вы знаете наверняка, это то, что после выполнения задания b, a будет иметь значение 20.
Следует избегать выражений, которые обращаются и используют операторы инкремента/декремента для одной и той же переменной в одно и то же время в разных местах. Это включает в себя передачу переменной в функции. Например

int a=10;
printf("%d, %d\n", a, --a)
может напечатать "10, 9", а может и "9, 9"


Member 14325983

Это школьное задание, от которого у меня разболелась голова, спасибо!

Рейтинг:
2

Patrice T

Цитата:
Я действительно не понимаю, как это работает.

Это серая зона.
Компилятор C может свободно переписывать ваш код так, как он считает нужным внутри строки кода.
Таким образом, разные компиляторы получат разные результаты, и все они верны, это непредсказуемо, и в большинстве случаев неожиданно.
Правило безопасности состоит в том, чтобы никогда не использовать более одного раза переменную, которая изменяется в строке кода.


Рейтинг:
19

Gerry Schmitz

Он будет делать оператор "префикс" ( -- ) прежде всего.

когда a равно 11, то

Б=а+(- в)
= 10 + 10

a обновляется "inline"; промежуточного хранилища нет.


k5054

Это неверно. Стандарт C не определяет порядок вычисления операндов. Дана следующая программа:

#include <stdio.h>
int main()
{
    int a = 10;
    int b = a + --a;
    printf("%d, %d\n", a, b);
    return 0;
}

Компилируя с gcc я получаю результат 9, 18;, но когда я компилирую с помощью clang, я получаю 9, 19 Кроме того, клэнг говорит мне:: фу.с:6:17: предупреждение: модификации неупорядоченное и К 'а' [-Wunsequenced], и используя -Wall gcc говорит мне foo.c:6:17: предупреждение: операция на ‘a’ может быть неопределенной [-Wsequence-point]

Gerry Schmitz

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

Все, что вы указали, - это то, что существуют "различия в компиляторах", которые сводятся к тому, чтобы "знать свои инструменты".

"Стандарт" подчеркивает "последовательность"; больше ничего.

k5054

Но ведь это не детерминизм, не так ли? Один и тот же компилятор может вычислять операнды в разном порядке на разных уровнях оптимизации. Хуже того, если вы надеетесь создать переносимый код, который может быть скомпилирован в других системах, возможно, с помощью компиляторов, к которым у вас нет доступа, не зная, что порядок оценки вплоть до компилятора, будет вызывать ошибки.

Gerry Schmitz

Это определенно детерминировано, если я использую скобки; и это все, с чем мы имеем дело: последовательность, будь то по умолчанию или принудительно.

k5054

Все равно ошибаешься, даже b = a + (--a)
оценивает по-разному в gcc и clang. Я думаю, что настоящий языковой юрист указал бы, что это неопределенное поведение, и поэтому реализация свободна делать то, что она хочет. Заставить волосатых демонов вылететь из вашего носа или запустить ядерные ракеты на горе Дум в Мордоре-это оба возможных варианта. Ни то, ни другое маловероятно, но не запрещено стандартом.

Gerry Schmitz

Если я найду компилятор C, который придерживается "последовательности C#", он все равно не удовлетворит вас из-за вашего опыта работы с Z.

Вы понятия не имеете, что использует ОП, но убеждены, что ваша "реальность" применима ко всем остальным.

ОП искал разумное объяснение, а не ФАД.