Назначить адрес недействительному указателю, переданному по ссылке

#c #void-pointers

#c #указатели void

Вопрос:

Вызывающий в первый раз, долгое время слушающий. У меня есть вопрос о каком-то указателе void * и, похоже, я не могу найти объяснение, поэтому, возможно, кто-то здесь может пролить некоторый свет.

У меня есть функция-обработчик, где (среди прочего) Я объявляю указатель void и передаю его по ссылке в какую-либо другую функцию:

 void some_handler(some args)
{
    void * p_out_data;
    some_other_function(amp;p_out_data);
    // ... do some stuff with p_out_data after some_other_function stores an address
}
  

В some_other_function я выделяю некоторую память (сколько зависит от нескольких факторов), копирую в нее a_bunch_of_data и сохраняю его адрес в p_out_data, чтобы some_handler мог получить доступ к a_bunch_of_data:

 void some_other_function(void * pp_out_data)   // pp_out_data is the address of p_out_data
{    
    void * p = malloc(d_size); 
    memcpy(p, amp;a_bunch_of_data, d_size);
    memcpy(pp_out_data, amp;p, sizeof(p));
}
  

Все это работает хорошо. Мой вопрос: почему единственный способ сохранить адрес памяти, возвращаемый malloc(), в p_out_data — это использовать memcpy? Я попытался напрямую сохранить адрес в разыменованном указателе:

 *pp_out_data = malloc(d_size);
  

Но я получаю сообщение об ошибке о незаконном использовании указателя void. Я знаю, что существует множество правил для указателей void, поэтому я предполагаю, что здесь применяется конкретное?

Комментарии:

1. pp_out_data должен быть указателем на void* . Как вы пишете «указатель на void* «?

Ответ №1:

Вы передаете указатель на указатель, поэтому определите функцию как таковую:

 void some_other_function(void **pp_out_data)
{    
    void * p = malloc(d_size); 
    memcpy(p, amp;a_bunch_of_data, d_size);
    *pp_out_data = p;
}
  

Комментарии:

1. Я вижу, что вы там сделали, но два косвенных обращения, вероятно, не идеальны для простой передачи адреса памяти. Смотрите мои комментарии выше.

2. Верно, в этом простом случае было бы предпочтительнее просто вернуть void * . Вы всегда можете опубликовать это как другой ответ, но я считаю, что мой ответ все еще поучителен.

3. Да! Это то, что я искал. Спасибо!

4. Кроме того, возврат void * будет работать, но, я думаю, я слишком упростил проблему для публикации, поскольку я фактически возвращаю код состояния.

Ответ №2:

*pp_out_data это не ваша переменная указателя; это данные, на которые указывает ваша переменная указателя.

Другими словами, вы уже разыменовали его.

Если вы ожидаете, что новый адрес будет передан из вашей функции через ваш pp_out_data параметр, это не работает таким образом; адрес в pp_out_data передается по значению.

return вместо этого новый адрес из функции:

 void* some_other_function(void* pp_out_data)
{    
    void* p = malloc(d_size); 
    memcpy(p, amp;a_bunch_of_data, d_size);
    memcpy(pp_out_data, amp;p, sizeof(p));
    return p;
}