【发布时间】:2019-09-22 12:01:51
【问题描述】:
假设我有一个宏(有关为什么的更多详细信息,请参阅下面的 P.S. 部分)
void my_macro_impl(uint32_t arg0, uint32_t arg1, uint32_t arg2);
...
#define MY_MACRO(arg0, arg1, arg2) my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2))
要使用此宏的硬件是小端并使用 32 位架构,因此所有指针都达到(包括)32 位宽度。我的目标是在错误传递uint64_t 或int64_t 参数时警告用户。
我正在考虑像这样使用sizeof
#define MY_MACRO(arg0, arg1, arg2) do \
{ \
static_assert(sizeof(arg0) <= sizeof(uint32_t)); \
static_assert(sizeof(arg1) <= sizeof(uint32_t)); \
static_assert(sizeof(arg2) <= sizeof(uint32_t)); \
my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2)); \
} while (0)
但是用户可以使用带有位字段的MY_MACRO,然后我的代码无法编译:
错误:“sizeof”对位域的应用无效
问题:是否可以在编译时检测宏参数的大小是否大于uint32_t?
附言
MY_MACRO 在实时嵌入式环境中的作用类似于printf。这个环境有一个硬件记录器,它最多可以接收 5 个参数,每个参数应该是 32 位。目标是保留printf 的标准格式。格式字符串是离线解析的,解析器很清楚每个参数都是 32 位的,所以它会根据格式字符串中的%... 进行转换。可能的用法如下。
不需要的用法:
uint64_t time = systime_get();
MY_MACRO_2("Starting execution at systime %llx", time); // WRONG! only the low 32 bits are printed. I want to detect it and fail the compilation.
预期用途:
uint64_t time = systime_get();
MY_MACRO_3("Starting execution at systime %x%x", (uint32_t)(time >> 32), (uint32_t)time); // OK!
【问题讨论】:
-
使用
sizeof 0 + (arg0)会有什么不同吗? -
@melpomene 假设 32 位架构 (godbolt.org/z/PwI9mZ),这可能会有所不同。
-
@melpomene ...唯一的缺点是当传递的参数是数组
warning: sizeof on pointer operation will return size of 'int *' instead of 'int [30]' [-Wsizeof-array-decay]时会发出警告
标签: c sizeof bit-fields c11