Каков результат i == (i = 2)? - PullRequest
0 голосов
/ 02 декабря 2018

Запустите следующий код:

// In Java, output #####
public static void main(String[] args) {
    int i = 1;

    if(i == (i = 2)) {
        System.out.println("@@@@@");
    } else {
        System.out.println("#####");
    }
}

Но:

// In C, output @@@@@,I did test on Clion(GCC 7.3) and Visual Studio 2017
int main(int argc, char *argv[]) {
    int i = 1;

    if(i == (i = 2)) {
        printf("@@@@@");
    } else {
        printf("#####");
    }

    return 0;
}

Мотивация задать этот вопрос исходит из следующего кода:

// The code is from the JDK 11 - java.util.concurrent.atomic.AtomicInteger
// I am curious about the behavior of the variable prev.
public final int getAndUpdate(IntUnaryOperator updateFunction) {
    int prev = get(), next = 0;
    for (boolean haveNext = false;;) {
        if (!haveNext)
            next = updateFunction.applyAsInt(prev);
        if (weakCompareAndSetVolatile(prev, next))
            return prev;
        haveNext = (prev == (prev = get()));
    }
}

ИтакКак объяснить два вышеупомянутых режима выполнения?

Ответы [ 3 ]

0 голосов
/ 02 декабря 2018

В C поведение i == (i = 2) не определено, поскольку оно пытается как обновить объект, так и использовать значение этого объекта в вычислении без промежуточной точки последовательности.Результат будет зависеть от компилятора, настроек компилятора и даже окружающего кода.

0 голосов
/ 02 декабря 2018

В спецификации языка Java (§15.7) указано:

Язык программирования Java гарантирует, что операнды операторов представляются в определенном порядке ., а именно слева направо.

В спецификации (§15.21.1) также говорится, что:

Произведенное значениеоператором == является true, если значение левого операнда равно значению правого операнда;в противном случае результат будет false.

Поэтому в Java оператор if во время выполнения будет выглядеть следующим образом, что, очевидно, оценивается как false:

if (1 == 2) {

}

В Си это просто не определено (см. Ответ Антти ).

0 голосов
/ 02 декабря 2018

Поведение программы на C, которая выполняет выражение i == (i = 2), равно undefined .

Оно происходит от C11 6.5p22 :

Если побочный эффект на скалярный объект не секвенирован относительно другого побочного эффекта на тот же скалярный объект или вычисления значения с использованием значения того же скалярного объекта, поведение не определено.Если имеется несколько допустимых порядков подвыражений выражения, поведение не определено, если такой беспорядочный побочный эффект возникает в любом из порядков.84)

i наЛевая часть == является вычислением значения для скалярного объекта i, а правая часть i = 2 имеет побочный эффект от присвоения значения 2 i.LHS и RHS == не связаны друг с другом.Следовательно, вся программа не имеет смысла в C.

Скомпилируйте с gcc -Wall, и GCC выдаст:

unsequenced.c:5:16: warning: operation on ‘i’ may be undefined [-Wsequence-point]
     if(i == (i = 2)) {
             ~~~^~~~

В отличие от C, Java гарантирует порядок оценки для операндов (слева направо), поэтому

haveNext = (prev == (prev = get()));

является правильным в Java.Значение LHS определяется строго до того, как произойдет оценка побочного эффекта на RHS.

В C у вас есть , чтобы написать это как что-то вроде

newPrev = get();
haveNext = (prev == newPrev);
prev = newPrev;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...