Метценгерштейн 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Встретил в коде следующую конструкцию: 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; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Всё что со знаками вопроса - верно. Проще никак. Смысл указателя на указатель, что бы вернуть значение не копируя содержимое в буфер-аргумента. Последний кусок кода напрочь ошибочный. "pp_tk_value = &m_device_tk;" скопирует указатель в аргумент. Но при выходе из функции oob_key не поменяется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 33 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба есть передать сам указатель вы его изменить не сможете. у них если if (m_tag_match) то указатель меняется. Всё правильно сделано (согласно их логике). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Хорошо, а в моем приведенном примере- в чем ошибка? Не могу указателю сразу адрес присвоить разве? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 33 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Хорошо, а в моем приведенном примере- в чем ошибка? Не могу указателю сразу адрес присвоить разве? Присвоить можете, только указатель ble_advdata_tk_value_t* oob_key; не изменится. P.S. Может книжечку почитать ? "Стань профи С за 24 часа" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Не нашел в инете такой книжки. Не совсем понимаю, зачем мне менять указатель. Точнее, я же в их логике его и меняю через разыменование и записи по нему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба на что будет указывать oob_key после выполнения функции в первом случае, и во втором? ну или даже так: что произойдёт с переменной pp_tk_value после выхода из функции? Точнее, я же в их логике его и меняю через разыменование и записи по нему. pp_tk_value = &m_device_tk; где именно в данной строчке происходит разыменование указателя? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Разыменование происходит в оригинальном примере: *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 . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба В моем случае- на то же. Понимаю, что где-то не прав, но не доходит почему. pp_tk_value уйдет из области видимости и останется в записи oob_key. Все изменения будут внесены в oob_key . pp_tk_value это просто ещё один указатель, который указывает на то же на что и oob_key. точнее указывал, а потом стал указывать на &m_device_tk. в каком именно месте в вашем коде происходит запись в oob_key? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба в каком именно месте в вашем коде происходит запись в oob_key? *pp_tk_value = &m_device_tk; в этом месте, т.к. работаю с указателями по памяти, а не по значению. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Понимаю, что где-то не прав, но не доходит почему. Недостаток базовых знаний, вам совершенно не зря советуют книжки почитать. На уровне ассемблера при вызове функции все аргументы копируются в контекст функции. В самой функнции эти копии-аргументы можно менять как заблагорассудится, на источник своих значений они уже повлиять не могу. Поэтому и существуют указатели, что передать(скопировать) в функцию значение адреса объекта, который нужно изменить. Если бы вы программировали на с++, то вы могли бы(но делать так не стоит использовать ссылку для того что бы ваш пример заработал: ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t *& pp_tk_value) И тогда по ссылке изменения вернуться в oob_key. Но делать так, повторюсь, не надо. Нужно понять для чего нужны указатели и указатель на указатель. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Так я же не против почитать что-то) Читал много, но с этим вопросом не сталкивался. Если есть под рукой статья, где это все наглядно демонстрируется, то с удовольствием посмотрю. Ну а в чем я в предыдущем посте не прав? *pp_tk_value = &m_device_tk; в этом месте, т.к. работаю с указателями по памяти, а не по значению. Это тоже самое что вы и сказали: На уровне ассемблера при вызове функции все аргументы копируются в контекст функции. В самой функнции эти копии-аргументы можно менять как заблагорассудится, на источник своих значений они уже повлиять не могу. Поэтому и существуют указатели, что передать(скопировать) в функцию значение адреса объекта, который нужно изменить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Упрощенно: Переменная снаружи имеет какое-то значение Выполняется вызов В стеке аллокируется кадр под все аргументы В эти новые места копируется значения переменных (связь между аргументами в функции и теми переменными что были использованы для вызова снаружи оборвалась) В функции меняются аргументы как угодно, они находятся в том кадре что был сделан при вызове. Возврат из функции (кадр аргументов освобождается, значения которые там находились становятся мусором) *pp_tk_value = &m_device_tk; Если ble_advdata_tk_value_t * pp_tk_value , в этом коде вы просто испортили начало массива pp_tk_value каким-то левым для содержимого этого массива адресом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба Но делать так, повторюсь, не надо. Почему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 27 июля, 2018 Опубликовано 27 июля, 2018 · Жалоба 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; } } Это код из оригинального примера. Произошло разыменование указателя и записался адрес чего- то. Но, если бы на вход пришел адрес массива, то да. А посмотрите внимательно- пришел адрес адреса)) Упрощенно: Переменная снаружи имеет какое-то значение Выполняется вызов В стеке аллокируется кадр под все аргументы В эти новые места копируется значения переменных (связь между аргументами в функции и теми переменными что были использованы для вызова снаружи оборвалась) В функции меняются аргументы как угодно, они находятся в том кадре что был сделан при вызове. Возврат из функции (кадр аргументов освобождается, значения которые там находились становятся мусором) Полностью согласен. Эти вещи я знаю отлично. Это не тот вопрос, который мне не понятен. Для того и передают в ф-ю адрес переменной. Изменив ее там, она поменяется и там откуда ее переслали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться