这个C++程序会发生什么?

Des*_*tor 0 c++ cout pointer-arithmetic

考虑以下计划:

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

当我运行该程序时,它显示F作为输出.怎么样?是否在这里执行指针运算?如果我使用 - 符号而不是+,则会出现空白输出.

bku*_*ytt 14

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

以下代码等同于您正在执行的操作:

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

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

因为cout只有在找到'\0'for c-strings' 时才会停止打印,你可能会继续打印直到打印出来.你不知道下一次会发生什么值,因此你有未定义的行为,如A所述.

  • @rozina在他的阵列范围之外,是的.他的数组是const char [5],因此他的内存是从`char [0]`到`char [4]`,他正在访问不在他的范围内的`char [345]`,并且可以打印任何内容位置,直到找到第一个''\ 0'`字符. (3认同)

asl*_*slg 7

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

 0  1  2  3  4
[n][u][m][ ][\0]
Run Code Online (Sandbox Code Playgroud)

打印时,它将用作指针.现在你为它添加了一个345的偏移量.

 0  1  2  3  4   5  6  7     345
[n][u][m][ ][\0][?][?][?]....[F][?][?]
Run Code Online (Sandbox Code Playgroud)

您的程序可能打印的不仅仅是F,而是在第一次\0找到时停止.它是未定义的行为,因为您的程序可以打印任何内容,并将访问无效的内存地址.

如果您的目标是打印整数,那么您可以写

std::cout << "num" << num << std::endl;
Run Code Online (Sandbox Code Playgroud)


shu*_*e87 6

使用所有警告进行编译非常有益:

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';

                         ^
Run Code Online (Sandbox Code Playgroud)

看到这里

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

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