Память malloc указателю на указатель

Я столкнулся с этой проблемой при использовании указателя на указатель на char:

void setmemory(char** p, int num) { *p=(char*)malloc(num); } void test(void) { char* str=NULL; setmemory(&str,100); strcpy(str,"hello"); printf(str); } int main() { test(); return 0; } 

Вышеприведенный код верен, но я не могу понять, почему здесь используется указатель на указатель char ** p? Почему просто использовать указатель на символ вместо этого? поэтому я изменяю этот fragment ниже и считаю, что он не работает, может ли кто-нибудь сказать мне, почему? Спасибо!

 void setmemory(char* p, int num) { p=(char*)malloc(num); } void test(void) { char* str=NULL; setmemory(str,100); strcpy(str,"hello"); printf(str); } int main() { test(); return 0; } 

Здесь следует отметить следующее: когда мы говорим указатели, мы обычно склонны думать в терминах pass by reference но не обязательно. Даже указатели могут passed by value

char* str является локальным для test а char* p является локальным для setmemory . Таким образом, изменения, которые вы делаете в setmemory , не будут отображаться в test если вы не отправляете указатель на указатель.

Вы можете заставить его работать с одним указателем, подобным этому

  char * setmemory(char* p, int num) // p is a new pointer but points at the same // location as str { p=(char*)malloc(num); // Now, 'p' starts pointing at a different location than 'str' strcpy(p ,"hello"); // Copy some data to the locn 'p' is pointing to return p; // Oops. The poor `str` is still pointing at NULL :( // Send him the address of the newly allocated area } void test(void) { char* str=NULL; str=setmemory(str,100); // We are passing a pointer which is pointing to NULL printf(str); //Now str points to the alloced memory and is happy :) } int main() { test(); return 0; } 

Обратите внимание, что в setmemory мы возвращаем локальный указатель, но это не проблема (без проблем с висячим указателем), поскольку этот указатель указывает на местоположение в куче, а не на стеке

Вы хотите изменить указатель, т. Е. Для функции нужна ссылка, а не значение. В C это делается путем указания адреса (указателя) на переменную, которая заключается в изменении самого указателя. Таким образом, один указатель предназначен для ссылок, другой для вас – порграммовая логика.

Здесь вы устанавливаете локальную переменную * p. Помните, что вы получаете указатель на данные, а не указатель на указатель на данные.

Подумайте об этом так:

Первый случай:

 int a; foo(a); // Passes a void foo(int b) { b = 4; // This only changes local variable, has no effect really } 

Второй случай:

 int a; foo(&a); // Passes *a void foo(int *b) { *b = 4; // This changes the contents of a. As you can see we have not changed the original pointer! b = 4; // This changes our local copy of the pointer, not the pointer itself, like in the first case! } 

Третий случай

 int *ptr; foo(&ptr); // Passes **ptr void foo(int **b) { **b = 4; // This changes the data of the passed pointer *b = 4; // This changes the passed pointer itself, ie it changes ptr. This is what test() is doing, the behavior you are looking for! b = 4; // This changes our local copy of a variable, just like the first case! } 

Код orignal передается в том месте, где вызывающий объект хочет поставить указатель на строку. Если вы передадите только символ «char *», вызывающий абонент будет передавать по значению содержимое местоположения вызывающих абонентов – возможно, какое-то неинициализированное значение.

Если вызываемый должен вернуть строку или другую косвенную структуру, вам нужны обе звездочки, чтобы вызываемый мог вернуть указатель в переменную указателя вызывающих.

Имеет ли это смысл? Это было со мной, но потом я написал это.