我正在使用Nordic Semiconductor的nRF51芯片编写蓝牙网格应用程序,在查看一些示例时,我偶然发现了这些代码:
nrf_mesh_address_t address = {NRF_MESH_ADDRESS_TYPE_INVALID, 0, NULL};
address.type = NRF_MESH_ADDRESS_TYPE_GROUP;
address.value = GROUP_ADDRESS;
当我读到这个片段address
时,首先定义了一些立即再次更改的变量。
这个双重定义不是不必要的吗?
nrf_mesh_addrees_t
的定义如下:
typedef struct
{
nrf_mesh_address_type_t type;
uint16_t value;
const uint8_t* p_virtual_uuid;
} nrf_mesh_address_t;
我的第一个想法是p_virtual_uuid
被声明为const
所以在定义之后无法更改,但是在将代码更改为此时我没有收到编译错误:
nrf_mesh_address_t address;
address.type = NRF_MESH_ADDRESS_TYPE_GROUP;
address.value = GROUP_ADDRESS;
address.p_virtual_uuid = NULL;
使用不同的变量定义变量两次有什么好处吗?
答案 0 :(得分:6)
是的,这似乎非常多余。
如果你正在使用C99,我建议:
nrf_mesh_address_t address = { .type = NRF_MESH_ADDRESS_TYPE_GROUP,
.value = GROUP_ADDRESS,
.p_virtual_uuid = NULL };
const
指的是指向的数据,而不是指针本身。后者将是uint8_t * const p_virtual_uuid
。
答案 1 :(得分:2)
数据成员
const uint8_t* p_virtual_uuid;
不是常量数据成员。它是一个指向常量对象的非常量指针。
指向常量对象的常量指针的声明将类似于
const uint8_t * const p_virtual_uuid;
在这种情况下,当定义了结构类型的对象时,你的indead会初始化数据成员。
此代码段中声明后面的表达式语句
nrf_mesh_address_t address = {NRF_MESH_ADDRESS_TYPE_GROUP, 0, NULL};
address.type = NRF_MESH_ADDRESS_TYPE_GROUP;
address.value = GROUP_ADDRESS;
是多余的。
你可以写
nrf_mesh_address_t address = {NRF_MESH_ADDRESS_TYPE_INVALID, GROUP_ADDRESS, NULL};
或者您可以在初始化列表中使用指示符。例如
nrf_mesh_address_t address =
{
.type = NRF_MESH_ADDRESS_TYPE_INVALID,
.value = GROUP_ADDRESS,
.p_virtual_uuid = NULL
};
与C ++相反,C中的支撑列表初始化器存在一个问题。初始化表达式的评估未被排序。因此,如果一个initioalizer的值取决于另一个初始化程序的值,那么确实你需要使用赋值而不是在括号括起的列表中初始化表达式。
从C标准(6.7.8初始化)
23其中任何副作用发生的顺序 初始化列表表达式未指定。
答案 2 :(得分:1)
你是正确的,因为它们是多余的,它等同于你的最后一段代码片段。
但是我确实看到了第一次使用的潜在价值。例如,如果要强制执行始终初始化变量的策略。您可以进行默认初始化
nrf_mesh_address_t address = {NRF_MESH_ADDRESS_TYPE_INVALID, 0, NULL};
可用并准备复制粘贴。
这可以避免这样的情况:
nrf_mesh_address_t address;
address.type = NRF_MESH_ADDRESS_TYPE_GROUP;
address.value = GROUP_ADDRESS;
我想设置type
和value
并将p_virtual_uuid
保留为默认值。但是我忘了初始化它,所以现在我的代码中有bug。
然而,这种做法的价值是值得商榷的。我只想展示一种可能的有效动机。