为了高效的代码维护,我需要确保数组索引0处的值是特定的预定义值。以下代码不起作用:
#define SPECIFIC_ADDR_IDX 0
#define SPECIFIC_ADDR 8
#define NOT_SPECIFIC_ADDR1 12
#define NOT_SPECIFIC_ADDR2 16
typedef struct _struct_s
{
const uint16_t addr; // addresses are constant and are not mutable
uint32_t val;
} struct_s;
struct_s globArr[] =
{
{.addr = SPECIFIC_ADDR, .val = 0},
{.addr = NOT_SPECIFIC_ADDR1, .val = 0},
{.addr = NOT_SPECIFIC_ADDR2, .val = 0},
};
// make sure the address at the SPECIFIC_ADDR_IDX is SPECIFIC_ADDR
_Static_assert(globArr[SPECIFIC_ADDR_IDX].addr == SPECIFIC_ADDR, " Illegal!");
它给出以下编译错误:
error: expression in static assertion is not constant
_Static_assert (globArr[SPECIFIC_ADDR_IDX].addr == SPECIFIC_ADDR, " Illegal!");
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
addr
的定义为const uint16_t
,所以我想在编译时就知道它的值。
在编译时是否有一种有效的方法来执行这种检查?
说明:我了解以这种方式,我无法使用_Static_assert
,const
不会在编译时就知道变量的值。我要问的是,是否有人知道任何一种技巧来解决这类问题。
令人满意的解决方案由Kamil Cuk提出。可以通过指定索引来完成初始化:
struct_t globArr[] =
{
[SPECIFIC_ADDR_IDX] = { .addr = SPECIFIC_ADDR, .val = 0 },
{.addr = NOT_SPECIFIC_ADDR1, .val = 0},
{.addr = NOT_SPECIFIC_ADDR2, .val = 0},
};
在这种情况下,如果将在索引[SPECIFIC_ADDR_IDX]处进行条目的其他初始化,则编译器将发出警告(不保证,但大多数编译器都会这样做)。只需确保在 warning = error 选项为ON的情况下进行编译即可。
答案 0 :(得分:1)
您只需在初始化中指定intex:
#define SPECIFIC_ADDR_IDX 0
#define SPECIFIC_ADDR 8
#define NOT_SPECIFIC_ADDR1 12
#define NOT_SPECIFIC_ADDR2 16
typedef struct _struct_s
{
const uint16_t addr; // addresses are constant and are not mutable
uint32_t val;
} struct_t;
struct_t globArr[] =
{
[SPECIFIC_ADDR_IDX] = { .addr = SPECIFIC_ADDR, .val = 0 },
{.addr = NOT_SPECIFIC_ADDR1, .val = 0},
{.addr = NOT_SPECIFIC_ADDR2, .val = 0},
};
无论如何,您都需要执行运行时断言,因此请使用断言:
void globArr_unittest(void) {
assert(globArr[SPECIFIC_ADDR_IDX].addr == SPECIFIC_ADDR);
}
static_assert
需要一个常量表达式。您不能在变量值上编写静态断言。即使您进行了static const struct_t globArr[]
的操作,globArr
的值也不是常量表达式。 C语言没有像C ++这样的constexpr
(或consteval
)说明符。因此,可悲的是,您无法在C语言中做到这一点。
const
只是一个修饰符,它表示不能通过此句柄修改变量。 const
变量可以修改,并且在C中不可变。
就像你做不到一样:
#if globArr[SPECIFIC_ADDR_IDX].addr == SPECIFIC_ADDR
你不能做到的
static_assert(globArr[SPECIFIC_ADDR_IDX].addr == SPECIFIC_ADDR, "");
什么是常数表达式,可以在cppreference中很好地枚举。数组下标[]
和成员访问权.
运算符的结果不是常量表达式,因此不能在静态断言中使用。