string s; &s+1; Legal? UB?
- by John Dibling
Consider the following code:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myAry[] =
{
"Mary",
"had",
"a",
"Little",
"Lamb"
};
const size_t numStrs = sizeof(myStr)/sizeof(myAry[0]);
vector<string> myVec(&myAry[0], &myAry[numStrs]);
copy( myVec.begin(), myVec.end(), ostream_iterator<string>(cout, " "));
return 0;
}
Of interest here is &myAry[numStrs]: numStrs is equal to 5, so &myAry[numStrs] points to something that doesn't exist; the sixth element in the array. There is another example of this in the above code: myVec.end(), which points to one-past-the-end of the vector myVec. It's perfecly legal to take the address of this element that doesn't exist. We know the size of string, so we know where the address of the 6th element of a C-style array of strings must point to. So long as we only evaluate this pointer and never dereference it, we're fine. We can even compare it to other pointers for equality. The STL does this all the time in algorithms that act on a range of iterators. The end() iterator points past the end, and the loops keep looping while a counter != end().
So now consider this:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myStr = "Mary";
string* myPtr = &myStr;
vector<string> myVec2(myPtr, &myPtr[1]);
copy( myVec2.begin(), myVec2.end(), ostream_iterator<string>(cout, " "));
return 0;
}
Is this code legal and well-defined? It is legal and well-defined to take the address of an array element past the end, as in &myAry[numStrs], so should it be legal and well-defined to pretend that myPtr is also an array?