使变量具有与#define 相同的 type/effect?

Make variable have same type/effect as #define?

我正在 ESP32 和路由器之间建立 wifi 连接。 ESP32 有一个包含所有 wifi 配置详细信息的结构,其中两个是 SSID 和密码。如果我尝试使用变量,我在设置这两个时遇到问题。

如果我使用#define 定义我想要的字符串,它就可以工作....sta 是保存配置参数的结构,sta 与另一个结构合并为 wifi_config_t 的数据类型。 ..ssid 和 password 的类型是 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 版本具有相同的效果!

您收到这些错误的原因是您将 char ESP_SSID[32] 定义为 char[],而结构将字段定义为 uint8_t []。这些是不同的指针(char * vs uint8_t *)。

如果将 ESP_SSID 的声明更新为 uint8_t ESP_SSID[32],警告将消失。

在我们的 ESP32 代码中,我们 strcpy 进入需要字符串的字段, memcpy 进入需要二进制数据的字段,例如 bssid.

数组初始化

您的代码无法编译的原因是 wifi_config_sta_t 结构中的 ssid 元素是 array 类型 - 并且只能初始化数组来自字符串文字或 brace-enclosed 列表。有关说明,请参阅 here。您正试图从另一个数组变量初始化它 - 这是非法的。

例如下面的初始化是合法的。

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不是常量表达式。

This answer 对 SO 上的类似问题给出了更多示例。

预处理器和常量表达式

注意

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

相同
char ssid[32] = "AccessPoint";

即,在 pre-processing 阶段,ESP_SSID 代码中的任何实例都将替换为字符串文字 "AccessPoint"。这就是为什么使用 #define 适用于您的应用程序的原因 - 您只是使用字符串文字初始化数组。

数组赋值

如果您想在 run-time 期间更新 SSID 和密码,一种选择是在启动时 zero-initialize 数组 - 然后根据需要使用 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);

请注意,由于 ESP IDF 构建过程中使用的编译选项,有必要将 uint8_t * 转换为 char *