Вопрос по pointers, string, c – память malloc на указатель на указатель

1

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

<code>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;
}
</code>

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

<code>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;
}
</code>
@ cnicutar, хороший пример здесь, спасибо! world peace
p является локальной переменной.*p не является. Kerrek SB

Ваш Ответ

4   ответа
0

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

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

Имеет ли это смысл? Это сделал для меня, но опять же, я написал это.

спасибо за потраченное время и код здесь & # xFF01; я очень признателен ^ _ ^ world peace
0

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

Понял, спасибо! ^ _ ^ world peace
0

что вы получаете указатель на данные, а не указатель на указатель на данные.

Думайте об этом так:

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

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, i.e. 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!
}
3

One thing to note here is - When we say pointers, we generally tend to think in terms of pass by reference but not necessarily. Even pointers can be 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 мы возвращаем локальный указатель, но это не проблема (нет проблем с висящими указателями), так как этот указатель указывает на местоположение в куче, а не в стеке

Понятно. Спасибо большое. Pavan. Это очень интересное и подробное объяснение. world peace
@PeteHerbertPenito Да. Хорошей практикой программирования является освобождение всей памяти с ошибками. Но этот пример имел дело с какой-то другой концепцией, а код только для иллюстрации. Отсюда нет внимания к свободе.
Извините, еще один быстрый вопрос новичка, почему он "бесплатный"? не нужно здесь? Я думал, что free всегда нужен, если используется malloc?
@worldpeace Не забудьте принятьone из ответов, которые помогли вам, отметив галочку рядом с каждым ответом

Похожие вопросы