Сделать переменную того же типа / эффекта, что и #define? - PullRequest
2 голосов
/ 20 июня 2019

Я устанавливаю соединение Wi-Fi между ESP32 и маршрутизатором.ESP32 имеет структуру, которая содержит все детали конфигурации Wi-Fi, две из которых - это SSID и пароль.У меня возникают проблемы при установке этих двух, если я пытаюсь использовать переменную.

Это работает, если я определяю строки, которые я хочу, используя #define .... sta - это структура, которая содержит параметры конфигурации, sta is unionedс другой структурой в тип данных, который является wifi_config_t .... ssid и пароль имеют тип uint8_t

//These work
#define ESP_SSID "AccessPoint"
#define ESP_PASS "Pass" 

//These don't work
char ESP_SSID[32] = "AccessPoint" //32 since that's max SSID length
char ESP_PASS[64] = "Pass" //64 since that's max pass length

//...later in code...
wifi_config_t wifi_config = {
    .sta = {
        .ssid = ESP_SSID,
        .password = ESP_PASS
    },
};

//...definition of .sta ...
typedef struct {
    uint8_t ssid[32];
    uint8_t password[64];
...
} wifi_sta_config_t;

Но я пытаюсь сделать так, чтобы я мог изменить SSID и Pass во время выполнения,Вот почему я хочу установить переменную.Однако, если я использую версии переменных, это вызывает следующие ошибки:

warning: initialization makes integer from pointer without a cast [-Wint-conversion]
.ssid = ESP_SSID,
        ^
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
.password = ESP_PASS
            ^
error:missing braces around initializer [-Werror=missing-braces]
.sta = {
       ^

Я знаю, что это совпадение по типу, но я не могу понять, как сделать версию переменной.имеют тот же эффект, что и версия #define!

Ответы [ 2 ]

5 голосов
/ 20 июня 2019

Инициализация массива

Причина, по которой ваш код не компилируется, состоит в том, что элемент ssid в структуре wifi_config_sta_t имеет тип array - и массивы могут быть инициализированы только из строкового литерала или в скобках список. См. здесь для объяснения. Вы пытаетесь инициализировать его из другой переменной массива, что недопустимо.

Следующие инициализации, например, допустимы.

char ssid1[32] = "My WiFi"; // from string literal -> okay
 // from brace-enclosed list -> okay
char ssid2[32] = {'M', 'y', ' ', 'W', 'i', 'F', 'i'};

Это, с другой стороны, не является:

char ESP_SSID[32] = "My WiFi";
// won't work - ESP_SSID is not a string literal
char ssid[32] = ESP_SSID; // ILLEGAL

потому что ESP_SSID не является константным выражением.

Этот ответ на аналогичный вопрос по SO дает дополнительные примеры.

Препроцессор и константные выражения

Обратите внимание, что

#define ESP_SSID "AccessPoint"
// etc.
char ssid[32] = ESP_SSID;

совпадает с

char ssid[32] = "AccessPoint";

Т.е. любые экземпляры в коде ESP_SSID заменяются строковым литералом "AccessPoint" на этапе предварительной обработки. Вот почему использование #define подходит для вашего приложения - вы просто инициализируете массив, используя строковый литерал.

Назначение массива

Если вы хотите обновить SSID и пароль во время выполнения, одним из вариантов является инициализация массива при запуске с нуля, а затем используйте strcpy() для обновления значений по мере необходимости.

wifi_config_t wifi_config = {0}; // Zero initialize all struct memberes
strcpy((char *)wifi_config.sta.ssid, ESP_SSID);
strcpy((char *)wifi_config.sta.password, ESP_PASS);

Обратите внимание, что необходимо привести uint8_t * к char * из-за параметров компиляции, используемых в процессе сборки ESP IDF.

0 голосов
/ 20 июня 2019

Причина, по которой вы получаете эти ошибки, заключается в том, что вы определяете char ESP_SSID[32] как char[], а структура определяет поля как uint8_t []. Это разные указатели (char * против uint8_t *).

Если вы измените декларацию ESP_SSID на uint8_t ESP_SSID[32], предупреждение исчезнет.

В нашем коде ESP32 мы strcpy добавляем в поля, требующие строки, и memcpy в поля, требующие двоичных данных, такие как bssid.

...