Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Sammm
3 / 3 / 1
Регистрация: 21.10.2012
Сообщений: 182
#1

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

02.07.2013, 22:13. Просмотров 537. Ответов 10
Метки нет (Все метки)

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;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.07.2013, 22:13
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1? (C++):

Почему указатель теряет свои значения после выхода с метода, память выделена динамически - C++
#include &lt;iostream&gt; using namespace std; void sqr( int* a, int length ); int main() { int *a = new int; int length =...

Почему переменные одного и того же класса меняют свои значения одновременно - C++/CLI
Действительно, столкнулся с таким фактом. Объявляю свой класс: ref class My_Class { public: static array&lt;int&gt;^ mas = gcnew...

Дана прямоугольная таблица a[1:n,1:n]. Найти количество строк, начинающихся со значения t - C#
Дана прямоугольная таблица a. Найти количество строк, начинающихся со значения t. (Двумерный массив)

Дана прямоугольная таблица a[1:n,1:n]. Найти количество строк, начинающихся со значения t - C#
Дана прямоугольная таблица a. Найти количество строк, начинающихся со значения t.

Почему INSERT INTO удаляет значения из уже существующих строк? - MySQL
Делаю запрос TRUNCATE `table1`; INSERT INTO `table1` (`id`,`date`) SELECT `id`, `date` FROM `table2`; даные вставляются. потом ...

Почему после выполнения команды cprintf значения строк затираются? - C++
Здраствуйте. Помогите пожалуйста, что это может быть, что вот уже больше дня играюсь с билдером и он непонятно что творит. Например,...

10
120°
12 / 10 / 1
Регистрация: 01.07.2013
Сообщений: 62
02.07.2013, 22:22 #2
нет оператора присваивания для этих переменных
C++
1
y = ++y;  // вычисляется значение справа от знака = и присваивается переменной слева от этого знака
0
Sammm
3 / 3 / 1
Регистрация: 21.10.2012
Сообщений: 182
02.07.2013, 22:30  [ТС] #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;
}
0
120°
12 / 10 / 1
Регистрация: 01.07.2013
Сообщений: 62
02.07.2013, 22:36 #4
прошу прощения. ступил немного
0
Kuzia domovenok
1948 / 1801 / 137
Регистрация: 25.03.2012
Сообщений: 6,240
Записей в блоге: 1
02.07.2013, 22:40 #5
Цитата Сообщение от 120° Посмотреть сообщение
нет оператора присваивания для этих переменных
да ладно? подучи-ка операторы.
Цитата Сообщение от Sammm Посмотреть сообщение
Почему y,z не увеличивают свои значения на 1?
возможно, компилятор оптимизирует код и, заранее присваивает U=1 после первого действия ++x, понимая, что раз х не равен нулю, то и лог.выражение х ИЛИ что-то_там тоже будет равно истине, т.е. единице! И обрывает вычисление выражения.
2
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
03.07.2013, 01:43 #6
Kuzia domovenok, Лень всему голова
Sammm, почитайте что-нибудь по теме "Ленивые операторы"
0
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
03.07.2013, 07:44 #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
0
-=ЮрА=-
Заблокирован
Автор FAQ
03.07.2013, 09:41 #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
1
ValeryS
Модератор
6705 / 5114 / 482
Регистрация: 14.02.2011
Сообщений: 17,183
03.07.2013, 10:01 #9
Цитата Сообщение от Sammm Посмотреть сообщение
u = ++x || ++y && ++z;
логика операторов И и ИЛИ
ИЛИ равно ИСТИНА если один из операторов ИСТИНА(!=0)
И равно ЛОЖЬ если один из операторов равно ЛОЖЬ(==0)
смотрим
++x ИСТИНА значит и выражение ИСТИНА, нет смысла высчитывать другие операторы, они просто отбрасываются
этот прием можно использовать для "мирных целей"
например
C++
1
if(a&& b/a)
никогда не будет деления на 0
потому что если a==0 это ЛОЖЬ и и второй оператор b/a не будет рассчитываться
0
SatanaXIII
Супер-модератор
Эксперт С++
5618 / 2653 / 246
Регистрация: 01.11.2011
Сообщений: 6,549
Завершенные тесты: 1
03.07.2013, 10:26 #10
Цитата Сообщение от Croessmah Посмотреть сообщение
почитайте что-нибудь по теме "Ленивые операторы"
А я не будь дураком взял и почитал. )
Очень интересно. Только по запросу "ленивые операторы" нагугливается сплошь только почта и сотовая техподдержка, так что лучше искать по "ленивые вычисления".

Вот даже вынес в отдельную тему - Ленивые вычисления.
0
Croessmah
03.07.2013, 10:39     Дана программа из 7 строк. Почему y,z не увеличивают свои значения на 1?
  #11

Не по теме:

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

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.07.2013, 10:39
Привет! Вот еще темы с ответами:

Почему программа вылетает при конкатенации строк? - C++
Собственно код #ifndef __STRING #define __STRING #include &lt;ostream&gt; class String { public: String();

Почему программа выводит сообщение на одной строке а запрос ввода значения на другой? - C#
Всем добрый день. Подскажите пожалуйста нубу, почему программа выводит сообщение на одной строке а запрос ввода значения на другой, а также...

Найти среднее арифметическое элементов каждой из строк заданной матрицы (почему не работает программа?) - C (СИ)
Задана квадратная матрица А размером N х N (N&lt;=10), состоящая из действительных элементов. Найти среднее арифметическое элементов каждой...

Структуры и ввод строк с пробелами: программа пропускает второй шаг, сразу переходя к третьему - почему? - C++
Здравствуйте, уважаемые форумчане! Я новичок и в С++ и на этом форуме, так что прошу сильно не пинать. Начал заниматься по книге Стивена...


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

Или воспользуйтесь поиском по форуму:
11
03.07.2013, 10:39
Ответ Создать тему
Опции темы

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