C++ 如何解释其中带有“+”的 cout?

How does C++ interpret a cout with a '+' in it?

我一直在使用 Java/C++ 来回移动,所以我搞砸了我的控制台输出,不小心写了如下行:

cout << "num" + numSamples << endl;
cout << "max" + maxSampleValue << endl;

每一个都给了我程序中其他字符串的点点滴滴。我现在意识到我的错误,但是 C++ 是如何解释这些行的,以便它们在我的程序中输出不同字符串的不同部分?

"num" 类型是 char const [4]。如果 numSamples 为整数,则 "num" + numSamples 类型为 const char *。所以你调用 operator << cor std::cout,为 const char * 重载并打印从地址 addres("num") + numSamples 开始的字符串在指针算术中。

试试这个:

cout << "num" + std::to_string(numSamples) << endl;
cout << "max" + std::to_string(maxSampleValue) << endl;

std::to_string() 函数可以在 <string>

中找到

这只是指针运算。例如,

cout << "num" + 1 << endl;

将打印从 ((address of)"num" + 1) 开始的字符串,即 "um".

如果我们添加的值超过字符串的长度,那么我们有未定义的行为。

原因很简单:

"num""max" 是字符串文字。他们的类型是const char *。 假设 numSamples 是一个整数,你正在做的是指针运算。

你基本上是在打印一个指向 "num" + numSamples 字节的字符串。

如果你这样做 cout << "num" + 1 << endl 这将打印 "um".

你可能已经明白了,但正确的做法是:cout << "num" << numSamples << endl;

另外,你问:

But what was C++ interpreting those lines as so that they output different parts of different strings in my program?

如前所述,"num" 是一个字符串文字。通常字符串文字位于二进制程序中的相同位置:.rodata。所有其他字符串文字都位于该区域,因此当您将指针前进一定数量的字节时,您可能会指向其他一些字符串文字,从而打印(部分)它们。

请记住,尽管 iostream 重载 <<(和 >>)来执行 I/O,但这些最初被定义为位移运算符。当编译器解析表达式时,它基本上是在查看 "operand, operator, operand",然后检查操作数是否属于可以应用该运算符的类型。

在这种情况下,我们有一个字符串文字和(显然)某种整数,并且编译器知道如何对它们进行数学运算(在将字符串文字转换为指针之后)。

然而,从编译器的角度来看,这与以下内容并没有太大区别:

int a, b=1, c=2, d = 3;

a = b << c + d;

区别在于int类型的操作数,意思很明显:它在做加法和位移。在 iostream 中,<<>> 的含义发生了变化,但它们在表达式中的语法不变。

从编译器的 "viewpoint" 来看,唯一的问题是 + 的操作数是否属于允许 + 的类型——在这种情况下,您有 pointer to char + integer,所以这是允许的。结果是一个指向 char 的指针,它有一个 << 的重载,它接受一个类型为 ostream 的左手操作数和一个类型为 pointer to char 的右手运算符,所以整个表达式是很好(就它而言)。

如果您查看 operator_precedence,您会看到 +<< 之前被求值,这使得该表达式在传递给运算符 [=12= 之前需要求值]:

"num" + numSamples

现在 "num" 将成为 static const char *,我假设 numSamples 是整数类型。由于 + 的左侧是指针类型并且您要向其添加,这就是指针算术。 cout 现在获得一个指向内存中比 "num""max"numSamplesmaxSamplueValue 的位置的指针。您的所有静态字符串很可能都在同一内存区域中排列,这就是您看到它们而不是随机乱码的原因。