1

我有一小段代码做了一些有趣的事情,但我不知道它是如何做到的。

int main(int argc, const char * argv[])
{
    char text[] = "object";
    for(char *ptr = &text[0]; *ptr != '\0'; ptr+=2) 
    {   
        cout << ptr << endl;
        ptr--;
    }
    return 0;
}

发生的事情是它每次都从 [1]、[2]、[3] 等到字符串的末尾,打印出内容。我无法理解它是如何做到的,因为指针永远不会被取消引用,但正确的字母似乎会被打印出来。我会假设不是字符串的字母,而是指针值将打印为奇怪的字符,但事实并非如此。

4

3 回答 3

3

这是未定义的行为。第一次迭代,ptr指向"object"。一切都好,打印出来,但你这样做ptr--。所以现在,ptr指向你不再拥有的记忆。只要您不对它取消引用或对其进行指针运算,就可以了。但是当你在循环中增加它时你会这样做 - ptr+=2.

为什么会这样:

在第一次迭代中,ptr指向"object",所以它打印出来。cout::operator << (const char*)打印一个以 null 结尾的字符串。不需要char取消引用。

在第二次迭代中,ptr递减,然后增加2,指向"bject"。等等...

于 2012-05-24T20:01:15.547 回答
2

你是对的,通常地址会被打印出来。除了 有一个特殊的重载char *,它将其视为 C 字符串并输出所有字符,从 开始ptr,直到找到零 ( \0)。

...或者如果您的代码正确,就会发生这种情况,因为就像现在一样,它通过ptr在第一次迭代时递减(ptr超出范围)然后立即将其递增 2 来调用 UB。


如果要显示指针的地址void *,请将其转换为:

cout << static_cast<void *>(ptr) << endl;
于 2012-05-24T20:00:23.107 回答
2

这里没有什么真正的hacky。有一个ostream::operator<<(const char *p)打印字符串。指针沿着字符串走,程序从不同的位置开始打印它。唯一奇怪的是疯狂的 +2, -1 指针递增。

于 2012-05-24T20:01:00.243 回答