如何修复i2c_config_t结构体初始化的C++编译错误?
修复i2c_config_t结构体初始化的编译错误
问题背景
初始化i2c_config_t结构体时出现编译错误,该结构体定义如下:
/** * @brief I2C initialization parameters */ typedef struct{ i2c_mode_t mode; /*!< I2C mode */ gpio_num_t sda_io_num; /*!< GPIO number for I2C sda signal */ gpio_pullup_t sda_pullup_en; /*!< Internal GPIO pull mode for I2C sda signal*/ gpio_num_t scl_io_num; /*!< GPIO number for I2C scl signal */ gpio_pullup_t scl_pullup_en; /*!< Internal GPIO pull mode for I2C scl signal*/ union { struct { uint32_t clk_speed; /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */ } master; struct { uint8_t addr_10bit_en; /*!< I2C 10bit address mode enable for slave mode */ uint16_t slave_addr; /*!< I2C address for slave mode */ } slave; }; }i2c_config_t;
第一种初始化代码及错误
初始化代码:
const i2c_port_t i2c_master_port = (i2c_port_t)I2C_MASTER_NUM; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, .scl_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, .master = {.clk_speed = I2C_MASTER_FREQ_HZ}, };
编译错误:
.sda_pullup_en行:Out-of-order initializers are not standard in C++(乱序初始化不符合C++标准).master行:a designator for an anonymous union member can only appear between braces that match that anonymous union(匿名联合体成员的指示符只能出现在对应联合体的大括号内)
第二种初始化代码及错误
初始化代码:
i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, .scl_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ };
编译错误:
.sda_pullup_en行:out of order initializers are not standard in C++(乱序初始化不符合C++标准).master.clk_speed行:a designator for an anonymous union member can only appear between braces that match that anonymous union(匿名联合体成员的指示符只能出现在对应联合体的大括号内)expected primary-expression before '.' token('.'前缺少主表达式)class "i2c_config_t" has no "clk_speed" field(i2c_config_t类没有clk_speed字段)
解决方案
1. 修正初始化顺序问题
C++标准要求结构体初始化时,成员的初始化顺序必须与结构体定义中的顺序完全一致。原代码中.scl_io_num的位置早于.sda_pullup_en,但结构体定义里的顺序是sda_io_num→sda_pullup_en→scl_io_num→scl_pullup_en,因此需要调整初始化顺序匹配定义。
2. 修正匿名联合体的初始化语法
C++对匿名联合体的初始化语法要求比C更严格,必须用嵌套大括号明确包裹联合体内部成员的初始化内容,不能直接使用.master作为顶层指示符。
最终修正代码
写法一(保留指定初始化器,可读性更强)
const i2c_port_t i2c_master_port = (i2c_port_t)I2C_MASTER_NUM; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .sda_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, .scl_io_num = I2C_MASTER_SCL_IO, .scl_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, // 用嵌套大括号包裹匿名联合体的初始化内容 { .master = {.clk_speed = I2C_MASTER_FREQ_HZ} } };
写法二(简化版,省略指示符)
const i2c_port_t i2c_master_port = (i2c_port_t)I2C_MASTER_NUM; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .sda_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, .scl_io_num = I2C_MASTER_SCL_IO, .scl_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE, // 直接初始化匿名联合体中的master结构体 { {I2C_MASTER_FREQ_HZ} } };
额外说明
如果编译器支持C20及以上标准,可使用乱序指定初始化器,但为了兼容性,建议遵循结构体定义顺序初始化。匿名联合体的语法限制是C与C的差异点之一,必须严格按照C++语法要求编写初始化代码。
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

