Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
73 / 7 / 0
Регистрация: 29.03.2011
Сообщений: 94
1

Изменение значение переменной в одном выражении

13.06.2012, 05:25. Просмотров 895. Ответов 13
Метки нет (Все метки)

Доброго утра! Написала такую нехитрую программку, посмотреть что будет, если вычислить j++ * ++j/j-- * --j... и тут я в ступоре....((( почему такой результат??
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
int main(int argc, char ** argv)
{
  int j, tmp;
 
  std::cout << "j-> "; std::cin >> j;
  tmp = j;
  std::cout << "j++ * ++j/j-- * --j  -> " << j++ * ++j/j-- * --j << "\n";
  j = tmp;
  std::cout << "tmp -> " << tmp << "\nj++ -> " << j++ << "\n++j -> " << ++j 
  << "\nj-- -> " << j-- << "\n--j -> " << --j << "\n";
 
  return 0;
}
вот что на выходе
xenia@glandule:~$ cd ~/Рабочий\ стол
xenia@glandule:~/Рабочий стол$ g++ t.cpp
xenia@glandule:~/Рабочий стол$ strip a.out
xenia@glandule:~/Рабочий стол$ ./a.out
j-> 5
j++ * ++j/j-- * --j -> 25
tmp -> 5
j++ -> 4
++j -> 4
j-- -> 4
--j -> 4
xenia@glandule:~/Рабочий стол$


точнее, меня интересует почему
tmp -> 5
j++ -> 4
++j -> 4
j-- -> 4
--j -> 4

а не
tmp -> 5
j++ -> 5
++j -> 6
j-- -> 6
--j -> 5

почему j++ * ++j/j-- * --j = 25 вроде поняла))
т.к. для j = 5 будет j++ = 5; ++j = 6 -> 5*6 = 30; j-- = 6 -> 30/6 = 5; --j = 5 -> 5*5 = 25

Заранее спасибки за объяснение))

Если это важно
ОС: Ubuntu 12.04 LTS 64-bit

xenia@glandule:~/Рабочий стол$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
Это свободно распространяемое программное обеспечение. Условия копирования
приведены в исходных текстах. Без гарантии каких-либо качеств, включая
коммерческую ценность и применимость для каких-либо целей.

xenia@glandule:~/Рабочий стол$


Не по теме:

Более информативного названия темы, к сожалению, не придумала(((

0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.06.2012, 05:25
Ответы с готовыми решениями:

Как визуально отследить изменение переменной в одном обработчике события?
Всем здравствуйте. При клике по Button1 через 3 сек в метке Label1 появится сообщение 'конец'....

Изменение значение переменной в отладке
Добрый день! Подскажите, имеется ли возможность в 8,3 на ходу в ходе отладки изменять значение...

Изменение текста в label на значение переменной
Есть переменная: int Points = 0; Отобразить значение этой переменно в label почему-то не...

как передать значение переменной которую я вводил в одном классе в другой класс (ввожу я в консоле)
class Registracia { public void Sakas() { Console.Write(&quot;Вес...

13
What a waste!
1576 / 1277 / 171
Регистрация: 21.04.2012
Сообщений: 2,677
13.06.2012, 05:28 2
Цитата Сообщение от Ксю92 Посмотреть сообщение
j++ * ++j/j-- * --j
Результат не определён, т.е. тут вообще может быть что угодно.
1
73 / 7 / 0
Регистрация: 29.03.2011
Сообщений: 94
13.06.2012, 05:29  [ТС] 3
Цитата Сообщение от gray_fox Посмотреть сообщение
Результат не определён, т.е. тут вообще может быть что угодно.
Почему? Ведь я явно ввожу значение в j
0
Форумчанин
Эксперт CЭксперт С++
8157 / 5005 / 1436
Регистрация: 29.11.2010
Сообщений: 13,458
13.06.2012, 05:34 4
предположим j = 5
Берем его и суммируем с самим собой, учитывая, что после того, как написали j++ j уже равна 6, а при операции ++j мы сначала добавляем 1, т.е. j уже становится равна 7. j++ * ++j это 5 * 7.
j-- На момент обращения j = 7, после равна 6. Выходит j++ * ++j / j-- = 5 * 7 / 7. При этом j = 6. Умножаем мы на --j, т.е. сначала отнимаем единицу, а потом умножаем. Выходит, что
j++ * ++j / j-- * --j == 5(j = 6) * 7(j = 7) / 7(j = 6) * 5(j = 5) == 5 * 7 / 7 * 5 == 25.
1
What a waste!
1576 / 1277 / 171
Регистрация: 21.04.2012
Сообщений: 2,677
13.06.2012, 05:36 5
Лучший ответ Сообщение было отмечено как решение

Решение

Ну я в формальных определениях не особо силён, надо искать на тему "точки следования" или как то так... Суть в том, что изменение значения переменной в одном выражении (до ';') определено как "undefined behaviour".

Добавлено через 1 минуту
Вот здесь есть про это: http://alenacpp.blogspot.com/2... oints.html
3
73 / 7 / 0
Регистрация: 29.03.2011
Сообщений: 94
13.06.2012, 05:38  [ТС] 6
Цитата Сообщение от Ксю92 Посмотреть сообщение
почему j++ * ++j/j-- * --j = 25 вроде поняла))
т.к. для j = 5 будет j++ = 5; ++j = 6 -> 5*6 = 30; j-- = 6 -> 30/6 = 5; --j = 5 -> 5*5 = 25
Это я поняла))

Вы мне объясните, почему
Цитата Сообщение от Ксю92 Посмотреть сообщение
точнее, меня интересует почему
tmp -> 5
j++ -> 4
++j -> 4
j-- -> 4
--j -> 4

а не
tmp -> 5
j++ -> 5
++j -> 6
j-- -> 6
--j -> 5
тут j = tmp изначально
0
Форумчанин
Эксперт CЭксперт С++
8157 / 5005 / 1436
Регистрация: 29.11.2010
Сообщений: 13,458
13.06.2012, 05:40 7
В статье все написано.

Для себя тоже подчерпнул много интересного)
1
What a waste!
1576 / 1277 / 171
Регистрация: 21.04.2012
Сообщений: 2,677
13.06.2012, 05:46 8
Ксю92, тут (там, где с выводом) тоже самое: несколько раз изменяете значение переменной j. То, что там будет что то осмысленное, никто не гарантирует.
1
73 / 7 / 0
Регистрация: 29.03.2011
Сообщений: 94
13.06.2012, 05:48  [ТС] 9
Цитата Сообщение от MrGluck Посмотреть сообщение
Потому что std::cout<< j++ означает сначала вывести на экран, а потом добавить 1.
++j напротив сначала добавляет 1, потом выводит на экран.
вот смотрим на мой код
C++
1
2
std::cout << "tmp -> " << tmp << "\nj++ -> " << j++ << "\n++j -> " << ++j 
  << "\nj-- -> " << j-- << "\n--j -> " << --j << "\n";
j мы вводим с клавиатуры. Допустим, ввели 5
j++ выведется на экран 5; но j увеличится на 1 (теперь j = 6)
++j j увеличится на 1, и выведется на экран, т.е. выведется 7
j-- выведется также 7, т.к. сначала выводим текущее значение, а потом уменьшаем на 1 (теперь j = 6)
--j выведется 5, т.к. сначала уменьшили на 1, а потом вывели

НО ПОЧЕМУ ВЫВОДИТСЯ
j++ -> 4
++j -> 4
j-- -> 4
--j -> 4


Добавлено через 46 секунд
Сейчас статью буду читать)
0
What a waste!
1576 / 1277 / 171
Регистрация: 21.04.2012
Сообщений: 2,677
13.06.2012, 05:49 10
Цитата Сообщение от Ксю92 Посмотреть сообщение
++ выведется на экран 5; но j увеличится на 1 (теперь j = 6)
++j j увеличится на 1, и выведется на экран, т.е.
т.е. дважды изменяешь значение одной переменной в одном выражении. всё, приехали)
1
бжни
2467 / 1676 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
13.06.2012, 05:52 11
Лучший ответ Сообщение было отмечено как решение

Решение

включаем у gcc опцию -Wsequence-point и смотрим, что он по этому поводу думает
4
73 / 7 / 0
Регистрация: 29.03.2011
Сообщений: 94
13.06.2012, 05:57  [ТС] 12
Цитата Сообщение от gray_fox Посмотреть сообщение
т.е. дважды изменяешь значение одной переменной в одном выражении. всё, приехали)
gray_fox, не не)) все верно) выведется на экран 5 но значение j увеличится на 1 (теперь j = 6)

Добавлено через 3 минуты
Цитата Сообщение от alex_x_x Посмотреть сообщение
включаем у gcc опцию -Wsequence-point и смотрим, что он по этому поводу думает
Вот что он думает))
xenia@glandule:~$ cd ~/Рабочий\ стол
xenia@glandule:~/Рабочий стол$ g++ t.cpp -Wsequence-point
t.cpp: В функции «int main(int, char**)»:
t.cpp:31:73: предупреждение: операция над «j» может дать неопределенный результат [-Wsequence-point]
t.cpp:31:73: предупреждение: операция над «j» может дать неопределенный результат [-Wsequence-point]
t.cpp:31:73: предупреждение: операция над «j» может дать неопределенный результат [-Wsequence-point]
t.cpp:33:128: предупреждение: операция над «j» может дать неопределенный результат [-Wsequence-point]
xenia@glandule:~/Рабочий стол$ strip a.out
xenia@glandule:~/Рабочий стол$ ./a.out
j-> 5
j++ * ++j/j-- * --j -> 25
tmp -> 5
j++ -> 4
++j -> 4
j-- -> 4
--j -> 4
xenia@glandule:~/Рабочий стол$


P.S. В принципе, это ответ на мой вопрос))

Добавлено через 24 секунды
alex_x_x, спасибки!))
0
Эксперт С++
2328 / 1701 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
17.07.2012, 00:47 13
Ксю92, на самом деле в Вашем примере все очевидно, как уже сказали переменная модифицируется дважды не переходя через точку следования. Есть менее очевидные способы наступить на грабли:
C++
1
2
3
4
void foo(int, int);
 
int i = 1;
foo(i, ++i); // UB
C++
1
2
3
int a = [1, 2, 3, 4];
int i = 0;
a[i] = ++i; // UB
C++
1
2
int a = 0, b = 1, c = 2;
(a += b) += c; // UB
В С++11 дела с этим обстоят лучше, т.к. вместо точек следования было введено отношение sequenced before.
1
606 / 406 / 8
Регистрация: 26.04.2012
Сообщений: 2,069
17.07.2012, 01:05 14
собственно вторую часть кода все правильно вывел (по которой был вопрос). а вот почему формула в ответе 30 дала - ХЗ...
1
Миниатюры
Изменение значение переменной в одном выражении  
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.07.2012, 01:05

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

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

Как передать значение переменной PHP в одном файле в переменную JS в другом файле?
Подскажите пожалуйста, как передать значение PHP из одного файла в JS в другом. Везде облазил....

Один и тот же объект в одном выражении модифицируется несколько раз - неопределенное поведение
Уважаемые форумчане! Недавно столкнулся с интересным на мой взгляд необычным поведением компилятора...

Надо вывести название переменной, тип данных переменной, значение переменной
у нас есть переменная int variable = 0; Надо вывести название переменной, тип данных переменной,...


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

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

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