Специалисты, решите простую задачу

Статус: Offline
Реєстрація: 03.12.2009
Повідом.: 22
Специалисты, решите простую задачу

Что выведет этот код?

Код:
	$i = 1;
	$i += ++$i + $i++;
	echo $i;

Только не спешите сразу запускать его, чтобы узнать результат.
Наверняка очень удивитесь, если попробуете решить сами :D
 
Невероятно, я просто в шоке!!! Какой день пхп учите?
 
хм...на асме не компилится...:confused:
 
Школьная задачка по приоритетам операций.
 
Школьная задачка по приоритетам операций.
Всё не так просто. Про PHP ничего не скажу, ибо не знаю, а в C/C++ поведение не определено. См. например
Тільки зареєстровані користувачі бачать весь контент у цьому розділі
 
Невероятно, я просто в шоке!!! Какой день пхп учите?
PHP я "учу" лет 5, не меньше. Просто никогда не использую такие конструкции, в этом нет ничего удивительного. Често - сам сразу ошибся, когда мне такую задачку задали :)
 
Школьная задачка по приоритетам операций.
Да, задачка скорее школьная, на практике такие завороты практически не встречаются. Но вы сможете решить ее?

хм...на асме не компилится...:confused:
А на асме, на сколько я помню, нет базовых операций преинкремент/постинкремент
 
Да, могу решить (что ее решать то? :confused:)
 
Код:
i += ++i + i++;
можно развернуть в
Код:
    i = i + (++i + i++);
который, в свою очередь, можно развернуть в
Код:
    i = i + ( (i = i + 1) + (i + 1) );
идем далее
Код:
    i = i + 1;
    i = i + (i + (i + 1));

Собственно, проверка.

Код:
v0id@faceless ~/projects/c++/test $ ls
main.cpp
v0id@faceless ~/projects/c++/test $ cat main.cpp
#include <iostream>

int main()
{
        int i = 1;
        i += ++i + i++;
        std::cout << i << "\n";
        return 0;
}
v0id@faceless ~/projects/c++/test $ gcc -lstdc++ main.cpp -o test
v0id@faceless ~/projects/c++/test $ ./test
7
v0id@faceless ~/projects/c++/test $
 
Да, чисто на знание приоритета операций, правильно что школьная, т.к. на деле за такой код никто по головке не погладит :)
 
Уважаемый ASokol, прочитайте пожалуйста статью, на которую я дал ссылку и ссылки из неё, например вот эту про "не баг" в gcc
Тільки зареєстровані користувачі бачать весь контент у цьому розділі
.
Код:
    i = i + ( (i = i + 1) + (i + 1) );
идем далее
Код:
    i = i + 1;
    i = i + (i + (i + 1));
Как минимум этот переход в C/C++ не правильный, т.к. добавляет sequence point в виде ";". С ней поведение определено, без неё - нет и может зависеть от использованного компилятора и его настроек.

У Вас наблюдается также ещё один неверный переход:
Код:
    i = i + (++i + i++);
который, в свою очередь, можно развернуть в
Код:
    i = i + ( (i = i + 1) + (i + 1) );
Почему это i++ вдруг стало эквивалентно (i+1)?
Давайте проведём эксперимент проще. Что выдаст следующая программа?
Код:
#include <iostream>

int main()
{
        int i = 1;
        std::cout << (i+1) << i++ << "\n";
        return 0;
}
 
// true
Только я, когда проверял, пошагово расскладывал:
Код:
	$i = 1;
	$temp1 = ++$i;				// $temp1 == 2, $i == 2
	$temp2 = $i++;				// $temp2 == 2, $i == 3
	$temp3 = $temp1 + $temp2;		// $temp3 == 4
	$result = $i + $temp3;			// $result == 7
 
Тема - редкостный боян
 
Дизассемблер выдал:
Код:
 80483f1:       movl   $0x1,-0x8(%ebp)    // присваиваем переменной единичку. i = 1
 80483f8:       addl   $0x1,-0x8(%ebp)    // добавляем единичку к i. i = i + 1
 80483fc:       mov    -0x8(%ebp),%eax    // достаем значение i в регистр 
 80483ff:       add    %eax,%eax          // добавляем значение регистра к этому же регистру 2 + 2 = 4
 8048401:       add    %eax,-0x8(%ebp)    // добавляем значение регистра к значению переменной. 4 + 2 = 6
 8048404:       addl   $0x1,-0x8(%ebp)    // добавляем единичку к значению i. 1 + 6 = 7

То есть я был не прав. На самом деле эквивалентом для gcc будет это

Код:
i = i + 1;
i = ((i + i) + i) + 1;

Давайте проведём эксперимент проще. Что выдаст следующая программа?
Код:
#include <iostream>

int main()
{
        int i = 1;
        std::cout << (i+1) << i++ << "\n";
        return 0;
}
Выдает 3 и 1.

Дизассемблер:
Код:
 80486ae:       c7 45 f4 01 00 00 00    movl   $0x1,-0xc(%ebp)		
 80486b5:       8b 5d f4                mov    -0xc(%ebp),%ebx		
 80486b8:       83 45 f4 01             addl   $0x1,-0xc(%ebp)		
 80486bc:       8b 45 f4                mov    -0xc(%ebp),%eax		
 80486bf:       83 c0 01                add    $0x1,%eax		
 80486c2:       89 44 24 04             mov    %eax,0x4(%esp)            
 80486c6:       c7 04 24 40 a0 04 08    movl   $0x804a040,(%esp)
 80486cd:       e8 26 fe ff ff          call   80484f8 <_ZNSolsEi@plt>
 80486d2:       89 5c 24 04             mov    %ebx,0x4(%esp)
 80486d6:       89 04 24                mov    %eax,(%esp)
 80486d9:       e8 1a fe ff ff          call   80484f8 <_ZNSolsEi@plt>

Весело. Впрочем комилятор предупредил: "main.cpp:6: предупреждение: операция над ‘i’ может дать неопределенный результат".
 
Останнє редагування:
testpearls сказав(ла):
// true
Только я, когда проверял, пошагово расскладывал:
Код:

$i = 1;
$temp1 = ++$i; // $temp1 == 2, $i == 2
$temp2 = $i++; // $temp2 == 2, $i == 3
$temp3 = $temp1 + $temp2; // $temp3 == 4
$result = $i + $temp3; // $result == 7
Забавненько, и что , действительно пхп выдал 7 ?
 
Хе-хе, наследие баша. Подобное много где обсуждалось.
Тільки зареєстровані користувачі бачать весь контент у цьому розділі
 
Назад
Зверху Знизу