这个 C++ 程序中发生了什么?

what happens in this C++ program?

考虑以下程序:

#include <iostream>
int main()
{
    int num=345;
    std::cout<<"num " + num<<'\n';
}

当我 运行 这个程序时,它显示 F 作为输出。如何?这里是不是在进行指针运算?如果我使用 - 符号而不是 +,则会出现空白输出。

字符串文字 "num "const char[5],它衰减到您要添加偏移量的 const char*

下面这段代码等同于你正在做的事情:

#include <iostream>
int main()
{
    int num = 345;
    const char* c_str = "num ";
    std::cout << c_str + num << '\n';
}

A: 您有未定义的行为,因为您正在访问数组边界之外的内存位置。你违反了内存安全。

由于 cout 只有在找到 '[=15=]' 的 c 字符串后才会停止打印,因此您可以继续打印直到找到为止。您不知道该值下一次发生的时间,因此您有未定义的行为,如 A.

中所述

编译所有警告非常有指导意义:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()':
main.cpp:6:25: warning: array subscript is above array bounds [-Warray-bounds]
     std::cout<<"num " + num<<'\n';

                         ^

here

本质上,编译器是在告诉您,您已经在存储 "num " 的底层数组上进行了指针运算。本质上 "num " 是一个数组,用于存储该字符串文字所需的字符。当您对其执行算术时,它会衰减为 const char*,然后您将 345 添加到指针地址。此内存地址在定义的数组之外,并且在 您的特定机器 上恰好是值 F。然而,这是未定义的行为,输出可能完全是另一台机器上的其他东西。

通常这些编译器警告是错误的结果,因此注意编译器告诉您的内容通常非常有价值。

假设您有 "num" 字符串。在记忆中它可能看起来像,

 0  1  2  3  4
[n][u][m][ ][[=10=]]

当您打印它时,它将用作指针。现在你给它加上 345 的偏移量。

 0  1  2  3  4   5  6  7     345
[n][u][m][ ][[=11=]][?][?][?]....[F][?][?]

您的程序可能打印的不仅仅是 F,它会在找到第一个 [=14=] 时停止。这是未定义的行为,因为您的程序几乎可以打印任何内容,并且会访问无效的内存地址。

如果你的目标是打印一个整数,那么你可以这样写

std::cout << "num" << num << std::endl;