C 中#define 的未定义行为
Undefined behaviour with #define in C
我在 C 中有一个定义,看起来像这样
#define ROW_SIZE ID_SIZE + USERNAME_SIZE + EMAIL_SIZE
计算结果为 293
然后我这样做
uint32_t num_rows = pager->file_length / ROW_SIZE;
pager->file_length
肯定是0
num_rows
的结果是 289。甚至 0 / ROW_SIZE
的计算结果也是 289。
为什么表达式的答案是错误的?
宏扩展是基于令牌的替换。也就是说,
pager->file_length / ROW_SIZE
扩展到
pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_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;
所以 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;
由于正常 operator precedence 等于
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)
我在 C 中有一个定义,看起来像这样
#define ROW_SIZE ID_SIZE + USERNAME_SIZE + EMAIL_SIZE
计算结果为 293 然后我这样做
uint32_t num_rows = pager->file_length / ROW_SIZE;
pager->file_length
肯定是0
num_rows
的结果是 289。甚至 0 / ROW_SIZE
的计算结果也是 289。
为什么表达式的答案是错误的?
宏扩展是基于令牌的替换。也就是说,
pager->file_length / ROW_SIZE
扩展到
pager->file_length / ID_SIZE + USERNAME_SIZE + EMAIL_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;
所以 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;
由于正常 operator precedence 等于
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)