Возврат функции char*

Пытаюсь реализовать возврат функции значений char

//Считанный штрихкод, объявлен глобально
char* recordedBar;

//Для теста, имитирует работу считывателя
void recoder() {
  if (millis() > testBarcodeTime) {
    testBarcodeTime = millis() + random(500, 4000);
    String bar = "460402354587" + String(random(0, 3));
    recordedBar = bar.c_str();
  }
}

recordedBar внутри функции имеет необходимое значение, но за пределами пустой. В string не хочу продолжать работу так как сильно много занимает памяти. Как реализовать функцию, что бы можно было работать с переменной в любом месте кода?

А по-другому та же самая информация меньше памяти будет занимать, по-твоему?

Да, как угодно:

Спокойно продолжать со String. Ваша боялка про

надумана. Она занимает всего на 6 байтов больше, чем если без String делать.

Но, если эти 6 байтов так критичны, запросите символьный буфер (при помощи new или calloc) и работайте вообще без String.

Конечно, ведь вы обьявили recordedBar как указатель. Ваша строчка bar - локальная для функции, внутри функции она существует, а при выходе уничтожается.

Ваш указатель остался, но там куда он указывает - уже ничего нет.

а вообще функция с возвращаемым значением должна иметь тип этого значения, а не void

1 лайк

а может там уже что-то уже другое :slight_smile:

@DronTat
так же обратите внимание, что вот это вот неправильная работа с миллис. При таком подходе ваш код сглючит при переполнении. Используйте вычитание времен, а не сложение.

//Считанный штрихкод, объявлен глобально
char* recordedBar;

//Для теста, имитирует работу считывателя
char* recoder() {
  String bar = "";
  if (millis() > testBarcodeTime) {
    testBarcodeTime = millis() + random(500, 4000);
    bar = "460402354587" + String(random(0, 3));
  }
  return bar.c_str();
}

Простите, но это … Вы что-то покурили :frowning:

Работать это будет точно также, как у ТС, т.е. не будет. И ровно по тем же причинам.

да, в примере я ошибся написав void. Но как вы и можете предполагать, сути это не меняет. Я думал что записав в глобальный char я могу как то решить вопрос. У меня просто после компилирования остается чуть больше 500 байтов, есть работа с ethernet шилдом и ардуинка после недели работы начинает сбоить, шлет в сеть испорченный пакеты http. Думал чуть освободить память с помощью перевода в char

Точно-точно )))
Торопился, бегаю тут как угорелый просто … ))

//Считанный штрихкод, объявлен глобально
char* recordedBar;

//Для теста, имитирует работу считывателя
char* recoder() {
  String bar = "";
  if (millis() > testBarcodeTime) {
    testBarcodeTime = millis() + random(500, 4000);
    bar = "460402354587" + String(random(0, 3));
  }
  return *bar.c_str();
}

Не Ваш день сегодня. Этот вариант ещё хуже :frowning:

Хотите освободить 6 байтов - освобождайте, только делайте это правильно, как я Вам написал в сообщении №3.

еще раз - ваш “глобальный char” не может хранить внутри даже одного символа, потому что это не самостоятельная переменная, а указатель. В нее ничего “записать” нельзя.
Разберитесь с разницей между переменными и указателями

Да и с освобождением памяти определись. Что освобождать будете. Память от статических переменных или динамических. Первые определяются компилятором, вторые уже при работе программы.

Ну память пусть сам выделяет, я чтоли должен? :smiley:

И, да, переводом Вы ничего не освободите. А вот более аккуратной работой со String могли бы. Как Вы работаете со String? Ощущение такое, что Вы специально пишете так, чтобы ни в какую память не влезть.

Вот смотрите, я добавил в String печать всякий раз когда она запрашивает и освобождает память. Затем запустил пример, где сделано всё как у Вас:

Код как у Вас
void setup(void) {
   Serial.begin(9600);
   Serial.println("Go on!");
//
   String bar = "";
   bar = "460402354587" + String(random(0, 3));
//
   Serial.println(bar);
}

void loop(void) {}
Результат кода как у Вас
Go on!
GET: 1 (1)
GET: 2 (1)
GET: 13 (1)
GET: 14 (13)
GET: 14 (1)
FREE: 14
FREE: 2
4604023545871
FREE: 14

Здесь в скобках стоит освобождаемая после GET память, т.е. то, что идёт на фрагментацию.

Посмотрите на эти GET. Вы в процессе работы со строкой нахапали аж 44 байта! А потом начали их освобождать! НАХРЕНА?

Стоило переписать Ваш код чуть-чуть аккуратнее:

Код чуть поаккуратнее
void setup(void) {
   Serial.begin(9600);
   Serial.println("Go on!");
//
   String bar("460402354587");
   bar += String(random(0, 3));
//
   Serial.println(bar);
}

void loop(void) {}

как результат сразу стал другим!

Результат
Go on!
GET: 13 (1)
GET: 2 (1)
GET: 14 (13)
FREE: 2
4604023545871
FREE: 14

Здесь Вы хапнули всего 29 байтов! Т.е. в полтора раза меньше, чем в прошлый раз. А всего-то было делов - чуть поаккуратнее написать код!

2 лайка

Так и есть. Попробовал, ради интереса. Правда , если кто опытный, может что и получится, я же только начал пробовать работу с памятью(а давно пора-бы разобраться)).

Вот, как раз это есть в примере

Спойлер
void print_s(char *str, int size) {
 for (int n = 0; n < size; n++)
  Serial.print((*(str + n)) - 48);
  Serial.println();
}

void setup() {
  Serial.begin(9600);
  Serial.println("Go on!");
  char bar[] = {"460402354587"};
  char *st = &bar[0];//адрес строки
  int size_str = strlen(bar) + 1;//размер строки, включая "\0"
  st = (char *)realloc(st, size_str + 1);//увеличиваем размер на 1 байт
  *(st + size_str - 1) = (char)(random('0', '3'));//дописываем к концу строки
  print_s(st, size_str);                          // псевдо-случайное значение
  // выводим в монитор
}

void loop() {

}
//Скетч использует 3422 байт (11%) памяти устройства.
//Всего доступно 30720 байт.
//Глобальные переменные используют 222 байт (10%) динамической памяти,
//оставляя 1826 байт для локальных переменных
//=====================

А это код от Евгения Петровича. По глобальным переменным один в один.

Спойлер
void setup(void) {
   Serial.begin(9600);
   Serial.println("Go on!");
//
   String bar("460402354587");
   bar += String(random(0, 3));
//
   Serial.println(bar);
}

void loop(void) {}

//Скетч использует 3664 байт (11%) памяти устройства.
//Всего доступно 30720 байт.
//Глобальные переменные используют 222 байт (10%) динамической памяти,
//оставляя 1826 байт для локальных переменных.

“Освободители” вы какую память освобождаете :rofl: “Куча” лежит в другом месте. Хорошо что не начали освобождать квадратные метры жилплощади программными способами :roll_eyes: или уже начали. :face_with_monocle:

Я пытался делать так:

  1. запросить один байт после строки bar
  2. если это невозможно, запросить 14 байт по новому адресу,
    и переписать туда bar.
    старую строку удалить
    3.дописать значение в конец строки.
    Т.е. я так понял работу reallock(). (впервые использую эту функцию)
    Если ошибаюсь, поправьте пжлст
    P.S. Т.е. если 1 байт доступен, то ничего и не освобождаем…

String делает ровно то же самое. Зачем тогда огород городить? Пусть делает.