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

Скобки не работают с постфиксным инкрементом - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.88
RNT
Автор FAQ
 Аватар для RNT
3131 / 351 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
19.09.2010, 12:40     Скобки не работают с постфиксным инкрементом #1
Почему скобки не работают с постфиксным инкрементом ? Программа должна вывести 1, а выводит 0. Без скобок приоритет постфиксного инкремента был ниже операции присваивания, а со скобками должен стать выше. Но почему-то приоритет не меняется.

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
 
int main ( )
{
    int var1=0, var2=0;
    var2= (var1++);
    cout <<  var2  << endl;
    return 0;
}
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Manjak
 Аватар для Manjak
268 / 174 / 7
Регистрация: 12.03.2010
Сообщений: 494
19.09.2010, 12:52     Скобки не работают с постфиксным инкрементом #2
При чем тут вообще приоритет операций? постфиксный инкремент возвращает старое значение переменной
RNT
Автор FAQ
 Аватар для RNT
3131 / 351 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
19.09.2010, 15:20  [ТС]     Скобки не работают с постфиксным инкрементом #3
Цитата Сообщение от Manjak Посмотреть сообщение
При чем тут вообще приоритет операций? постфиксный инкремент возвращает старое значение переменной
Если так, то переменной var в нижеприведенном исходнике должен быть присвоен 0, но присвоена 1

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
 
int main ( )
{
    int var = 0;
    var = var++;
    cout <<  var  << endl; //Выводит 1
    return 0;
}
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
19.09.2010, 16:27     Скобки не работают с постфиксным инкрементом #4
RNT, Эм... У тебя одна переменная.
var = var++;
Здесь еще var которому ты приравниваешь равен 0.
cout << var << endl; var=1;

Попробуй лучше уж так:

C++
1
2
3
4
5
6
7
8
9
#include <iostream>
 
int main()
{
    int i=0;
    int var=i++;
    std::cout<<var<<' '<<i<<'\n';
    return 0;
}
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,307
19.09.2010, 16:35     Скобки не работают с постфиксным инкрементом #5
Цитата Сообщение от RNT Посмотреть сообщение
Если так, то переменной var в нижеприведенном исходнике должен быть присвоен 0, но присвоена 1
C++
1
 var = var++;
A может оказаться хоть "Hello, World!" :-) UB, однако....
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
19.09.2010, 16:35     Скобки не работают с постфиксным инкрементом #6
CheshireCat, Да не. Там же в начале:

int var = 0;
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,307
19.09.2010, 16:47     Скобки не работают с постфиксным инкрементом #7
Не. Именно UB в чистом виде, и именно в этой строке - более одной модификации одной и той же переменной (var) до достижения точки следования.
RNT
Автор FAQ
 Аватар для RNT
3131 / 351 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
19.09.2010, 17:13  [ТС]     Скобки не работают с постфиксным инкрементом #8
Нашел в Википедии

http://ru.wikipedia.org/wiki/%D0%A2%...BD%D0%B8%D1%8F
Точки следования необходимы в ситуации, когда одна и та же переменная изменяется в выражении более одного раза. Часто в качестве примера приводят выражение i=i++, в котором происходит присваивание переменной i и её же инкремент. Какое значение примет i? Стандарт языка должен либо указать одно из возможных поведений программы как единственно допустимое, либо указать диапазон допустимых поведений (см. неуточняемое поведение), либо указать, что поведение программы в данном случае совершенно не определено (см. неопределённое поведение). В языках C и C++ вычисление выражения i=i++ приводит к неопределённому поведению, поскольку это выражение не содержит внутри себя ни одной точки следования.
Видимо, мой код вообще некорректен.
Manjak
 Аватар для Manjak
268 / 174 / 7
Регистрация: 12.03.2010
Сообщений: 494
19.09.2010, 17:36     Скобки не работают с постфиксным инкрементом #9
На самом деле понять почему неправильно работает тот код достаточно просто, но обьяснять зачем eax, ecx регистры смысла не вижу, просто не надо так делать.

Assembler
1
2
3
4
5
001017F5  mov         eax,dword ptr [var]  
001017F8  mov         dword ptr [var],eax  
001017FB  mov         ecx,dword ptr [var]  
001017FE  add         ecx,1  
00101801  mov         dword ptr [var],ecx
RNT
Автор FAQ
 Аватар для RNT
3131 / 351 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
20.09.2010, 18:42  [ТС]     Скобки не работают с постфиксным инкрементом #10
Цитата Сообщение от Manjak Посмотреть сообщение
При чем тут вообще приоритет операций? постфиксный инкремент возвращает старое значение переменной
А когда все-таки происходит увеличение переменной ? После того, как выполнится вся строка ?
Manjak
 Аватар для Manjak
268 / 174 / 7
Регистрация: 12.03.2010
Сообщений: 494
20.09.2010, 19:30     Скобки не работают с постфиксным инкрементом #11
Для "var = var++" сразу выполняется оператор = а потом уже ++.
А посфиксный инкремент работает так
C++
1
2
3
4
5
{
    int retVal = val;
    ++val;
    return retVal;
}
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
22.09.2010, 08:21     Скобки не работают с постфиксным инкрементом #12
Цитата Сообщение от RNT Посмотреть сообщение
А когда все-таки происходит увеличение переменной ? После того, как выполнится вся строка ?
Вот же:
Цитата Сообщение от Manjak Посмотреть сообщение
Assembler
1
2
3
4
5
001017F5  mov         eax,dword ptr [var]  
001017F8  mov         dword ptr [var],eax  
001017FB  mov         ecx,dword ptr [var]  
001017FE  add         ecx,1  
00101801  mov         dword ptr [var],ecx
Здесь видно, что сначала происходит присваивание, а потом инкремент.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16822 / 5243 / 318
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
22.09.2010, 11:03     Скобки не работают с постфиксным инкрементом #13
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Manjak, вроде бы уже тут поясняли. То, что ты видишь в коде - это построение кода конкретно на твоём компиляторе. Другой компилятор может посторить другой код. Undefined Behaviour означает, что нельзя даже теоретически предложить "правильный" выход из сложившейся ситуации, а потому какждый компилятор в какждом UB случае ведёт себя так, как звёзды встали

Добавлено через 1 час 40 минут
Ну и, чисто для демонстрации того, что такое Undefined Behaviour. Запускал на sparc'е, поскольку только на нём имею возможность запустить на двух разных компиляторах

C
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
int a = 0, b = 0;
 
int
main (void)
{
  a = b++ + b++;
  printf ("a=%d b=%d\n", a, b);
}
Компилятор gcc выдаёт "a=0 b=1"
Компилятор sun cc выдаёт "a=1 b=2"

Теперь немного перепишем исходник: переменные вместо глобальных сделаем локальными

C
1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int
main (void)
{
  int a = 0, b = 0;
  a = b++ + b++;
  printf ("a=%d b=%d\n", a, b);
}
Компилятор gcc выдаёт "a=0 b=2"
Компилятор sun cc выдаёт "a=0 b=2"

Итого получили как минимум три различных результата
Black Fregat
 Аватар для Black Fregat
1353 / 983 / 215
Регистрация: 31.05.2009
Сообщений: 4,093
22.09.2010, 11:21     Скобки не работают с постфиксным инкрементом #14
Вот тут на эту тему вполне толково разжевано: http://alenacpp.blogspot.com/2005/11...ce-points.html
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
22.09.2010, 11:23     Скобки не работают с постфиксным инкрементом #15
Evg, а можете объяснить, почему в данном случае поведение локальной переменной отличается от глобальной?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16822 / 5243 / 318
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
22.09.2010, 11:30     Скобки не работают с постфиксным инкрементом #16
Цитата Сообщение от Kastaneda Посмотреть сообщение
Evg, а можете объяснить, почему в данном случае поведение локальной переменной отличается от глобальной?
Различия идут от того, что в случае глобальной переменной она попадает в память, а в случае локальной - компилятор пытаяется её запихнуть на регистр. А дальнейшая конкретная причина кроется в особенностях устройства компилятора. На то оно и undefined behaviour, что компилятор не следит за корректностью в этом случае, а потому тут получилось так, как получилось. При желании можно поиграться с опциями и увидеть, что даже при разных опциях на одном компиляторе можно получить разные результаты
Manjak
 Аватар для Manjak
268 / 174 / 7
Регистрация: 12.03.2010
Сообщений: 494
22.09.2010, 11:30     Скобки не работают с постфиксным инкрементом #17
Ну, во-первых, это код из области маразма, и да он будет по разному собран разными компиляторами. В куске, что я показал, код сгенерированный МСовским компилятором, тем, которым пользуется автор темы, тот же gcc выдаст 1. А к чему разводить полемику по данному поводу?
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
22.09.2010, 11:37     Скобки не работают с постфиксным инкрементом #18
Цитата Сообщение от Evg Посмотреть сообщение
Различия идут от того, что в случае глобальной переменной она попадает в память, а в случае локальной - компилятор пытаяется её запихнуть на регистр.
Это я знал, просто я подумал, что есть какое-то объяснение того, что результаты разные и(как я думал) зависят от типа хранения переменной.

Не по теме:

А вот про "точки следования" признаюсь вообще не знал

Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16822 / 5243 / 318
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
22.09.2010, 12:00     Скобки не работают с постфиксным инкрементом #19
Цитата Сообщение от Manjak Посмотреть сообщение
Ну, во-первых, это код из области маразма
Плевать из какой области. Это наглядная демонстрация того, как будет построен код, содержащий UB. К тому же коэффициэнт маразма моего примера строго равен коэффициэнту маразма примера "var = var++" (с точки зрения стандарта)

Цитата Сообщение от Manjak Посмотреть сообщение
В куске, что я показал, код сгенерированный МСовским компилятором, тем, которым пользуется автор темы, тот же gcc выдаст 1. А к чему разводить полемику по данному поводу?
Для объяснения того, как работает эта программа, ты продемонстрировал фрагмент ассемблерного кода и из твоих слов вытекало, что вот дескать так оно и должно работать. Я достаточно внятно (как мне показалось) пояснил, что подобные коды будут работать как бог на душу положит, а доказательства в виде кода одного из компиляторов не канают. Мои пояснения адресованы в первую очередь тем, кто может неправильно истолковать твои слова. Что ты хотел пояснить - я так и не понял, но из контекста всей темы довольно чётко себе представляю, что кто-то из начинающих сделает из твоих слов неправильный вывод
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.09.2010, 12:13     Скобки не работают с постфиксным инкрементом
Еще ссылки по теме:

Конструктор и скобки C++
Проверка на скобки C++
Для каждой открывающей скобки найти позицию ей соответствующей закрывающей скобки C++

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

Или воспользуйтесь поиском по форуму:
Manjak
 Аватар для Manjak
268 / 174 / 7
Регистрация: 12.03.2010
Сообщений: 494
22.09.2010, 12:13     Скобки не работают с постфиксным инкрементом #20
Цитата Сообщение от Manjak Посмотреть сообщение
просто не надо так делать.
Специально добавил, а информацию о внутренней обработке, по моему, новичку не то что трудно будет усвоить, ему, извините за мой французский, порвет башню.
Yandex
Объявления
22.09.2010, 12:13     Скобки не работают с постфиксным инкрементом
Ответ Создать тему
Опции темы

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