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所述.
假设你有你的"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)
使用所有警告进行编译非常有益:
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.然而,这是未定义的行为,输出可能完全在另一台机器上.
通常这些编译器警告是错误的结果,因此关注编译器告诉您的内容通常非常有价值.
| 归档时间: |
|
| 查看次数: |
203 次 |
| 最近记录: |