在<地址>地址算术一章中,函数afree
的定义如下:
static char allocbuf[ALLOCSIZE]; // storage for alloc
static char *allocp = allocbuf; // next free position
void afree(char *p)
{
if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
allocp = p;
}
据我所知,if语句的目的是测试p
是否在缓冲区的范围内。
但是,如果p
不在缓冲区的范围内,则比较会导致未定义的行为,不是吗?在进行比较之前,是否不必将两个指针(p
和allocbuf
)都转换为整数?
函数应该不是这样吗?还是这个版本错误?
void afree(char *p)
{
uintptr_t p_int = (uintptr_t) p;
uintptr_t a_start = (uintptr_t) allocbuf;
uintptr_t a_end = (uintptr_t) (allocbuf + ALLOCSIZE);
if (p_int >= a_start && p_int < a_end)
allocp = p;
}
答案 0 :(得分:1)
但是,如果p不在缓冲区的范围内,则比较会导致未定义的行为,不是吗?
是的
在进行比较之前,是否不必将两个指针(
p
和allocbuf
)都转换为整数?
是的,这是通常的解决方法。
即使如此,也未为此类转换后的指针指定>
,<
和某些==
的算术关系。您更新后的代码仍然无法按预期运行,但结果至少不是UB。
考虑两个指针int_street:1
和char_street:4
可以指向相同的物理地址,并且比较起来与指针相等,但是整数0x00010004, 0x00020004
不同。
请注意,K&R是在很早以前写的,甚至在(u)intptr_t
未定义的时候,甚至在Long Time Ago in a Galaxy Far Far Away之前也写过。
C99已启动(u)intptr_t
。它们仍然是可选类型,即使它们非常普遍地实现。