У меня есть отказ сегментации в коде ниже, но после того, как я изменил его на указатель на указатель, он прекрасен. Кто-либо мог привести мне какую-либо причину?
void memory(int * p, int size) {
try {
p = (int *) malloc(size*sizeof(int));
} catch( exception& e) {
cout<<e.what()<<endl;
}
}
это не работает в основной функции ударом
int *p = 0;
memory(p, 10);
for(int i = 0 ; i < 10; i++)
p[i] = i;
однако, это работает как это.
void memory(int ** p, int size) { `//pointer to pointer`
try{
*p = (int *) malloc(size*sizeof(int));
} catch( exception& e) {
cout<<e.what()<<endl;
}
}
int main()
{
int *p = 0;
memory(&p, 10); //get the address of the pointer
for(int i = 0 ; i < 10; i++)
p[i] = i;
for(int i = 0 ; i < 10; i++)
cout<<*(p+i)<<" ";
return 0;
}
Потому что вы хотите получить значение указателя обратно из операций, выполняемых в функции. malloc
выделяет память и дает вам адрес этой памяти.
В вашем первом примере вы сохраняете этот адрес в локальной переменной аргумента p
, но поскольку это всего лишь аргумент, он не возвращается в основную программу, потому что C / C ++ являются передача по значению по умолчанию - даже для указателей.
Main Function malloc
p p allocated
+---+ +---+
| 0 | | 0 | A
+---+ +---+
becomes...
p p allocated
+---+ +---+
| 0 | | ------------> A
+---+ +---+
и, таким образом, когда main читает p, он получает 0, а не A.
В вашем рабочем коде вы следуете за указателем, переданным на адрес, и этот адрес дает вам местоположение переменной указателя в основной программе. Вы обновляете значение указателя по этому адресу, и основная программа затем может найти значение для использования в качестве своего местоположения в памяти - таким образом, передавая адрес, возвращенный malloc
, обратно в основную программу для использования.
Main Function malloc
p p allocated
+---+ +---+
| 0 |<------- | A
| | | |
+---+ +---+
becomes...
p p allocated
+---+ +---+
| |<------- |
| ----------------------> A
+---+ +---+
и, таким образом, когда main считывает p, он получает A.
При первом обращении к памяти:
void memory(int * p, int size)
Осознайте, что вы передаете ЗНАЧЕНИЕ в memory (), а не адрес. Следовательно, вы передаете значение «0» в memory (). Переменная p
- это просто копия того, что вы передаете ... in содержит то же значение, но НЕ указывает на тот же адрес ...
Во второй функции , вы передаете ADDRESS вашего аргумента ... поэтому вместо этого p
указывает на адрес вашей переменной, а не просто является копией вашей переменной.
Итак, когда вы вызываете malloc следующим образом:
*p = (int *) malloc(size*sizeof(int));
Вы назначаете возврат malloc значению переменной, на которую указывает p
.
Таким образом, ваш указатель действителен за пределами memory ().
Я исправил код .. прочтите комментарий, и все будет ясно ..
#include<iostream>
#include<conio.h>
#include<exception>
using namespace std;
void memory(int* p, int size) { //pointer to pointer` not needed
try{
p = new int[size] ;
} catch(bad_alloc &e) {
cout<<e.what()<<endl;
}
}
int main()
{
// int *p = 0; wrong .. no memory assigned and then u are passing it to a function
int *p;
p = new int ; // p = malloc( sizeof(int));
/*before using a pointer always allocate it memory else
you ll get frequent system crashes and BSODs*/
memory(p, 10); //get the address of the pointer
for(int i = 0 ; i < 10; i++)
p[i] = i;
for(int i = 0 ; i < 10; i++)
cout<<*(p+i)<<" ";
getch();
return 0;
}
вам не нужно использовать указатель на указатель, а использовать указатель, на который имеется ссылка, т.е. *, а не просто *
Первый пример не работает, потому что параметр указателя не является указателем в main, он просто содержит то же значение.
В Си у вас есть только передача по значению. Поэтому ваша функция memory() получает свою собственную локальную копию p. malloc внутри memory() присваивает только той копии p, которая является локальной для функции. Когда memory() возвращается в main(), копия p из main остается неизменной. В C++ для решения этой проблемы используется передача по ссылке, например, так:
void memory(int*& p, int size)
В C для достижения аналогичных результатов используются двойные указатели.
Указатель хранит адрес, по которому хранятся данные. Передача указателя на функцию означает присвоение ей адреса данных . Однако здесь у вас нет адреса для данных до вызова malloc
. Поэтому вместо этого вам нужно передать адрес указателю (т.е. указатель на указатель). Это позволяет памяти
принимать адрес указателя p
и устанавливать p
для указания области памяти, которая выделяется для данных.
Вам нужен указатель на указатель, потому что вам нужно вернуть значение вновь выделенного указателя.
Есть три способа вернуть это значение (2, если вы используете C):
Третий способ определенно мне больше нравится.
(и нет, я не допускаю, что вы тоже могли бы использовать глобал, это не четвертый способ, а ужас).
память (стр, 10); // получаем адрес указателя
, это просто отправляет значение p, а не адрес p. он отправляет (* p). если добавлены p 123 и его значение 50, он отправляет 50 функции.
и в функции памяти он создает новый указатель с новым адресом, например 124, и он содержит 50; и он выделит память и запишет начало выделенной памяти в 124, а не в 123, поэтому p в главном по-прежнему содержит 50. Итак, вы ничего не сделали !. Вы можете контролировать это с помощью этого кода.
#include<iostream>
#include<conio.h>
#include<exception>
using namespace std;
void memory(int* p, int size) { //*************pointer to pointer` is a must**********
try{
p = new int[size] ;
p[0]=100;
} catch(bad_alloc &e) {
cout<<e.what()<<endl;
}
}
int main()
{
int *p = 0; ******you can do you should do this*******
p = new int ;
/* p = malloc( sizeof(int)); // this just change the value inside of p it is unnecessary
and you will lose a adress from memory :) and possibly it will be unsafe if you free p may, you just
free one adress*/
/*before using a pointer always allocate it memory else
you ll get frequent system crashes and BSODs*/
memory(p, 10); //get the address of the pointer//you are getting nothing
cout <<p[0];
//we set p[0] to 100 but it will write a garbage value here.
//because the value inside of p didn't change at the memory function
//we sent just the value inside of p.
getch();
return 0;
}