Ах, эти указатели

Pinokio

Начал изучать С++ и тут наткнулся на недопонимание.Операция new резервирует место в куче, необходимое для хранения значения этого типа. т.е. правильно делать так.
float* pf;
pf  = new float(0);
//дальше что-то делаем с переменной.
*pf = 3.14;  
cout << *pf << endl;
Тогда я не понимаю, как без new получается выполнение этого
float* pf;
*pf = 3.14;
cout << *pf << endl;
Объясните пожалуйста, как без выделения места в куче я могу оперировать указателем, записывая в него?????
13 ответов

Pinokio

Тогда я не понимаю, как без new получается выполнение этого
Рано или поздно это приведет к падению программы, вот и вся наука


Pinokio

Да, весь Керниган и Ричи испичкан вторым вариантом, а new применяется только для массивов. как мы вообще можем записать в *pf, если мы память в куче не резервировали????


Pinokio

Тогда я не понимаю, как без new получается выполнение этого
В какой среде, именно выполнение (не компиляция)?


Pinokio

если мы память в куче не резервировали????
пишем в никуда


Pinokio

Вы имеете в виду на чем запускаю на выполнение? если да, то на виндовс, но как это относится к делу?! этот вариант работает и на винде и на линуксе (gcc). Просто объясните почему без выделения памяти я работать могу с отдельной переменной как будто память я уже выделил.Пишем в никуда???? это как?


Pinokio

этот вариант работает и на винде и на линуксе (gcc)
В том-то и дело, что у меня не работает...


Pinokio

это как?
в pf содержится какой-то мусор, который интерпретируется как адрес. И по этому адресу производится запись. Это прямая дорога к падению.


Pinokio

Если в debug собирать, то не работает.


Pinokio

Вот такой вариант еще может отработать корректно, но это дело случая:
#include <iostream>
using namespace std;
int foo1(){
    float* pf;
    pf  = new float(0);
    //дальше что-то делаем с переменной.
    *pf = 3.14;  
    cout << *pf << endl;
    return 0;
}
 
int foo2(){
    float* pf;
    *pf = 3.14;
    cout << *pf << endl;
    return 0;
}
int main(){
    foo1();
    foo2();
}


Pinokio

Да, вы правы. студия не пропустила, я использовал g++ (mingw) он пропустил это.
    int A[] = {1,2,3,4,5,6,7,8,9}, B[9];
    int i;
    int *a, *b; //дальше пойдет начальная инициализация.
    for(a=A, b=B, i = 0; i<9;i++)
            *(b++) = *(a++);
хорошо, но студия пропустила такой код, как мы можем записать в переменную адрес, если под нее ничего не выделено? (P.s. кажется я буксую на месте и не пойму очевидного)


Pinokio

int A[] = {1,2,3,4,5,6,7,8,9}, B[9];//Массивы A и B
int i;
int *a, *b; //Память под сами указатели уже есть
for(a=A, b=B, i = 0; i<9;i++)//a "указывает" на массив A, b - на B
*(b++) = *(a++);//Запись идет уже в массивы


Pinokio

K&R содержит ряд примеров, С подмножество С++, значит все примеры должны выполнится на С++. или я ошибаюсь?


Pinokio

как мы можем записать в переменную адрес, если под нее ничего не выделено
переменная - в данном случае, это указатель. У него есть значение (адрес), оно может быть инициализировано (выделена память через new, присвоен адрес другой переменной, присвоено значение другого указателя) или не инициализировано. И вот если оно не инициализировано, то операции разыменования (*) приводят к тому, что Вы оперируете с данными, которые лежат по совершенно левому адресу. Там может быть "мусор", может быть что-то что Вы использовали недавно, может вообще ошибка доступа появиться при обращении к этому адресу, и много чего его интересного. Но до добра это не доводит никогда.