C中带有#define的未定义行为
我在C中有一个定义,看起来像这样C中带有#define的未定义行为,c,c-preprocessor,undefined-behavior,C,C Preprocessor,Undefined Behavior,我在C中有一个定义,看起来像这样 #define ROW_SIZE ID_SIZE + USERNAME_SIZE + EMAIL_SIZE 估计为293 然后我做这个 uint32_t num_rows = pager->file_length / ROW_SIZE; pager->file\u length肯定是0 num_rows的结果是289。即使0/行大小也计算为289 为什么表达式的答案是错误的?宏扩展是基于令牌的替换。换句话说, pager->file_length
#define ROW_SIZE ID_SIZE + USERNAME_SIZE + EMAIL_SIZE
估计为293
然后我做这个
uint32_t num_rows = pager->file_length / ROW_SIZE;
pager->file\u length
肯定是0num_rows
的结果是289。即使0/行大小
也计算为289
为什么表达式的答案是错误的?宏扩展是基于令牌的替换。换句话说,
pager->file_length / ROW_SIZE
扩展到
pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_SIZE
我相信您也同意,上述值不一定为零,尤其是当USERNAME\u SIZE
或EMAIL\u SIZE
不为零时
要解决此问题,请在宏定义中的表达式周围加括号:
#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)
发生了什么事
uint32_t num_rows = pager->file_length / ROW_SIZE;
扩展为
uint32_t num_rows = pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;
因此num_rows的计算结果为0+ID_SIZE+USERNAME_SIZE+EMAIL_SIZE
,这不是零。考虑将括号添加到定义:
#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)
您必须记住,预处理器宏基本上是在源代码中被查询替换的 如果你有
uint32_t num_rows = pager->file_length / ROW_SIZE;
编译器在预处理后看到的是
uint32_t num_rows = pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;
由于法线等于
uint32_t num_rows = (pager->file_length / ID_SIZE) + USERNAME_SIZE + EMAIL_SIZE;
这当然不是你所期望或想要的。因此,在宏中始终使用额外的括号很重要,如
#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)
应该这样写:
#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)
#定义行大小ID\u大小+用户名大小+电子邮件大小
->#定义(行大小ID\u大小+用户名大小+电子邮件大小)
这是一个非常常见的常见问题解答。任何初级C编程书籍都会在预处理器一章中解释如何编写正确的宏。它肯定会提到这个特定的错误,并带有操作符优先级和缺少正确的括号。那就去读那一章吧。有人知道这方面的经典复制品吗?我们需要一个!在定义一个macro@Lundin这个怎么样: