Как указано в большинстве ответов ранее, совершенно безопасно передавать указатель на func2()
в вашем специальном случае.
В реальном мире часть программного обеспечения, однако, я считаю это вредным, поскольку у вас нет контроля над тем, что делает func2()
с вашей переменной. func2()
может создать псевдоним своего параметра, чтобы использовать его асинхронно в более поздний момент времени. И в это время локальная переменная int i
может исчезнуть, когда этот псевдоним будет использоваться позже.
Так что с моей точки зрения передача указателя на локальную (автоматическую) переменную чрезвычайно опасна и ее следует избегать.
Вы можете сделать это, если вы объявляете переменную в func1()
, как static int i;
В этом случае обеспечивается, что память i
не будут переработаны и перезаписаны. Однако вам потребуется настроить блокировку Mutex для управления доступом к этой памяти в параллельной среде.
Чтобы проиллюстрировать эту проблему, вот какой-то код, который я только что споткнулся вчера во время тестирования программного обеспечения у моего клиента. И да, он выходит из строя ...
void func1()
{
// Data structure for NVMemory calls
valueObj_t NVMemObj;
// a data buffer for eeprom write
UINT8 DataBuff[25];
// [..]
/* Assign the data pointer to NV Memory object */
NVMemObj.record = &DataBuff[0];
// [..]
// Write parameter to EEPROM.
(void)SetObject_ASync(para1, para2, para3, &NVMemObj);
return;
}
void SetObject_ASync(para1, para2, para3, valueObj_t *MemoryRef)
{
//[..]
ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr = MemoryRef->record;
//[..]
return;
}
В этом случае, данные в DataBuff
давно нет, когда указатель в ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr
используется для хранения данных в EEPROM.
Чтобы исправить этот код, по крайней мере необходимо объявить static UINT8 DataBuff[25];
Кроме того, считается, что также объявлено static valueObj_t NVMemObj
, поскольку мы не знаем, что вызываемая функция выполняет с этим указателем.
Выражаясь кратко: TL; DR
Несмотря на то, что это законно в языке Си, я считаю это вредным передавать указатели на автоматические переменные в вызове функции. Вы никогда не знаете (и часто не хотите знать), что именно вызываемая функция выполняет с переданными значениями. Когда вызываемая функция устанавливает псевдоним, вы получаете большие неприятности.
Только мои 2 цента.
Использование указателя на переменную после уничтожения переменной небезопасно. Вы этого не делаете. – immibis
OT: Это должно быть 'void func1 (void)', если для функции не определены аргументы. – alk
Возможный дубликат [Безопасный переход указателя на автоматическую переменную для работы?] (Http://stackoverflow.com/questions/17798785/safe-to-pass-pointer-to-auto-variable-to-function) – ravron