Подтвердить что ты не робот

Использование условного оператора

Рассмотрим следующее утверждение. Каким будет значение, сохраненное в b?

int a=1;
int b = a+=1 ? a+=1 : 10;

Я получаю ответ как 4. Может ли кто-нибудь объяснить, как это работает.

4b9b3361

Ответ 1

Это связано с приоритетом. Если вы посмотрите на следующий код (с самым правым a+=1 измененным для простоты):

#include <iostream>

int main (void) {
    int a=1;
    int b = a+=1 ? 7 : 10;
    std::cout << b << std::endl;
    return 0;
}

вы увидите, что вывод 8, а не 7 или 10.

Это потому, что утверждение:

    int b = a+=1 ? 7 : 10;

интерпретируется как:

    int b = (a += (1 ? 7 : 10));

Теперь, применив это к вашему делу, получим:

    int b = (a += (1 ? a += 1 : 10));

и, в порядке выполнения:

  • самый правый a += 1 (так как 1 - true) устанавливает a в 2.
  • самый левый a += 2 (2 является результатом предыдущего шага) устанавливает a в 4.
  • b = 4 (4 является результатом предыдущего шага).

Просто имейте в виду, что вы не можете обязательно полагаться на этот порядок оценки. Несмотря на то, что в ? есть точка последовательности (так что 1 оценивается полностью до продолжения), нет никакой точки последовательности между самой правой a += ... и самой левой a += .... И изменение одной переменной дважды без промежуточной точки последовательности - это поведение undefined, поэтому gcc -Wall предоставит вам очень полезное сообщение:

warning: operation on ‘a’ may be undefined

Тот факт, что он дает вам 4, - это чистое совпадение. Это может так же легко дать вам 3, 65535 или даже отформатировать жесткий диск, чтобы научить вас уроку: -)

Ответ 2

Как указано в других ответах, эти два фрагмента кода эквивалентны из-за правил грамматики С++, которые определяют, как должны обрабатываться составные выражения.

int a=1;
int b = a+=1 ? a+=1 : 10;

и

int a=1;
int b = (a += (1 ? (a += 1) : 10));

Хотя в условном выражении есть точка последовательности, она находится между оценкой первого выражения (1) и оценкой того, что оценивается одно из второго и третьего выражений (a += 1 в этом случае), После оценки второго или третьего выражения отсутствует явная дополнительная точка последовательности.

Это означает, что a дважды изменяется в инициализаторе для b без промежуточной точки последовательности, поэтому код имеет поведение undefined.

Ответ 3

Анализ сборки:

int main() 
{
    int a=1;
    int b = a+=1 ? a+=1 : 10;
    return 0;
}

Сводный код, сгенерированный (используя MinGW) для приведенного выше кода, показан ниже. Комментарии мои, конечно! Читайте также комментарии!

 call ___main        //entering into main()
 movl $1, 12(%esp)   //int a = 1; means 12(%esp) represents a;
 incl 12(%esp)       //a+=1 ; a becomes 2
 movl 12(%esp), %eax //loading 'a' onto a register(eax); eax becomes 2 
 addl %eax, %eax     //adding the register to itself; eax becomes 4
 movl %eax, 12(%esp) //updating 'a' with the value of eax; 'a' becomes 4
 movl 12(%esp), %eax //this step could be optimized away; anyway it loads value of 'a' onto the register(eax); eax becomes 4, in fact even earlier it was 4 too! needless step!
 movl %eax, 8(%esp)  //loading the value of eax at another memory location which is 8(%esp); this location represents b; 
 movl $0, %eax       //making eax zero! the return value of main()!
 leave               //now main() says, please leave me!

12(%esp) представляют собой расположение памяти a и на расстоянии 4 байта от него, то есть 8(%esp) представляет b. В конце значение в обоих этих ячейках памяти равно 4.

Следовательно, b = 4. Также a = 4.