C99:数组或堆分配的缓冲区是否会以UINTPTR_MAX结束?

Jos*_*man 2 c pointers c99 intptr

我可以假设以下不变量吗?

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);
}
Run Code Online (Sandbox Code Playgroud)

在我正在编写的解析器中,我想使用指针标记某些偏移:例如,我可能有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();
}
Run Code Online (Sandbox Code Playgroud)

但是如果malloc()返回内存ptr + len == UINTPTR_MAX,或者数组具有相同的属性,那么这个方案就会被挫败.假设这种情况永远不会发生是否安全?根据标准是否安全?如果没有,在实践中是否安全?

bdo*_*lan 5

C标准提供的唯一保证如下:

ISO/IEC 9899:1999(E)§7.18.1.4/ 1

以下类型指定一个带符号的整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将等于原始指针:

intptr_t
Run Code Online (Sandbox Code Playgroud)

以下类型指定一个无符号整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将等于原始指针:

uintptr_t
Run Code Online (Sandbox Code Playgroud)

这些类型是可选的.

不保证这些转换整数的精确内容.特别是,给定一个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();
}
Run Code Online (Sandbox Code Playgroud)

如果end_of_submessage可能位于不同的缓冲区中,您可以使用以下内容:

char *buf_start = buf;
// ...
if (buf_start <= end_of_submessage && buf >= end_of_submessage)
  process_submsg_end();
Run Code Online (Sandbox Code Playgroud)