Цитата(Метценгерштейн @ Jul 29 2018, 08:19)
а вот здесь зачем указатель на указатель?
Код
ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t ** pp_tk_value)
Разве не достаточно было так:
Код
ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t * pp_tk_value)
{
pp_tk_value = &m_device_tk;
}
Вам надо понять (один раз и на всю жизнь), для чего в качестве аргумента функции передавать указатель на указатель.
Поймёте это - поймёте и ваш код.
То, что вы знаете, и о чём пишется в любом учебнике по С
1.Передавая объекты в функцию по-значению, вы сможете использовать их (значения), но не сможете их изменить. Все изменения аргументов внутри функции изменят лишь копии объектов, переданных в функцию, но не сами объекты. Т.е. изменение копии никак не отражается на оригинале, с которого копия была снята.
2. Чтобы можно было изменять значения объекта изнутри функции, в функцию в качестве аргумента надо передать не сам объект, а указатель на него. В этом случае в функцию передастся копия указателя на объект. Но т.к. копия указателя на объект указывает на тот же самый объект, что и исходный указатель, то этом случае функция через косвенную адресацию будет иметь доступ к такому объекту. Ведь в качестве параметра ей придёт указатель (т.е. фактически адрес) объекта. Зная адрес объекта (т.е. имея копию указателя на него) всегда можно изменить и сам объект, разыменовав указатель и присвоив ему новое значение.
А теперь то, что из этого следует, но на чём не акцентируется внимание в учебниках или вообще не говорится.
3. А что делать, если вам надо внутри функции изменить значение объекта имеющего тип указателя? Т.е. надо внутри функции присвоить указателю адрес другого объекта. Как такое сделать? Если передать в функцию сам указатель, то можно будет изменять тот объект, на который он указывает, но не сам указатель. А нам то этого не надо. Нам надо, чтобы указатель после выхода из функции указывал на другой объект (содержал его адрес). Вот для этого и приходится передавать в качестве аргументов функциям указатель на указатель.
Очень простой пример для иллюстрации сказанного в п. 3
Код
// Произвольный тип данных пользователя (предположим, int)
typedef int usertype_t;
// Функция, изменяющая значение указателя на объект типа usertype_t
// PtrToPtrToObj -указатель на указатель на объект типа usertype_t
// PtrToNewObj - указатель на новый объект
void SetPtrToNewObj (usertype_t** PtrToPtrToObj, usertype_t* PtrToNewObj) {
*PtrToPtrToObj=PtrToNewObj;
}
int main (){
// Объекты типа usertype_t
usertype_t ObjA, ObjB;
// Указатель на объект типа usertype_t
usertype_t* ObjPtr=&ObjA; // Теперь ObjPtr указывает на объект ObjA
// Меняем значение указателя. Нам нужно, чтобы он теперь указывал на другой объект
// Эквивалент строки: ObjPtr=&ObjB;
SetPtrToNewObj (&ObjPtr,&ObjB); // Теперь ObjPtr указывает на объект ObjB
}
А теперь зная это посмотрим на код:
Код
ret_code_t nfc_tk_value_get(ble_advdata_tk_value_t * pp_tk_value)
{
pp_tk_value = &m_device_tk;
}
Что он делает?
pp_tk_value - это аргумент функции. Т.е. при вызове функции в него копируется значение типа ble_advdata_tk_value_t *. Т.е. это копия указателя на объект типа ble_advdata_tk_value_t. КОПИЯ указателя, а не сам указатель!
pp_tk_value = &m_device_tk; - что вы сделали этой строкой?
Вы присвоили КОПИИ УКАЗАТЕЛЯ новое значение. Но изменение КОПИИ никак не повлияло на оригинал. Оригинальный указатель остался прежним. А после выхода из функции pp_tk_value вышел из области видимости. Т.е. эта строка не изменила никаких объектов программы.
А должна была присвоить указателю новое значение - адрес объекта m_device_tk типа ble_advdata_tk_value_t.
Сообщение отредактировал Professor Chaos - Sep 1 2018, 15:08