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

Загадка указателей - C++

Восстановить пароль Регистрация
 
 
bigibug
0 / 0 / 0
Регистрация: 03.04.2014
Сообщений: 3
03.04.2014, 23:06     Загадка указателей #1
Здравствуйте =) Привел меня к Вам следующий вопрос.
Поступило задание составить программу для решения квадратного уровнения, используя указатели.
В процессе работы наткнулся на то что, казалось бы, одно и тоже (по смыслу) выдает разные результаты.
Преподаватель работу принял, но разницу не смог обьяснить. А я теперь ночами спать не могу, понять хочу что не так сделал. =) Единственная разница выделена жирным шрифтом.
Подскажите, пожалуйста, почему 2 следующие программы выдают столь различные результаты?
Листинг 1
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
]#include<iostream>
#include<math.h>
using namespace std;
int main()
{
    int *p=new int[3],i,j=0;
    double x1,x2,d;
    char *t="abc";
    char *q=t;
    while (*q) 
    {
    cout<<*q++<<"=";
   [B] cin>>*(p+j);j++;[/B]
    for (i=0;i<3;i++) cout<<*(p+i)<<endl;     
    }
    d=pow(p[1],2)-4*p[0]*p[2];
    cout<<"d="<<d<<endl;
    if (d>=0) {x1=(-p[1]+sqrt(d))/2*(p[0]);
               x2=(-p[1]-sqrt(d))/2*(p[0]);
               cout<<"x1="<<x1<<endl<<"x2="<<x2;
        }
    else cout<<"net corney";
    delete [] p;
}

Результат 1
Кликните здесь для просмотра всего текста

a=1
1
0
0
b=5
1
5
0
c=4
1
5
4
d=9
x1=-1
x2=-4

Листинг 2
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
    int *p=new int[3],i,j=0;
    double x1,x2,d;
    char *t="abc";
    char *q=t;
    while (*q) 
    {
    cout<<*q++<<"=";
   [B] cin>>*p++;[/B]
    for (i=0;i<3;i++) cout<<*(p+i)<<endl;     
    }
    d=pow(p[1],2)-4*p[0]*p[2];
    cout<<"d="<<d<<endl;
    if (d>=0) {x1=(-p[1]+sqrt(d))/2*(p[0]);
               x2=(-p[1]-sqrt(d))/2*(p[0]);
               cout<<"x1="<<x1<<endl<<"x2="<<x2;
        }
    else cout<<"net corney";
    delete [] p;
}

Результат 2
Кликните здесь для просмотра всего текста

a=1
0
0
1035
b=5
0
1035
892547121
c=4
1035
892547121
842086196
d=6ю53828e+17
x1=1.72275e+10
x2=-8.1967e+11
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
03.04.2014, 23:26     Загадка указателей #2
Все потому, что во втором случае ты указатель на массив просто-напросто теряешь (p - изменяется!!!). Т.е. p теперь указывает не на то, что должен (начало массива из интов) - на место за массивом, а там мусор, вообще говоря. Ну по результатам видно и так)

C++
1
2
3
int *cur = p;
------
cin>>*cur++;
Так получишь то, что тебе нужно.
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:27     Загадка указателей #3
cin>>*p++;
Здесь сначала выполнится постфиксный инкремент, указатель изменит свое значение, а затем этот увеличенный указатель будет разыменован.
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
03.04.2014, 23:28     Загадка указателей #4
Цитата Сообщение от Dani Посмотреть сообщение
Здесь сначала выполнится постфиксный инкремент, указатель изменит свое значение, а затем этот увеличенный указатель будет разыменован.
Не в том дело... тем более это неверно.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11800 / 6779 / 765
Регистрация: 27.09.2012
Сообщений: 16,829
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:31     Загадка указателей #5
Изменяете сам указатель, поэтому потом он "указывает" черт знает куда.

Добавлено через 1 минуту
Цитата Сообщение от monolit Посмотреть сообщение
Не в том дело...
как раз в этом! В куске кода
C++
1
cin>>*(p+j)
указатель p не изменяется, а в
C++
1
cin>>*p++;
изменяется и сам указатель
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:33     Загадка указателей #6
Цитата Сообщение от monolit Посмотреть сообщение
Не в том дело... тем более это неверно.
Это почему еще?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11800 / 6779 / 765
Регистрация: 27.09.2012
Сообщений: 16,829
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:42     Загадка указателей #7
Цитата Сообщение от Dani Посмотреть сообщение
Это почему еще?
думаю, было пропущено несколько слов из предложения
Цитата Сообщение от Dani Посмотреть сообщение
Здесь сначала выполнится постфиксный инкремент, указатель изменит свое значение, а затем этот увеличенный указатель будет разыменован.
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:42     Загадка указателей #8
Цитата Сообщение от monolit Посмотреть сообщение
тем более это неверно
Понял, не так написал: указатель увеличится, но разыменуется еще старый указатель, т.к. инкремент постфиксный.
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
03.04.2014, 23:43     Загадка указателей #9
как раз в этом! В куске кода
Я понимаю) Но тогда вторая часть фразы
а затем этот увеличенный указатель будет разыменован
здесь не нужна, ибо она ситуацию не проясняет - а только уводит внимание (с разыменованием у него все нормально, и заполнением массива тоже - вы это и так знаете) Вот на это я и указал. Тем более с порядком операций он все-таки ошибся)
Да и вообще, не о чем тут говорить - на пустом месте такая дискуссия развернулась.

Кликните здесь для просмотра всего текста

Цитата Сообщение от Croessmah Посмотреть сообщение
изменяется и сам указатель
Это в самом первом посте я и написал)
bigibug
0 / 0 / 0
Регистрация: 03.04.2014
Сообщений: 3
04.04.2014, 09:44  [ТС]     Загадка указателей #10
Ага, значит вводя *p++ я получаю не выражение *(p+1), указывающее на адрес следующего элемента массива p[], а, грубо говоря, указатель на 'p+1' значение которого впринципе фиг пойми какое. Я правильно понял?
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
04.04.2014, 09:48     Загадка указателей #11
Цитата Сообщение от bigibug Посмотреть сообщение
значение которой впринципе фиг пойми какое
ну не фиг пойми, а p + sizeof(тип на который указывает указатель)
Цитата Сообщение от bigibug Посмотреть сообщение
Я правильно понял?
да операция p+1, вернет указатель на следцщий элемент массива, а операция, p++, вернет указатель на текущий элемент, и изменит р, р теперь будет указывать на следующий элемент
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
04.04.2014, 10:03     Загадка указателей #12
aLarman, Вы видать не совсем внимательно прочитали его последний вопрос, так что понял он неправильно.
Цитата Сообщение от bigibug Посмотреть сообщение
указатель на 'p+1' значение которого впринципе фиг пойми какое
Запись cin>>*p++ эквивалентна следующему:
C++
1
2
cin>>*p;
p += 1;
Но в предыдущем тебе правильно ответили...
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
04.04.2014, 10:23     Загадка указателей #13
Цитата Сообщение от monolit Посмотреть сообщение
Вы видать не совсем внимательно прочитали его последний вопрос, так что понял он неправильно.
по-моему под
Цитата Сообщение от monolit Посмотреть сообщение
указатель на 'p+1' значение
он имел ввиду p+=1; но вообще говоря, кто знает как он понял...
bigibug
0 / 0 / 0
Регистрация: 03.04.2014
Сообщений: 3
04.04.2014, 10:35  [ТС]     Загадка указателей #14
Ясно, спасибо огромное за помощь =) Всем добра!
intern
 Аватар для intern
15 / 15 / 6
Регистрация: 30.03.2014
Сообщений: 67
Завершенные тесты: 1
04.04.2014, 16:28     Загадка указателей #15
В продолжение темы есть вопрос:
C++
1
2
int arr[] = {7, 8, 9};
cout << *++arr;
требует l-значение, а
C++
1
2
3
int arr[] = {7, 8, 9};
int *parr = arr;
cout << *++parr;
работает нормально
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
04.04.2014, 17:27     Загадка указателей #16
Ну да, а в чем собственно вопрос? Да и второе 'работает нормально' - это врядли. Если только не хотели вывести второй элемент массива.
recoder
 Аватар для recoder
129 / 129 / 28
Регистрация: 13.09.2013
Сообщений: 260
Записей в блоге: 2
04.04.2014, 17:34     Загадка указателей #17
Дьюхерст С.С. C++. Священные знания. Почитайте. Там кратко, но доступно объясняется арифметика указателей.
intern
 Аватар для intern
15 / 15 / 6
Регистрация: 30.03.2014
Сообщений: 67
Завершенные тесты: 1
04.04.2014, 17:34     Загадка указателей #18
Чтобы разобраться.
Ведь arr и parr - адреса 0-го элемента в arr[].
А вопрос - почему не работает 1-й вариант?
recoder
 Аватар для recoder
129 / 129 / 28
Регистрация: 13.09.2013
Сообщений: 260
Записей в блоге: 2
04.04.2014, 17:47     Загадка указателей #19
Можно так.
C++
1
std::cout << ++*arr;
А это
C++
1
cout << *++arr;
Undefined behavior. Вроде как.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.04.2014, 18:07     Загадка указателей
Еще ссылки по теме:

Создать специализацию для шаблона, которая принимает массив указателей на строки и количество этих указателей C++
Создать специфицированный шаблон функции, принимающей массив указателей на char и количество самих указателей C++
Загадка преобразования IntToHex C++

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

Или воспользуйтесь поиском по форуму:
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11800 / 6779 / 765
Регистрация: 27.09.2012
Сообщений: 16,829
Записей в блоге: 2
Завершенные тесты: 1
04.04.2014, 18:07     Загадка указателей #20
Цитата Сообщение от intern Посмотреть сообщение
А вопрос - почему не работает 1-й вариант?
потому что там arr - это имя массива, а не просто указатель.
Yandex
Объявления
04.04.2014, 18:07     Загадка указателей
Ответ Создать тему
Опции темы

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