3

Suppose I have the following in C++:

char buffer[SIZE];
char * ptr = &buffer[SIZE];

where ptr's value is never dereferenced. Is this even legal to do C++? That is use the memory address one stride from the last element of an array (say as a special value to compare to)?

Thomas Eding
  • 35,312
  • 13
  • 75
  • 106
  • 6
    Does this compile? Should it be `char * ptr = &buffer[SIZE];`? – rwong May 14 '11 at 11:54
  • 2
    Possible duplicate: http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by-the – cpx May 14 '11 at 11:59
  • 3
    You did dereference when you said `buffer[SIZE]`... Formally it's a grey area, but FWIW no compiler I've ever seen will do anything unexpected. – Johannes Schaub - litb May 14 '11 at 12:42
  • 1
    @litb: Its not a gray area. The Standard explicitly allows taking the address, but dereferincing that address is explicitly undefined behavior. – John Dibling May 14 '11 at 15:22
  • 1
    @John But using [] does dereference it! I suppose one should really say `buffer+SIZE` instead of `&buffer[SIZE]`. –  May 14 '11 at 15:27
  • I'm not sure that it does, but I'll have to check the Std later when I get some time. – John Dibling May 14 '11 at 15:29
  • @John: this has been round a few times. The issue is that `&buffer[SIZE]` is defined to mean `&*(buffer + SIZE)`. Nothing in the standard seems to explicitly state that in this context, the `*` operator does not in fact dereference its operand. However, no lvalue-to-rvalue conversion takes place, and in practice as far as implementations are concerned that's what actually performs a memory load (aka "dereference"). – Steve Jessop May 14 '11 at 17:17
  • @John no. He did dereference that address when he said `buffer[SIZE]`. That is equivalent to `*(buffer + SIZE)` which does dereference a pointer, yielding an lvalue. It does *not* read a value from the lvalue, but the grey area consists in that the spec is not clear on whether or not reading the read is required for it to be UB. – Johannes Schaub - litb May 15 '11 at 12:37

2 Answers2

10

If you said:

char buffer[SIZE];
char * ptr = & buffer[SIZE];

then yes, it is legal. You are specifically allowed by the C++ standard to use the one-past-the-end of an array in this manner, and it is used extensively when (for example) working with iterators.

Edit: But see comments by litb and Steve Jessop. If you want to be entirely politcally correct, you probably want:

char * ptr = buffer + SIZE;

Either way, the one-past-the-end address is a valid address - the perhaps not quite clear issue (as I understand it) is whether you are allowed to dereference it.

  • And in fact, many implementations of STL algorithms depend on this guarantee. – John Dibling May 14 '11 at 15:21
  • @John: which implementations of STL algorithms rely on doing `&*(ptr+offset)`? None of them deal in arrays and offsets, they deal in iterators (and hence sometimes in pointers). The address `buffer+SIZE` is definitely fine, that's explicitly dealt with in the definition of pointer addition. It's the intermediate lvalue `*(buffer+SIZE)` that's in question. – Steve Jessop May 14 '11 at 17:03
6

You meant &buffer[SIZE]? Yes it is legal in C++. The value of ptr is one past end of buffer, most standard algorithms can use it as end() iterator for buffer.

Öö Tiib
  • 10,809
  • 25
  • 44