使变量具有与#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 *
。
我正在 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 *
。