在Address Arithmetic一章中,函数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;
}
但是,如果p不在缓冲区的范围内,则比较会导致未定义的行为,不是吗?
是。
在进行比较之前,是否有必要将两个指针(
p
和allocbuf
)转换为整数?
是的,这是通常的工作。
即使如此,>
,<
和一些==
的算术关系也没有为这样的转换指针指定。您更新的代码仍然无法按预期工作,但结果至少不是UB。
考虑两个指针int_street:1
和char_street:4
可能指向相同的物理地址并且比较等于指针,但整数0x00010004, 0x00020004
是不同的。
请注意,K&R是在不久前写的,即使在没有定义Long Time Ago in a Galaxy Far Far Away的(u)intptr_t
之前。
C99开始了(u)intptr_t
。它们仍然是可选类型,即使它们非常普遍实现。