Перейти к содержанию
    

указатель на указатель

Встретил в коде следующую конструкцию:

 

ble_advdata_tk_value_t* oob_key;
err_code = nfc_tk_value_get(&oob_key);

 

где:

 

typedef struct
{
  uint8_t tk[BLE_GAP_SEC_KEY_LEN];      /**< Array containing TK value in little-endian format. */
} ble_advdata_tk_value_t;

 

ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t ** pp_tk_value)
{
    if (m_tag_match)
    {
        *pp_tk_value = &m_device_tk;
        return NRF_SUCCESS;
    }
    else
    {
        return NRF_ERROR_NOT_FOUND;
    }
}

 

Есть вопрос. Как все проговорить что тут происходит?

Есть тип структуры ble_advdata_tk_value_t. Создали переменную- указатель на этот тип: oob_key.

Дальше? Передаем не просто адрес (сам указатель oob_key), а именно адрес этого указателя? А в ф-ии уже принимаем указатель на указатель?

Разыменовывали на один уровень вверх и по тому значению присвоили адрес уже массива.

 

А проще никак?

err_code = nfc_tk_value_get(oob_key);

 

и приняли:

ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t * pp_tk_value)
{
    if (m_tag_match)
    {
        pp_tk_value = &m_device_tk;
        return NRF_SUCCESS;
    }
    else
    {
        return NRF_ERROR_NOT_FOUND;
    }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё что со знаками вопроса - верно. Проще никак. Смысл указателя на указатель, что бы вернуть значение не копируя содержимое в буфер-аргумента.

Последний кусок кода напрочь ошибочный. "pp_tk_value = &m_device_tk;" скопирует указатель в аргумент. Но при выходе из функции oob_key не поменяется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

у них если if (m_tag_match) то указатель меняется.

Всё правильно сделано (согласно их логике).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хорошо, а в моем приведенном примере- в чем ошибка? Не могу указателю сразу адрес присвоить разве?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хорошо, а в моем приведенном примере- в чем ошибка? Не могу указателю сразу адрес присвоить разве?

Присвоить можете, только указатель

 

ble_advdata_tk_value_t* oob_key;

 

не изменится.

 

P.S. Может книжечку почитать ?

"Стань профи С за 24 часа"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не нашел в инете такой книжки.

 

Не совсем понимаю, зачем мне менять указатель. Точнее, я же в их логике его и меняю через разыменование и записи по нему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

на что будет указывать oob_key после выполнения функции в первом случае, и во втором?

ну или даже так: что произойдёт с переменной pp_tk_value после выхода из функции?

 

Точнее, я же в их логике его и меняю через разыменование и записи по нему.

pp_tk_value = &m_device_tk;

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разыменование происходит в оригинальном примере:

*pp_tk_value = &m_device_tk;

 

В моем случае, и в приведенном вами примере, конечно, разыменования не происходит. Просто идет присвоение адреса переменной типа указатель:

pp_tk_value = &m_device_tk;

 

Попробую ответить на первый вопрос.

После выполнения ф-ии oob_key будет указывать в первом случае на

&m_device_tk

т.к. происходит разыменование и присвоение адреса:

*pp_tk_value = &m_device_tk;

 

В моем случае- на то же. Понимаю, что где-то не прав, но не доходит почему.

 

pp_tk_value уйдет из области видимости и останется в записи oob_key. Все изменения будут внесены в oob_key .

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В моем случае- на то же. Понимаю, что где-то не прав, но не доходит почему.

pp_tk_value уйдет из области видимости и останется в записи oob_key. Все изменения будут внесены в oob_key .

pp_tk_value это просто ещё один указатель, который указывает на то же на что и oob_key.

точнее указывал, а потом стал указывать на &m_device_tk.

 

в каком именно месте в вашем коде происходит запись в oob_key?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в каком именно месте в вашем коде происходит запись в oob_key?

 

*pp_tk_value = &m_device_tk;

в этом месте, т.к. работаю с указателями по памяти, а не по значению.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Понимаю, что где-то не прав, но не доходит почему.

Недостаток базовых знаний, вам совершенно не зря советуют книжки почитать. На уровне ассемблера при вызове функции все аргументы копируются в контекст функции. В самой функнции эти копии-аргументы можно менять как заблагорассудится, на источник своих значений они уже повлиять не могу. Поэтому и существуют указатели, что передать(скопировать) в функцию значение адреса объекта, который нужно изменить. Если бы вы программировали на с++, то вы могли бы(но делать так не стоит использовать ссылку для того что бы ваш пример заработал:

ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t *& pp_tk_value)

И тогда по ссылке изменения вернуться в oob_key. Но делать так, повторюсь, не надо. Нужно понять для чего нужны указатели и указатель на указатель.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так я же не против почитать что-то) Читал много, но с этим вопросом не сталкивался. Если есть под рукой статья, где это все наглядно демонстрируется, то с удовольствием посмотрю.

Ну а в чем я в предыдущем посте не прав?

 

*pp_tk_value = &m_device_tk;

в этом месте, т.к. работаю с указателями по памяти, а не по значению.

 

Это тоже самое что вы и сказали:

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Упрощенно:

Переменная снаружи имеет какое-то значение

Выполняется вызов

В стеке аллокируется кадр под все аргументы

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

В функции меняются аргументы как угодно, они находятся в том кадре что был сделан при вызове.

Возврат из функции (кадр аргументов освобождается, значения которые там находились становятся мусором)

 

*pp_tk_value = &m_device_tk;

Если ble_advdata_tk_value_t * pp_tk_value , в этом коде вы просто испортили начало массива pp_tk_value каким-то левым для содержимого этого массива адресом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t ** pp_tk_value)
{
    if (m_tag_match)
    {
        *pp_tk_value = &m_device_tk;
        return NRF_SUCCESS;
    }
    else
    {
        return NRF_ERROR_NOT_FOUND;
    }
}

Это код из оригинального примера.

Произошло разыменование указателя и записался адрес чего- то. Но, если бы на вход пришел адрес массива, то да. А посмотрите внимательно- пришел адрес адреса))

 

Упрощенно:

Переменная снаружи имеет какое-то значение

Выполняется вызов

В стеке аллокируется кадр под все аргументы

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

В функции меняются аргументы как угодно, они находятся в том кадре что был сделан при вызове.

Возврат из функции (кадр аргументов освобождается, значения которые там находились становятся мусором)

 

Полностью согласен. Эти вещи я знаю отлично. Это не тот вопрос, который мне не понятен. Для того и передают в ф-ю адрес переменной. Изменив ее там, она поменяется и там откуда ее переслали.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...