Форум программистов, компьютерный форум CyberForum.ru

Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? - C++

Восстановить пароль Регистрация
 
Sammm
3 / 3 / 1
Регистрация: 21.10.2012
Сообщений: 182
02.07.2013, 22:13     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #1
C++
1
2
3
4
5
6
7
#include<stdio.h>
int main(){
int x = 1, y = 1, z = 1, u;
u = ++x || ++y && ++z;
printf("x=%d, y=%d, z=%d, u=%d",x,y,z,u);
return 0;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.07.2013, 22:13     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1?
Посмотрите здесь:

C++ Почему после выполнения команды cprintf значения строк затираются?
C++ Программа тестирования, не могу разобрать свои косяки :(.
как задавать свои значения массива? C++
C++ Почему программа вылетает при конкатенации строк?
Как прописать в #ИМЯ? в Excel свои значения? C++
C++ Массив меняет свои значения
C++ дана программа на С++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
120°
12 / 10 / 1
Регистрация: 01.07.2013
Сообщений: 62
02.07.2013, 22:22     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #2
нет оператора присваивания для этих переменных
C++
1
y = ++y;  // вычисляется значение справа от знака = и присваивается переменной слева от этого знака
Sammm
3 / 3 / 1
Регистрация: 21.10.2012
Сообщений: 182
02.07.2013, 22:30  [ТС]     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #3
120°, без присваивания значение все равно должно увеличиваться, вот пример:
C++
1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main(){
int x = 1, y = 1, z = 1;
++x;
++y;
++z;
printf("x=%d, y=%d, z=%d",x,y,z);
return 0;
}
120°
12 / 10 / 1
Регистрация: 01.07.2013
Сообщений: 62
02.07.2013, 22:36     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #4
прошу прощения. ступил немного
Kuzia domovenok
 Аватар для Kuzia domovenok
1886 / 1741 / 117
Регистрация: 25.03.2012
Сообщений: 5,910
Записей в блоге: 1
02.07.2013, 22:40     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #5
Цитата Сообщение от 120° Посмотреть сообщение
нет оператора присваивания для этих переменных
да ладно? подучи-ка операторы.
Цитата Сообщение от Sammm Посмотреть сообщение
Почему y,z не увеличивают свои значения на 1?
возможно, компилятор оптимизирует код и, заранее присваивает U=1 после первого действия ++x, понимая, что раз х не равен нулю, то и лог.выражение х ИЛИ что-то_там тоже будет равно истине, т.е. единице! И обрывает вычисление выражения.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
12283 / 6970 / 784
Регистрация: 27.09.2012
Сообщений: 17,282
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 01:43     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #6
Kuzia domovenok, Лень всему голова
Sammm, почитайте что-нибудь по теме "Ленивые операторы"
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
03.07.2013, 07:44     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #7
По большому счету здесь дело не в оптимизации, а в стандарте.
5.15 Logical OR operator
1 The || operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). It returns true if either of its operands is true, and false otherwise. Unlike |, || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.

Думаю, это было бы уже слишком, если бы компилятор позволял себе такую оптимизацию вопреки стандартам.
Кстати, в данном случае VC2008++ создает честный код для дебаг-версии

Замечание

Для инкремента целых чисел VC++ создает подобный код:
MOV EAX, DWORD PTR[VAR]
ADD EAX, 1 ; Если результат 0, то ZF будет установлен, иначе - сброшен.
MOV DWORD PTR[VAR], EAX

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
;...
    int x = 1, y = 1, z = 1, u;
004113BE  mov         dword ptr [x],1 
004113C5  mov         dword ptr [y],1 
004113CC  mov         dword ptr [z],1 
 
    u = ++x || ++y && ++z;
; Инкремент x. 
004113D3  mov         eax,dword ptr [x]
004113D6  add         eax,1
004113D9  mov         dword ptr [x],eax
; Переход (true), если ZF==0 (если x!=0)
004113DC  jne         main+60h (411400h)
 
; Инкремент y.
004113DE  mov         ecx,dword ptr [y]
004113E1  add         ecx,1
004113E4  mov         dword ptr [y],ecx
; Переход (false), если ZF==1 (если y==0).
004113E7  je          main+54h (4113F4h)
 
; Инкремент z.
004113E9  mov         edx,dword ptr [z]
004113EC  add         edx,1
004113EF  mov         dword ptr [z],edx
; Переход (true), если ZF==0 (если z!=0).
004113F2  jne         main+60h (411400h)
 
; Результат false, запись в стек.
004113F4  mov         dword ptr [ebp-0F4h],0
 
; Переход (сохранение результата в u).
004113FE  jmp         main+6Ah (41140Ah)
 
; Результат true, запись в стек.
00411400  mov         dword ptr [ebp-0F4h],1
 
; Сохранение результата в u.
0041140A  mov         eax,dword ptr [ebp-0F4h] 
00411410  mov         dword ptr [u],eax 
 
    printf("x=%d, y=%d, z=%d, u=%d",x,y,z,u);
;...


В релизе конечно же оптимизирует и выкидывает все вычисления вообще, сразу заталкивая значения в стек для вызова функции.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main ()
{
    int x = 1, y = 1, z = 1, u;
    u = ++x || ++y && ++z;
    printf("x=%d, y=%d, z=%d, u=%d",x,y,z,u);
00401000  push        1    
00401002  push        1    
00401004  push        1    
00401006  push        2    
00401008  push        offset string "x=%d, y=%d, z=%d, u=%d" (402104h) 
0040100D  call        dword ptr [__imp__printf (4020A0h)] 
00401013  add         esp,14h 
    return 0;
00401016  xor         eax,eax 
}
00401018  ret
-=ЮрА=-
Заблокирован
Автор FAQ
03.07.2013, 09:41     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #8
Sammm, потому что логика твоего алгоритма следующая или ++x или (++y && ++z) - как сказал выше nxtech,
Цитата Сообщение от nxtech Посмотреть сообщение
The || operator groups left-to-right.
, т.е первое ИЛИ всегда отрабатывает, а второе никогда не работает. Собственно переставь в своём коде u = ++y && ++z || ++x; и увидишь что теперь инкремент х не сработал.
А вот если оставить всё как есть и присвоить х значение -1 то получим отработку обоих условий
C
1
2
3
4
5
6
7
#include<stdio.h>
int main(){
int x = -1, y = 1, z = 1, u;
u = ++x || ++y && ++z;
printf("x=%d, y=%d, z=%d, u=%d",x,y,z,u);
return 0;
}
http://codepad.org/aGrzdCzG
В подобных случаях полезно всё разбивать на понятные логике if-else конструкции. Вот для пущего понимания
C
1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
int main(){
int iVal = 0;
int x = -1, y = 1, z = 1, u;
if(iVal = ++x)
   u = iVal;
else
if(iVal = ++y && ++z)
   u = iVal;
printf("x=%d, y=%d, z=%d, u=%d",x,y,z,u);
return 0;
}
http://codepad.org/DnIxmPlR
ValeryS
Модератор
6413 / 4879 / 448
Регистрация: 14.02.2011
Сообщений: 16,176
03.07.2013, 10:01     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #9
Цитата Сообщение от Sammm Посмотреть сообщение
u = ++x || ++y && ++z;
логика операторов И и ИЛИ
ИЛИ равно ИСТИНА если один из операторов ИСТИНА(!=0)
И равно ЛОЖЬ если один из операторов равно ЛОЖЬ(==0)
смотрим
++x ИСТИНА значит и выражение ИСТИНА, нет смысла высчитывать другие операторы, они просто отбрасываются
этот прием можно использовать для "мирных целей"
например
C++
1
if(a&& b/a)
никогда не будет деления на 0
потому что если a==0 это ЛОЖЬ и и второй оператор b/a не будет рассчитываться
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5534 / 2568 / 234
Регистрация: 01.11.2011
Сообщений: 6,345
Завершенные тесты: 1
03.07.2013, 10:26     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? #10
Цитата Сообщение от Croessmah Посмотреть сообщение
почитайте что-нибудь по теме "Ленивые операторы"
А я не будь дураком взял и почитал. )
Очень интересно. Только по запросу "ленивые операторы" нагугливается сплошь только почта и сотовая техподдержка, так что лучше искать по "ленивые вычисления".

Вот даже вынес в отдельную тему - Ленивые вычисления.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.07.2013, 10:39     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1?
Еще ссылки по теме:

C++ Namespaces. Кто создавал свои собственные? Почему-то не работает в VS10
Дана матрица, состоящая из М строк и N столбцов C++
C++ Где в приведенном коде переменные хранят свои значения
Написать генератор случайных чисел, декрементирующий свои значения C++
Почему указатель теряет свои значения после выхода с метода, память выделена динамически C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Croessmah
03.07.2013, 10:39     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1?
  #11

Не по теме:

Цитата Сообщение от SatanaXIII Посмотреть сообщение
Только по запросу "ленивые операторы" нагугливается сплошь только почта и сотовая техподдержка
Первая же страница:
Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1?
не знаю, где тут сотовые операторы с почтой

Yandex
Объявления
03.07.2013, 10:39     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1?
Ответ Создать тему
Опции темы

Текущее время: 13:59. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru