Не удалось вернуть значение int из функции

Я создал библиотеку myJSON, чтобы упростить чтение и запись значений из/в FLASH моего ESP8266 NodeMCU/Wemos Mini.

Я не хочу "испортить" вопрос, опубликовав весь свой код/библиотеку, но попытаюсь объяснить, что происходит -

Я получаю значение 0 при чтении определенного key (а не его сохраненного value ). Я предполагаю, что это не имеет ничего общего с библиотекой myJSON, но мое понимание возврата значения из функции.

Код выглядит следующим образом:

(сначала некоторые пояснения):

1) json — это экземпляр библиотеки myJSON.

2) json.setValue(key, value) — получает key и value (char/int) и сохраняет их в ВСПЫШКА.

3)json.getINTValue(key, return_var) — получает key и возвращает его значение int в return_var. функция возвращает 1 — в случае успешного чтения и 0 — в противном случае.

внутри setup()

int int_val;
// json.setValue("int_key",343); // закомментировано после первого запуска - чтобы убедиться, что он сохранен и прочитан из флэш-памяти.
Serial.println(json.getINTValue("int_key",int_val)); // ЗАМЕТКА 2
Serial.print("Value is: "); // ЗАМЕТКА 3
Serial.println(int_val);   // ЗАМЕТКА 3

myJSON (только соответствующий код)

bool myJSON::getINTValue (const char *key, int retval){
        StaticJsonDocument<DOC_SIZE> tempJDOC;
        myJSON::readJSON_file(tempJDOC);
        bool hasKey = tempJDOC.containsKey(key);
        if (hasKey){
          retval = tempJDOC[key];
          Serial.print("retval :"); // ПРИМЕЧАНИЕ 1
          Serial.println(retval);  // ПРИМЕЧАНИЕ 1
          return 1;
        }
        else {
          return 0; // когда ключа нет
        }
}

void myJSON::setValue(const char *key, char *value){
        StaticJsonDocument<DOC_SIZE> tempJDOC;
        myJSON::readJSON_file(tempJDOC);
        tempJDOC[key]=value;
        myJSON::saveJSON2file(tempJDOC);
}
void myJSON::setValue(const char *key, int value){
        StaticJsonDocument<DOC_SIZE> tempJDOC;
        myJSON::readJSON_file(tempJDOC);
        tempJDOC[key]=value;
        myJSON::saveJSON2file(tempJDOC);
}

результат (СМ. ОБОЗНАЧЕНИЯ):

21:01:03.198 -> retval :343  // ВЫВОД ПРИМЕЧАНИЕ 1
21:01:03.198 -> 1            // ВЫВОД ПРИМЕЧАНИЕ 2
21:01:03.198 -> Value is: 0  // ВЫВОД ПРИМЕЧАНИЕ 3

Насколько я понял:

1) setValue работает по мере необходимости (включая сохранение во флэш-память). 2) необъяснимо, кроме получения значения = 0, при установке значения char (есть 2 функции myJSON::setValue для работы с int и char), код работает по мере необходимости.

Благодарим за любую помощь (и извините за мой английский).

Парень

, 👍1

Обсуждение

bool myJSON::getINTValue(const char *key, int &retval){, @Juraj

@Юрай, ты можешь объяснить, почему? и почему она отличается от переменной char?, @Guy . D

это не вопрос Arduino. & является «ссылкой». параметр с & не значение, а ссылка на переменную, @Juraj

@Juraj - я знаю среднее значение &, но почему оно не передает свое значение a в retval?, @Guy . D


2 ответа


Лучший ответ:

2

параметры вызова функции копируются в параметры функции. если указатель копируется, он все еще указывает на память, в которую вы записываете данные. если int копируется, то изменение значения изменяет копию, а не переменную, используемую в качестве параметра. ссылка — это своего рода указатель

как создать входной параметр, передав параметр по ссылке

void setup() {

  Serial.begin(115200);
  int x = 3;
  fnc(x);
  Serial.println(x);
}

void loop() {

}

void fnc(int &x) {
  x = 5;
}

выводит 5

пример со сложным типом

#include <IPAddress.h>

void setup() {

  Serial.begin(115200);
  IPAddress ip(192, 168, 1, 5);
  fnc(ip);
  Serial.println(ip);
}

void loop() {

}

void fnc(IPAddress& ip) {
  ip = IPAddress(192, 168, 1, 3);
}

с &ip он печатает 192.168.1.3. без усилителя он печатает 192.168.1.5

,

Спасибо! и причина, по которой char ведет себя по-другому, заключается в том, что он указывает на указатель?, @Guy . D

char* — это указатель. и char[] тоже указатель. он копируется, поэтому присвоение ему другого указателя не сработает. но если вы измените память, на которую она указывает, вы прочитаете за пределами функции ту же ячейку памяти с измененным содержимым., @Juraj


2

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

Определение getINTValue() гласит

getINTValue (const char *key, int retval)

поэтому retval будет целым числом и будет вызываться по значению. Это означает, что локальная переменная с таким именем создается и заполняется значением из параметров вызова функции. Вы пишете в эту переменную, но она выбрасывается, когда функция возвращается. И запись в локальную переменную не изменила внешнюю переменную.

Вы должны использовать вызов по ссылке. Ваша функция должна принимать указатель на целочисленную переменную. Затем вы разыменовываете его и пишете в него:

getINTValue (const char *key, int *retval){
    ...
    *retval = tempJDOC[key];
    ...
}

При вызове функции getINTValue() это должно быть сделано следующим образом:

int value;
bool result = getINTValue("int_key", &value);

Операция & возвращает вам указатель на переменную value, которую функция затем использует для записи значения в эту ячейку памяти.


char* отличается, потому что в этом случае вы передаете массив функции. Компилятор видит, что используемая переменная является массивом и использует в качестве параметра указатель на первый элемент массива. Это распространенный способ, потому что вы можете перебирать массив с помощью указателей (без номеров индексов). Вы можете сделать то же самое с любым массивом любого типа, но в этом случае у вас будет только одна переменная, а не массив.

,

Ой, извините, неправильно прочитал. Не могли бы вы вкратце уточнить свой комментарий или дать мне подсказку, что здесь искать в Google? Я научился этому так, как показал в своем ответе, и во время поиска в Google я не смог найти ваш способ сделать это (хотя я долго не гуглил). Было бы здорово узнать больше., @chrisl

Я написал это как ответ, @Juraj