字符串 s; &s+1;合法的?布?

发布于 2024-08-24 07:39:55 字数 1521 浏览 7 评论 0原文

考虑以下代码:

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

这里感兴趣的是 &myAry[numStrs]:numStrs 等于 5,因此 &myAry[numStrs] 指向不等于 5 的值存在;数组中的第六元素。上面的代码中还有另一个例子:myVec.end(),它指向向量myVec的末尾一位。获取这个不存在的元素的地址是完全合法的。我们知道string的大小,因此我们知道C风格string数组的第6个元素的地址必须指向哪里。只要我们只计算这个指针而不取消引用它,就可以了。我们甚至可以将它与其他指针进行比较以获得相等性。 STL 在作用于一系列迭代器的算法中始终执行此操作。 end() 迭代器指向末尾,循环在计数器 != end() 时保持循环。

现在考虑一下:

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

这段代码合法且定义明确吗?将数组元素的地址放在末尾之后是合法且定义良好的,如 &myAry[numStrs] 中所示,因此假装 应该是合法且定义良好的myPtr 也是一个数组?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

铁轨上的流浪者 2024-08-31 07:39:55

拥有一个指向数组“超出末尾”的指针是合法的,而不是 UB,并且任何单个对象都可以被视为位于长度为 1 的数组中;但是,由于 &ptr[1] 取消引用然后获取地址的技术性,您需要使用 ptr + 1 来代替。这也适用于 &array[size] 变为 array + size

您所拥有的将在我所知道的所有平台上按照您的预期工作,但考虑到使用明确正确的形式是多么容易,我认为没有理由不这样做。

It is legal and not UB to have a pointer to "one past the end" of an array, and any single object can be treated as if it were in an array of length 1; however, you need to use ptr + 1 instead due to the technicality of &ptr[1] dereferencing and then taking the address. This also applies to &array[size] becoming array + size.

What you have will work as you expect on all platforms of which I'm aware, but given how easy it is to use the unambiguously correct form, I see no reason not to do that instead.

隔岸观火 2024-08-31 07:39:55

C++标准5.6/4“加法运算符”中说:

就这些运算符而言,指向非数组对象的指针的行为与指向长度为 1 的数组的第一个元素的指针相同,对象的类型作为其元素类型。

C99 标准 6.5.6/7 的说法基本相同。

The C++ standard in 5.6/4 "Additive operators" says:

For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

The C99 standard 6.5.6/7 says essentially the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文