Проверяем в Atollic True Studio , gcc для STM32F205 :
Возврат данных из функции
Сразу для понимания пример :
uint8_t myFunction(....)
{
......
return 123;
}
main()
{
uint8_t ret = myFunction(...);
// равносильно в буквальном смысле
uint8_t ret = 123;
То есть тот тип данных , что возвращается из функции создается в основной программе просто как переменная.
Поэтому возвращая из функции массивы и другие объемные данные надо понимать , что вы расходуете память.
Возврат указателя из функции через return
uint8_t str[]="1234567";
// --> func str=0x2000016c '1234567' работает
static uint8_t str[]="1234567";
// --> func str=0x2000016c '1234567' работает
uint8_t * func(uint16_t ii)
{
uint8_t str[]="1234567";
// --> func str=0x20001238 '1234567' НЕ РАБОТАЕТ
static uint8_t str[]="1234567";
// --> func str=0x2000016c '1234567' работает
uint8_t *str="1234567";
// --> func str=0x8010280 '1234567' работает
printf("func str=%p '%s'\n",str,str);
return str;
}
void main()
{
uint8_t * pStr= func(456);
printf("pStr='%s'\n",pStr);
...
HardFault ! для uint8_t str[]="1234567" (внутри функции);
uint8_t str[] (внутри функции) - размещение в стеке
uint8_t *str размещение во флеше (это где константные данные и код хранится)
static uint8_t str[](вне / в функции) , uint8_t str[] (вне функции) - в статической памяти SRAM , она же куча, (эта та , которая очищается после выключения)
Выводы
Возврат указателя из функции возможен , но главный вопрос : указатель на кого ? . То есть где находится указуемый ? : если в стеке то нельзя, если в куче и флэше , то можно.
Возврат указателя из функции через параметр передаваемый в функцию
Это возможно только если передавать двойной указатель ** !
uint8_t str[]="1234567"; // 20000000 - это куча
uint8_t* str="1234567"; // 0x8001cec - это flash .rodata
void func( uint8_t **pp)
{
printf("func pp=%p 0x%x *pp=%x\n" , pp , pp, *pp); // func pp=0x2001ffec 0x2001ffec *pp=f
*pp=str; // так можно оказывается
printf("func pp=%p 0x%x *pp=%x\n" , pp , pp, *pp); // func pp=0x2001ffec 0x2001ffec *pp=20000000
// сам параметр pp (двойной указатель) размещен в стеке (pp=0x2001ffec)
// и он будет затерт при выходе из функции
// а его значение *pp - это указатель на p в main (его значение было 0xf и ему поменяли на 0x20000000) !
return;
}
int main(void)
{
uint8_t *p=0x0f;
uint8_t *pp=&p;
printf("p=%p 0x%x pp=%p 0x%x\n" , p , p , pp , pp); //p=0xf 0xf pp=0x2001ffec 0x2001ffec
func(pp);
printf("p=%p 0x%x pp=%p 0x%x\n" , p , p , pp , pp); // p=0x20000000 0x20000000 pp=0x2001ffec 0x2001ffec
printf("p=%p = '%s' \n" , p , p); // p=0x20000000 = '1234567'
Если надо вернуть несколько указателей из функции
Тогда можно тупо возвращать по return структуру с нужным количеством параметров.
И по-видимому это единственный правильный метод.