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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.96
Feuer
72 / 72 / 7
Регистрация: 13.10.2008
Сообщений: 144
#1

Помогите чайнику с инкрементом... - C++

13.10.2008, 22:28. Просмотров 3012. Ответов 12
Метки нет (Все метки)

Здравствуйте! Понимаю, конечно, что вопрос наверное дурацкий... но я только начал знакомство с С++, а этот вопрос не дает покоя...

Код
int i=0;
cout<<"i = "<<i<<", (i++)= "<<i++<<endl;
cout<<"i = "<<i;
Как мне казалось, поскольку инкремент постфиксный, то i должно увеличится только ко второй строке, однако результат выполнения таков:
i = 1, (i++)= 0
i = 1
Наверное я чего-то не знаю.... объясните, пожалуйста...
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Skaffi
 Аватар для Skaffi
1 / 1 / 0
Регистрация: 13.10.2008
Сообщений: 10
14.10.2008, 00:10     Помогите чайнику с инкрементом... #2
привет)

все просто) если ты напишешь вот так:
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
 
int main()
{
int i=0;
cout<<"i = "<<i;
cout<<"(i++)= "<<i++<<endl;
cout<<"i = "<<i<<endl;
}
то будет работать, как ты и предполагаешь:

сначала i=0;
потом значение (i++)=0; а i увеличивается на 1, т.е. i=1

Добавлено через 1 минуту 56 секунд
НАВЕРНО, перед тем, как выполнить cout твоего кода, сначала вычисляется i++, следовательно и значение i меняется...
Alirp
 Аватар для Alirp
55 / 50 / 1
Регистрация: 04.05.2008
Сообщений: 273
14.10.2008, 08:15     Помогите чайнику с инкрементом... #3
Приоритер операции ++ больше чем у операции <<, а так как они в одной строке, поэтому инкремент и выполняется раньше. Посмотри приоритеты операций и порядок их выполнения.
http://www.cyberguru.ru/programming/...de-page35.html
igor_nf
118 / 12 / 1
Регистрация: 21.08.2007
Сообщений: 222
14.10.2008, 16:34     Помогите чайнику с инкрементом... #4
Цитата Сообщение от Alirp Посмотреть сообщение
Приоритер операции ++ больше чем у операции <<, а так как они в одной строке, поэтому инкремент и выполняется раньше. Посмотри приоритеты операций и порядок их выполнения.
http://www.cyberguru.ru/programming/...de-page35.html
Боюсь ты ошибаешься. Я сходил по представленной ссылке и не обнаружил там приоритета оператора <<, что впрочем и не удивительно (здесь, я надеюсь, ты различаешь операцию двоичного сдвига и оператор потокового вывода).
Ranofer
2 / 2 / 0
Регистрация: 04.09.2008
Сообщений: 20
14.10.2008, 16:47     Помогите чайнику с инкрементом... #5
"При перегрузке операций сохраняются количество аргументов, приоритеты операций и правила ассоциаций, используемые в стандартных типах данных" - учебник Павловской Т.А.
А операция потокового вывода, это помоему перегруженная операция сдвига..
Но..
Программа
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
    int i=0;
    cout << "i = " << i << ", (i++)= " << i++ << endl;
    cout << "i = " << i << endl;
    system("pause");
    return 0;
}
выдает
i = 0, (i++)= 0
i = 1
Vourhey
Почетный модератор
6471 / 2246 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
14.10.2008, 17:16     Помогите чайнику с инкрементом... #6
Пергрузка операций тут не при чем. Приоритет тоже. Ты читаешь строку слева направо. Никто же не обещал, что операторы потоков буду делать также. Поясняю:
Код
. начинаем выполнение cout
00411A05  mov         eax,dword ptr [i]   грузим текущее значение i в EAX. теперь там 0.
00411A08  mov         dword ptr [ebp-0D0h],eax    .запомнил адрес? 
00411A0E  mov         ecx,dword ptr [i]     . следующие три операции - это инкремент
00411A11  add         ecx,1 
00411A14  mov         dword ptr [i],ecx     . теперь i равно единице
00411A17  mov         esi,esp 
00411A19  mov         edx,dword ptr [__imp_std::endl (41A344h)] 
00411A1F  push        edx      .помещаем символ перехода на новую строку.
00411A20  mov         edi,esp 
00411A22  mov         eax,dword ptr [ebp-0D0h]     .помнишь еще? здесь 0
00411A28  push        eax        .грузим теперь 0
00411A29  push        offset string ", (i++)= " (417868h)     .наша строка, где 0
. обрати внимание на этом шаге у нас уже есть
"(i++)= " 0 endl; 
00411A2E  mov         ebx,esp
00411A30  mov         ecx,dword ptr [i] 
00411A33  push        ecx      .а вот теперь уже грузим i. А он единица.
00411A34  push        offset string "i = " (417800h)     .строку..
00411A39  mov         edx,dword ptr [__imp_std::cout (41A348h)] 
00411A3F  push        edx       .поток cout
00411A40  call        std::operator<<<std::char_traits<char> > (411159h)   .собственно, вызов
Понятно теперь почему?

Добавлено через 5 минут 50 секунд
Если совсем у тебя плохо с ассемблером, то перевожу, как интерпретируется строка:
Код
cout<<"i = "<<i<<", (i++)= "<<i++<<endl;
Первым делом инкрементриую i, запоминаю его предыдущее значение. В конец помещаю переход на новую строку, за ним, я вывожу предыдущее значние i (0), потом в строку толкаю '(i++)= ', потом туда же толкаю уже текущее значение i, и затем строку 'i = '.
Вот и вся марихуана...

Добавлено через 5 минут 30 секунд
Цитата Сообщение от Ranofer Посмотреть сообщение
Но..
Программа
Код
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
    int i=0;
    cout << "i = " << i << ", (i++)= " << i++ << endl;
    cout << "i = " << i << endl;
    system("pause");
    return 0;
}
Молодой человек, Вы гоните. Первая программа у вас аналогичная. Пробелы ничего не меняют.

Добавлено через 14 секунд
Смотри выше, я написал, почему.
Feuer
72 / 72 / 7
Регистрация: 13.10.2008
Сообщений: 144
14.10.2008, 22:22  [ТС]     Помогите чайнику с инкрементом... #7
Спасибо всем, кто откликнулся!
Отдельное спасибо Vourhey!!
Ranofer
2 / 2 / 0
Регистрация: 04.09.2008
Сообщений: 20
15.10.2008, 10:21     Помогите чайнику с инкрементом... #8
Цитата Сообщение от Vourhey Посмотреть сообщение
Молодой человек, Вы гоните. Первая программа у вас аналогичная. Пробелы ничего не меняют.
За объяснение спасибо. =)
Не понял только в каком месте я гоню.
Во-первых, программа не моя я ее скопировал из первого поста и расставил пробелы для удобства. Скомпилировал, запустил и получил..
Код
i = 0, (i++)= 0
i = 1
Добавлено через 11 часов 25 минут 25 секунд
Так, что-то я совсем запутался.

Я видоизменил программу..
Код
#include <iostream>
using namespace std;
int main(){
    int i=0;
    cout << "i = " << i << ", (i++)= " << i++ << ", i = " << i << endl;
    cout << "i = " << i << ", (i++)= " << i++ << ", i = " << i << endl;
    system("pause");
    return 0;
}
и она выдает..
Код
i = 0, (i++)= 0, i = 1
i = 1, (i++)= 1, i = 2
Похоже компилятор забивает на приоритет операции инкремента и читает строку слева-направо. То есть выводит на экран:
1. "i = ",
2. текущее значение i, равное нулю,
3. ", (i++)= ",
4. посчитав и запомнив инкремент, выводит предыдущее значение i, равное нулю (если бы инкремент был префиксный, то тут была бы единица),
5. "i = "
6. текущее значение i, равное единице.

Вот.
Vourhey
Почетный модератор
6471 / 2246 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
15.10.2008, 12:56     Помогите чайнику с инкрементом... #9
Цитата Сообщение от Ranofer Посмотреть сообщение
Похоже компилятор забивает на приоритет операции инкремента и читает строку слева-направо. То есть выводит на экран:
1. "i = ",
2. текущее значение i, равное нулю,
3. ", (i++)= ",
4. посчитав и запомнив инкремент, выводит предыдущее значение i, равное нулю (если бы инкремент был префиксный, то тут была бы единица),
5. "i = "
6. текущее значение i, равное единице.

Вот.
Вот? Для твоей первой задачи я тебе объяснил почему. А сейчас у меня нет времени повторять уже пройденное. Продизассемблируй и узнаешь. Вот.

P. S. а еще многое зависит от реализации операторов потоковых для конкретного компилера и его либ. Вот.
Ranofer
2 / 2 / 0
Регистрация: 04.09.2008
Сообщений: 20
15.10.2008, 16:08     Помогите чайнику с инкрементом... #10
Цитата Сообщение от Vourhey Посмотреть сообщение
а еще многое зависит от реализации операторов потоковых для конкретного компилера и его либ. Вот.
То есть для одной и той же программы:
Код
    int i=0;
    cout << "i = " << i << ", (i++)= " << i++ << endl;
    cout << "i = " << i << endl;
могут быть 2(или более) различных результата:
Код
i = 1, (i++)= 0
i = 1
Код
i = 0, (i++)= 0
i = 1
в зависимости от реализации потоковых операторов для конкретного компилера и его либ?
Vourhey
Почетный модератор
6471 / 2246 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
15.10.2008, 17:28     Помогите чайнику с инкрементом... #11
Судя по тому, что одинаковые программы. Эта:
Код
cout << "i = " << i << ", (i++)= " << i++ << endl;
дает тебе
i = 0, (i++)= 0

и тот же самый код:
Код
cout<<"i = "<<i<<", (i++)= "<<i++<<endl;
дает тебе
i = 1, (i++)= 0

то легко

Добавлено через 6 минут 1 секунду
Этот код
Код
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
    int i=0;
    cout << "i = " << i << ", (i++)= " << i++ << endl;
    cout << "i = " << i << endl;
    system("pause");
    return 0;
}
дает одинаковый результат и в gcc, и в VS2008.

И такой же код:
Код
int i=0;
cout<<"i = "<<i<<", (i++)= "<<i++<<endl;
cout<<"i = "<<i;
дает тот же результат.

И это, блин, правильно. Потому что пробелы ничего не решают. И я не верю тебе, что эти одинаковые программы выводят различный результат.
Ranofer
2 / 2 / 0
Регистрация: 04.09.2008
Сообщений: 20
15.10.2008, 18:45     Помогите чайнику с инкрементом... #12
Посмеялся

Только результат... "i = 1, (i++)= 0" получается не у меня, а у Feuer.
У меня же "i = 0, (i++)= 0".

Программа одна и та же (и не надо меня в пробелы тыкать ), скопирована у Feuer.

пс. Компилирую в dev-c++ (g++)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.10.2008, 21:25     Помогите чайнику с инкрементом...
Еще ссылки по теме:

Поясните чайнику что тут не так C++
C++ помогите!
C++ Объясните чайнику в чем ошибка
C++ Связный список- Объясните чайнику

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

Или воспользуйтесь поиском по форуму:
Vourhey
Почетный модератор
6471 / 2246 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
15.10.2008, 21:25     Помогите чайнику с инкрементом... #13
Ну да, я вас спутал.
ОК. Тем более, какие тогда вобще вопросы? Разная реализация, если по разному себя ведет. Проблемы не вижу в переписке операторов вывода/вывода потока.
Я объяснил Feuer, почему у него так работает. Не понимаю, что еще нужно? Продизассемблируй свой код и узнаешь, почему у тебя нули. И VS и g++ в моем случае дают результат Feuer.

P. S. когда человек не втыкает его тыкают...
Yandex
Объявления
15.10.2008, 21:25     Помогите чайнику с инкрементом...
Ответ Создать тему
Опции темы

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