我可以假设以下不变量吗?
void foo(char *buf, size_t len) {
// "buf" points to either an array or memory allocated with malloc().
assert((uintptr_t)(buf + len) < UINTPTR_MAX);
}
在我正在编写的解析器中,我想使用指针标记某些偏移:例如,我可能有char *end_of_submessage
,其中end_of_submessage
相对于我当前的缓冲区。但是如果子消息没有在当前缓冲区内结束,我想使用一个大于当前缓冲区中任何偏移量的值。所以我会这样做:
void parse(char *buf, size_t len, uintptr_t end_of_submessage) {
// Some parsing that might increment "buf"
// ...
// If end_of_submessage == UINTPTR_MAX, processing will not be
// triggered even if we have processed our entire current buffer.
if ((uintptr_t)buf >= end_of_submessage)
process_submsg_end();
}
但是如果malloc()返回内存ptr + len == UINTPTR_MAX
或者数组具有相同的属性,那么这个方案就会被挫败。假设这种情况永远不会发生是否安全?根据标准是否安全?如果没有,在实践中是否安全?
答案 0 :(得分:5)
C标准提供的唯一保证如下:
ISO / IEC 9899:1999(E)§7.18.1.4/ 1
以下类型指定带有属性的带符号整数类型 那么任何有效的void指针都可以转换为这种类型 转换回指向void的指针,结果将相等 到原始指针:
intptr_t
以下类型表示 无符号整数类型,其属性是指向void的任何有效指针 可以转换为这种类型,然后转换回指向void的指针, 并且结果将与原始指针进行比较:
uintptr_t
这些类型是可选的。
不保证这些转换整数的精确内容。特别是,给定一个char指针p
,(uintptr_t)(p + 1) == ((uintptr_t)p) + 1
不能保证为真。
如果要标记偏移,则应使用另一个指针的ptrdiff_t
偏移量,或者只需使用指针标记结束。例如:
void parse(char *buf, size_t len, char *end_of_submessage)
{
// ...
if (buf >= end_of_submessage)
process_submsg_end();
}
如果end_of_submessage
可能位于不同的缓冲区中,您可以使用以下内容:
char *buf_start = buf;
// ...
if (buf_start <= end_of_submessage && buf >= end_of_submessage)
process_submsg_end();