Does std :: end have to specify a null terminator for strings?

I noticed that I std::end

will always refer to the null terminator when it comes to strings or character arrays. I thought I std::end

should have been referring to the end of the array following the last valid element. Is it '\0'

not a valid item? This is part of the array. Here are some tests that return true:

#include <iostream>

int main()
{
    std::string s("hello!");
    auto s_end = *(s.data() + s.size() + 1);
    std::cout << std::boolalpha  << (*std::end(s) == s_end) << "\n"
              << (s_end == '\0') << "\n";
    char buf[6 + 1];
    std::copy(s.begin(), s.end(), &buf[0]);
    auto buf_end = *(buf + s.size() + 1);
    std::cout << (*std::end(buf) == buf_end) << "\n"
              << (buf_end == '\0') << "\n";

    char test[3] = {'h', '\0', 'e'};
    std::cout << (*std::end(test) == '\0');
    return 0;
}

      

+3


source to share


1 answer


For a character array, std::end

indeed specifies the last character in the array. For

char test[3] = {'h', '\0', 'e'};

      

pointer std::end(test)

matches test + 3

. A dereference expression is the same as an evaluation test[3]

. This behavior is undefined. In your particular case, it happened that he gave '\0'

. But in general it can lead to a different value, or to a failure, or something else entirely. std::end(test)

points not to the character '\0'

at index 1 in the array test

!

Note that it std::end

behaves evenly across all arrays. That is, if we have an array T a[N]

, then it std::end(a)

returns a + N

, regardless of whether T

char

or what the content is a

. It doesn't give you the end of the line; it gives you the end of the array. Again, the return value is always a + N

. NO EXCEPTIONS!



A std::string

terminating null character exists for, but it is not considered part of the string. (Unlike other characters, you are not allowed to change it, when the pain is undefined.) If you have

std::string s("hello");

      

it s[5]

will have a null character value, but as I said, it is not considered part of the string: s

it is considered to have five characters, not six. It's best to think of it std::string

as not null terminated at all. The last character s[4]

that matters 'o'

, a std::end(s)

is the iterator passed only std::begin(s) + 4

, that is std::begin(s) + 5

.

This is a little more subtle than it looks, as the standard does not technically guarantee that std::end(s)

it makes no difference at all, so you cannot say that it points to a trailing null. In practice, it points to a trailing null, but dereferences it is still undefined.

+5


source







All Articles