开发者

C99: Will arrays or heap-allocated buffers ever end at UINTPTR_MAX?

Can I assume the following invariant?

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);
}

In a parser I am writing I want to mark certain offsets using pointers: for example I might have char *end_of_submessage, where end_of_submessage is relative to my current buffer. But if the submessage does not end inside the current buffer, I want to use a value that is larger than any offset in the c开发者_如何学运维urrent buffer could possibly be. So I would do:

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();
}

But this scheme would be thwarted if malloc() returned memory such that ptr + len == UINTPTR_MAX, or an array had the same property. Is it safe to assume this will never happen? Is it safe according to the standard? If not, is it safe in practice?


The only guarantee that the C standard provides is follows:

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

The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

intptr_t

The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

uintptr_t

These types are optional.

No guarantees are given about the precise content of these converted integers. In particular, given a char pointer p, (uintptr_t)(p + 1) == ((uintptr_t)p) + 1 is not guaranteed to be true.

If you want to mark offsets, you should use a ptrdiff_t offset from another pointer, or you can simply use a pointer to mark the end. For example:

void parse(char *buf, size_t len, char *end_of_submessage)
{
// ...
    if (buf >= end_of_submessage)
        process_submsg_end();
}

If end_of_submessage may lie in a different buffer, you can use something like:

char *buf_start = buf;
// ...
if (buf_start <= end_of_submessage && buf >= end_of_submessage)
  process_submsg_end();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜