Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
bigibug
0 / 0 / 0
Регистрация: 03.04.2014
Сообщений: 3
1

Загадка указателей

03.04.2014, 23:06. Просмотров 746. Ответов 20
Метки нет (Все метки)

Здравствуйте =) Привел меня к Вам следующий вопрос.
Поступило задание составить программу для решения квадратного уровнения, используя указатели.
В процессе работы наткнулся на то что, казалось бы, одно и тоже (по смыслу) выдает разные результаты.
Преподаватель работу принял, но разницу не смог обьяснить. А я теперь ночами спать не могу, понять хочу что не так сделал. =) Единственная разница выделена жирным шрифтом.
Подскажите, пожалуйста, почему 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
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.04.2014, 23:06
Ответы с готовыми решениями:

Почему в сортировке указателей на объекты в вызове функции используются адреса объектов, а не указателей?
Доброго времени суток! Рассматриваю пример (из Лафоре) сортировки массива...

Создать специфицированный шаблон функции, принимающей массив указателей на char и количество самих указателей
Задача: создать специфицированный шаблон функции, принимающей массив указателей...

Объяснить различия в работе указателей на целое число и указателей на const char (строки в стиле Си)
Уважаемые программисты, возникло несколько вопросов касательно указателей. ...

Создать специализацию для шаблона, которая принимает массив указателей на строки и количество этих указателей
Нужно создать специализацию для шаблона, которая принимает массив указателей на...

Различия указателей char* от указателей других типов
Помогите пожалуйста разобраться! Прочитал раздел про указатели и даже вроде...

20
monolit
188 / 187 / 46
Регистрация: 24.03.2011
Сообщений: 670
Завершенные тесты: 1
03.04.2014, 23:26 2
Все потому, что во втором случае ты указатель на массив просто-напросто теряешь (p - изменяется!!!). Т.е. p теперь указывает не на то, что должен (начало массива из интов) - на место за массивом, а там мусор, вообще говоря. Ну по результатам видно и так)

C++
1
2
3
int *cur = p;
------
cin>>*cur++;
Так получишь то, что тебе нужно.
0
Dani
1393 / 637 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:27 3
cin>>*p++;
Здесь сначала выполнится постфиксный инкремент, указатель изменит свое значение, а затем этот увеличенный указатель будет разыменован.
0
monolit
188 / 187 / 46
Регистрация: 24.03.2011
Сообщений: 670
Завершенные тесты: 1
03.04.2014, 23:28 4
Цитата Сообщение от Dani Посмотреть сообщение
Здесь сначала выполнится постфиксный инкремент, указатель изменит свое значение, а затем этот увеличенный указатель будет разыменован.
Не в том дело... тем более это неверно.
1
Croessmah
++Ͻ
14622 / 8373 / 1579
Регистрация: 27.09.2012
Сообщений: 20,571
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:31 5
Изменяете сам указатель, поэтому потом он "указывает" черт знает куда.

Добавлено через 1 минуту
Цитата Сообщение от monolit Посмотреть сообщение
Не в том дело...
как раз в этом! В куске кода
C++
1
cin>>*(p+j)
указатель p не изменяется, а в
C++
1
cin>>*p++;
изменяется и сам указатель
0
Dani
1393 / 637 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:33 6
Цитата Сообщение от monolit Посмотреть сообщение
Не в том дело... тем более это неверно.
Это почему еще?
0
Croessmah
++Ͻ
14622 / 8373 / 1579
Регистрация: 27.09.2012
Сообщений: 20,571
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:42 7
Цитата Сообщение от Dani Посмотреть сообщение
Это почему еще?
думаю, было пропущено несколько слов из предложения
Цитата Сообщение от Dani Посмотреть сообщение
Здесь сначала выполнится постфиксный инкремент, указатель изменит свое значение, а затем этот увеличенный указатель будет разыменован.
0
Dani
1393 / 637 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
03.04.2014, 23:42 8
Цитата Сообщение от monolit Посмотреть сообщение
тем более это неверно
Понял, не так написал: указатель увеличится, но разыменуется еще старый указатель, т.к. инкремент постфиксный.
0
monolit
188 / 187 / 46
Регистрация: 24.03.2011
Сообщений: 670
Завершенные тесты: 1
03.04.2014, 23:43 9
как раз в этом! В куске кода
Я понимаю) Но тогда вторая часть фразы
а затем этот увеличенный указатель будет разыменован
здесь не нужна, ибо она ситуацию не проясняет - а только уводит внимание (с разыменованием у него все нормально, и заполнением массива тоже - вы это и так знаете) Вот на это я и указал. Тем более с порядком операций он все-таки ошибся)
Да и вообще, не о чем тут говорить - на пустом месте такая дискуссия развернулась.

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

Цитата Сообщение от Croessmah Посмотреть сообщение
изменяется и сам указатель
Это в самом первом посте я и написал)
0
bigibug
0 / 0 / 0
Регистрация: 03.04.2014
Сообщений: 3
04.04.2014, 09:44  [ТС] 10
Ага, значит вводя *p++ я получаю не выражение *(p+1), указывающее на адрес следующего элемента массива p[], а, грубо говоря, указатель на 'p+1' значение которого впринципе фиг пойми какое. Я правильно понял?
0
aLarman
644 / 565 / 164
Регистрация: 13.12.2012
Сообщений: 2,112
Завершенные тесты: 1
04.04.2014, 09:48 11
Цитата Сообщение от bigibug Посмотреть сообщение
значение которой впринципе фиг пойми какое
ну не фиг пойми, а p + sizeof(тип на который указывает указатель)
Цитата Сообщение от bigibug Посмотреть сообщение
Я правильно понял?
да операция p+1, вернет указатель на следцщий элемент массива, а операция, p++, вернет указатель на текущий элемент, и изменит р, р теперь будет указывать на следующий элемент
0
monolit
188 / 187 / 46
Регистрация: 24.03.2011
Сообщений: 670
Завершенные тесты: 1
04.04.2014, 10:03 12
aLarman, Вы видать не совсем внимательно прочитали его последний вопрос, так что понял он неправильно.
Цитата Сообщение от bigibug Посмотреть сообщение
указатель на 'p+1' значение которого впринципе фиг пойми какое
Запись cin>>*p++ эквивалентна следующему:
C++
1
2
cin>>*p;
p += 1;
Но в предыдущем тебе правильно ответили...
0
aLarman
644 / 565 / 164
Регистрация: 13.12.2012
Сообщений: 2,112
Завершенные тесты: 1
04.04.2014, 10:23 13
Цитата Сообщение от monolit Посмотреть сообщение
Вы видать не совсем внимательно прочитали его последний вопрос, так что понял он неправильно.
по-моему под
Цитата Сообщение от monolit Посмотреть сообщение
указатель на 'p+1' значение
он имел ввиду p+=1; но вообще говоря, кто знает как он понял...
0
bigibug
0 / 0 / 0
Регистрация: 03.04.2014
Сообщений: 3
04.04.2014, 10:35  [ТС] 14
Ясно, спасибо огромное за помощь =) Всем добра!
0
intern
15 / 15 / 8
Регистрация: 30.03.2014
Сообщений: 74
Завершенные тесты: 2
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;
работает нормально
0
monolit
188 / 187 / 46
Регистрация: 24.03.2011
Сообщений: 670
Завершенные тесты: 1
04.04.2014, 17:27 16
Ну да, а в чем собственно вопрос? Да и второе 'работает нормально' - это врядли. Если только не хотели вывести второй элемент массива.
0
recoder
131 / 131 / 53
Регистрация: 13.09.2013
Сообщений: 260
Записей в блоге: 2
04.04.2014, 17:34 17
Дьюхерст С.С. C++. Священные знания. Почитайте. Там кратко, но доступно объясняется арифметика указателей.
0
intern
15 / 15 / 8
Регистрация: 30.03.2014
Сообщений: 74
Завершенные тесты: 2
04.04.2014, 17:34 18
Чтобы разобраться.
Ведь arr и parr - адреса 0-го элемента в arr[].
А вопрос - почему не работает 1-й вариант?
0
recoder
131 / 131 / 53
Регистрация: 13.09.2013
Сообщений: 260
Записей в блоге: 2
04.04.2014, 17:47 19
Можно так.
C++
1
std::cout << ++*arr;
А это
C++
1
cout << *++arr;
Undefined behavior. Вроде как.
0
Croessmah
++Ͻ
14622 / 8373 / 1579
Регистрация: 27.09.2012
Сообщений: 20,571
Записей в блоге: 2
Завершенные тесты: 1
04.04.2014, 18:07 20
Цитата Сообщение от intern Посмотреть сообщение
А вопрос - почему не работает 1-й вариант?
потому что там arr - это имя массива, а не просто указатель.
1
04.04.2014, 18:07
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.04.2014, 18:07

Как обойтись без указателей и указателей на указатель?
Ибо не совсем выходит понять,что на что тут указывает #include &quot;stdafx.h&quot;...

Создание массивов указателей на массивы указателей
Помогите в решении задачи: создал массив указателей на массивы указателей на...

Добавление нового указателя в конец массива указателей, удаление указанного элемента, добавление указателей
Здравствуйте. Помогите, пожалуйста, разобраться с одним большим заданием....


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

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

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