C中带有#define的未定义行为

问题描述 投票:-2回答:4

我在C语言中有一个定义,看起来像这样

#define ROW_SIZE ID_SIZE + USERNAME_SIZE + EMAIL_SIZE

其值为293然后我这样做

uint32_t num_rows = pager->file_length / ROW_SIZE;

pager->file_length肯定为0num_rows的结果为289。甚至0 / ROW_SIZE的计算结果为289。

为什么对答案的回答是错误的?

c c-preprocessor undefined-behavior
4个回答
3
投票

发生了什么事

uint32_t num_rows = pager->file_length / ROW_SIZE;

展开为

uint32_t num_rows = pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;

so num_rows的值为0 + ID_SIZE + USERNAME_SIZE + EMAIL_SIZE,不为零。考虑在您的定义中添加括号:

#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)

2
投票

宏扩展是基于令牌的替换。换句话说,

pager->file_length / ROW_SIZE

扩展到

pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_SIZE

我相信您同意上述数值不一定为零,特别是如果USERNAME_SIZEEMAIL_SIZE不为零。

要解决这个问题,请在宏定义的表达式两边加上括号:

#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)

1
投票

应该这样写:

#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)

0
投票

您必须记住,预处理器宏基本上在源代码中被查询替换。

如果有,例如

uint32_t num_rows = pager->file_length / ROW_SIZE;

编译器在预处理后会看到什么

uint32_t num_rows = pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;

由于普通operator precedence等于

uint32_t num_rows = (pager->file_length / ID_SIZE) + USERNAME_SIZE + EMAIL_SIZE;

当然不是您期望或想要的。因此,务必始终在宏中使用多余的括号,如[

#define ROW_SIZE (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)
© www.soinside.com 2019 - 2024. All rights reserved.