Каким будет указатель pNext в следующем случае с использованием C?

#c #pointers

Вопрос:

 func()
{
    Object* pNext;
    func1(pNext);
}

func1(Object* pNext)
{
    pNext = Segement->GetFirstPara(0);
}
 

Я ожидал, что это будет указатель на firstpara, возвращенный из func1 (), но я вижу, что NULL может что-то объяснить и как это исправить, чтобы на самом деле вернуть указатель firstpara ()?

Ответ №1:

Только для C вы можете сделать параметр ссылкой

 func()
{
    Object* pNext;
    func1(pNext);
}

func1(Object*amp; pNext)
{
    pNext = Segement->GetFirstPara(0);
}
 

Здесь происходит разница между передачей параметров по значению и передачей по ссылке. C всегда проходит по значению. Чтобы вернуть значение, значение должно быть ссылочным значением (например, Объект** ссылается на объект* как указатель). C добавляет ссылочные параметры (обозначаемые символом amp;).
Передача по значению передает только копию данных, но никогда сами фактические данные. Вот почему переменная, используемая в вызове функции, не была обновлена в функции.

Ответ №2:

В c вы хотели бы:

 func1(amp;pNext);
func1(Object** pNext) { *pNext = ... }
 

В C

 func1(pNext);
func1(Object*amp; pNext) { pNext = ... }
 

В любом языке ваш пример передаст неинициализированное Object* значение func1 , которое скопирует его , присвоит значение копии и затем вернет. Обратите внимание, что исходный pNext никогда не изменяется (это помогло бы, если бы вы использовали разные имена для своих переменных).

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

Ответ №3:

Чтобы изменить указатель, вам нужно передать указатель на указатель, Object** pNext т. е. Чтобы изменить значение переменной внутри функции, вы передаете указатель. Следовательно, по расширению, чтобы изменить значение указателя внутри функции, передайте указатель на указатель.

 func() { 
    Object* pNext;
    func1(amp;pNext);
}

func1(Object** pNext) { *pNext = Segement->GetFirstPara(0); }
 

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

1. Не совсем. amp; является оператором адреса.

2. Да, Джон исправил amp;pNext в func1. Я направил их не в ту сторону. Прошло слишком много времени с тех пор, как я использовал С.

Ответ №4:

Пожалуйста, инициализируйте pNext при его создании. Сейчас, когда вы отлаживаете, он может быть равен нулю, но в поле он будет 0x12AbD468 или что-то в этом роде. Если у вас есть такой тест, как:

 if( NULL != pNext )
{
  pNext->DoSomething();
}
 

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

В вашем случае, поскольку ‘func1()’ не использует pNext в качестве параметра, вы можете просто вернуть его из функции:

 func()
{
  Object *pNext = func1();
}

Object* func1()
{
  return Segment->GetFirstPara(0);
}
 

Ответ №5:

Это должно быть

 
func()
{
  Object *pNext;
  func1(amp;pNext);
}

void func1(Object **pNext)
{
  *pNext = Segment->GetFirstPara(0);
}