Почему мой массив char пуст
следующий скетч будет работать совершенно нормально и, как и ожидалось :
#include <Wire.h>
#include "SparkFun_External_EEPROM.h"
ExternalEEPROM ExtEEPROM;
char username[33] = "";
char password[65] = "";
void setup()
{
Serial.begin(115200);
delay(1000);
Wire.begin();
#define EEPROM_ADDRESS 0b1011000 // 0x58
ExtEEPROM.setMemorySize(256000/8); // 256kbit = 32kbyte
ExtEEPROM.setPageSize(64); // 64 byte page size.
ExtEEPROM.enablePollForWriteComplete();
ExtEEPROM.setPageWriteTime(10); // max. ms for AT24C128
if (ExtEEPROM.begin(EEPROM_ADDRESS, Wire) == false)
{
Serial.println("No memory detected. Freezing.");
while (1);
}
Serial.println("Memory detected!");
String uuu = "myusername";
String ppp = "mypassword";
uuu.toCharArray(username, sizeof(username) - 1);
ppp.toCharArray(password, sizeof(password) - 1);
Serial.print("password=");Serial.println(password);
ExtEEPROM.put(0, username);
//delay(100);
ExtEEPROM.put(0 + sizeof(username), "greatnewpassword");
}
void loop() {
char xxx[33] = "";
ExtEEPROM.get(0, xxx);
Serial.print("xxx=");Serial.println(xxx); // prints the username
char yyy[33] = "";
ExtEEPROM.get(0 + sizeof(username), yyy);
Serial.print("yyy=");Serial.println(yyy); // prints the password
delay(1000);
}
Однако если я заменю ExtEEPROM.put(0 + sizeof(username), "greatnewpassword");
на ExtEEPROM.put(0 + sizeof(username), password);
, то yyy
печатает пустой в последовательном мониторе. Почему?
@Musa, 👍2
Обсуждение3 ответа
Лучший ответ:
проблема, похоже, в том, что я использую lib. Я думаю, что он не может обрабатывать данные, перекрывающие размер страницы.
если я заменю это
char username[33] = "";
char password[65] = "";
к этому:
char username[16] = "";
char password[16] = "";
все работает нормально, так как он сохраняет и считывает данные с EEPROM через I2C.
разговор был [перенесен на chat](https://chat.stackexchange.com/rooms/134577/discussion-on-answer-by-musa-why-is-my-char-array-empty)., @Juraj
.get
и .put
передают указатель char, а не содержимое массива char. Таким образом, вы записываете не содержимое строки, а адрес в памяти, где она хранится.
С помощью строкового литерала, который фиксирован и никогда не меняется, так что то, что вы пишете, и то, что вы читаете, прекрасно. Однако с переменной адрес может быть любым, и хранить адрес некоторой оперативной памяти, где хранится строка, бессмысленно.
.get()
и .put()
следует использовать только для атомарных, автономных типов, таких как int
или float
, а не для указателей, таких как char *
.
Вместо этого вам нужно использовать функции .read(address, buffer, size)
и .write(address, buffer, size)
для чтения и записи содержимого ваших массивов символов.
В коде операции get()
и put()
передаются фактические массивы, а не указатели. Поскольку массивы передаются _ by reference_, они не распадаются на указатели., @Edgar Bonet
Как уже упоминает Маенко:
.get() и .put() следует использовать только для атомарных, автономных типов, таких как int или float, а не для указателей, таких как char *.
Не уверен, что здесь означает atomic, но вы можете .put и .get любой тип данных, особенно struct.
struct EPROMData {
char username[33];
char password[65];
};
EPROMData data {"myusername","mypassword"};
void setup() {
...
ExtEEPROM.put(0,data);
}
void loop() {
EPROMData d;
ExtEEPROM.get(0,d);
Serial.print("user="); Serial.println(d.username);
...
}
Конечно, если тип данных является указателем или строковым объектом (содержащим только указатель), вы не будете довольны .put / .get
Под атомарным я подразумеваю "это вещь полная в себе". Структура завершена. Int завершен. Char * не является полным, так как он не содержит данных, это всего лишь указатель на них. Так что это не "атомно". То же самое относится и к строковому объекту, поскольку объект не содержит строковых данных, а только указатель на выделенную память, содержащую строковые данные., @Majenko
- Как читать и записывать EEPROM в ESP8266
- Передача функции-члена класса в качестве аргумента
- контент» не захватывается
- esp32 Stack canary watchpoint срабатывает
- Преобразование byte* в int в Arduino
- Очистка EEPROM
- Как передать нестатический член класса в обратный вызов?
- Spiffs против Eeprom на esp8266
Попробуйте сделать последовательную печать пароля, чтобы увидеть, сделал ли вызов toCharArray то, что он должен был сделать., @Nick Gammon
OT: Не пишите
any_boolean == false
, используйте!any_boolean
. Если вы думаете, что думаете, вы должны убедиться, что кто-то понимает, тогда я бы рекомендовал(any_boolean == false) == true
.: - D, @the busybeeOT:
sizeof
- это оператор, а не функция, поэтому используйтеsizeof variable
. Однако его операндом может быть тип, и тогда он нуждается в круглых скобках по синтаксическим причинам. Это приводит к этой вездесущей вредной привычке писать его как функцию., @the busybeeВы уверены, что ставите фактический _array_
password
, а не указатель, созданный его распадом (например,char *foo = password; ExtEEPROM.put (..., foo);
)?, @Edgar Bonet256kbit-это не 256000 бит. Это 256 * 1024 бита, или 262144., @Majenko