2

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

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, whereend_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或数组具有相同的属性,则此方案将受阻。假设这永远不会发生是否安全?按照标准安全吗?如果不是,在实践中是否安全?

4

1 回答 1

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();
于 2011-07-14T23:57:08.413 回答