#include<iostream.h>
#include<conio.h>
int *p;
void Set()
{
int i;
i=7;
p=&i;
}
int Use()
{
double d;
d=3.0;
d+=*p;
//if i replace the above 3 statements with --> double d=3.0+*p; then output is 10 otherwise the output is some random value(address of random memory location)
//why is this happening? Isn't it the same?
return d;
}
void main()
{
clrscr();
Set();
cout<<Use();
getch();
}
Мой вопрос, как упоминалось в комментариях выше. Я хочу знать точную причину разницы в выводах. В приведенном выше выходном коде есть какой-то адрес случайной ячейки памяти, и я понимаю, что из-за я является локальной переменной Set() но тогда как это видно во втором случае, заменив его двойным d = 3. 0+ * p; потому что тогда выход приходит 10 (7 + 3), хотя 7 не должно было быть видимым?
Результат использования указателя p
не определен, он также может дать вам segfault или просто вернуть 42. Техническая причина результатов, которые вы получаете, вероятно:
i
внутри Set
помещается в стек. Значение 7 хранится там, и p
указывает на это место в памяти. Когда вы вернетесь из значения Set
остается в памяти: стек не "уничтожен", это просто указатель стека, который сбрасывается. p
все еще указывает на это местоположение, которое по-прежнему содержит целочисленное представление "3".
Внутри Use
то же место в стеке, которое используется повторно для d
.
Когда компилятор не оптимизирует, в первом случае (т.е. Все вычисления в одной строке) он сначала использует значение 7 (которое все еще присутствует в памяти с p
указывающим на него), выполняет ли вычисление, перезаписывает значение (поскольку вы назначаете его d
который находится в том же месте) и возвращает его.
Во втором случае он сначала перезаписывает значение с двойным значением 3.0, а затем берет первые 4 байта, которые интерпретируются как целочисленные значения для оценки *p
в d+=*p
.
Этот случай показывает, почему возвращение указателей/ссылок на локальные переменные является такой плохой: при написании функции Set
вы даже можете написать какие-то модульные тесты, и они не обнаружат ошибку. Это может остаться незамеченным только до тех пор, пока программное обеспечение не вступит в производство и не выполнит какую-то действительно критическую задачу и просто не сработает.
Это относится ко всем типам "неопределенного поведения", особенно на языках "низкого уровня", таких как C/C++. Плохо то, что "undefined" может очень хорошо означать "отлично работать, пока он не станет слишком поздно"...
После выхода из функции Установить значение указателя p становится недействительным из-за уничтожения локальной переменной i. Программа имеет неопределенное поведение.
TAB
на клавиатуре?