"" + number 的行为是什么以及为什么 c++ 编译它?

What's the behaviour of "" + number and why c++ compile it?

在下面的代码中,我成功地编译了它,但我不明白为什么对于某些数字值程序崩溃而对于其他值却没有。有人可以解释添加 long int 和编译器使用的 char* 的行为吗?

#include <iostream>

int main()
{
    long int number=255;
    std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
    number=15155;
    std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
    return 0;
}

测试结果:

Value 1 : >                                                                            
Value 2 : Segmentation fault  

注意:我不是在寻找有关如何添加带数字的字符串的解决方案。

指针运算是罪魁祸首。

const char*operator<< 接受,但在您的示例中不会指向有效的内存地址。

如果您打开 -Wall,您将看到一个编译器警告:

main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
    6 |     std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
      |                                                           ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
    8 |     std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
      |                                                           ^
Value 1 :  q

Live Demo

在 C++ 中,"" 是一个 const char[1] 数组,它 衰减 为指向数组第一个元素的 const char* 指针 (在这种情况下,字符串文字的 '[=16=]' nul 终止符)。

将整数与指针相加执行指针运算,这会将指针中的内存地址增加指定数量的指针声明为的类型的元素(在这种情况下,char).

因此,在您的示例中,... << ("" + number) << ... 等同于 ... << &""[number] << ...,或者更一般地说:

const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
    reinterpret_cast<const uintptr_t>(ptr)
    + (number * sizeof(char))
);
... << ptr << ...

这意味着当 number 是 0 以外的任何值时,您将超出数组的范围,因此您的代码具有 未定义的行为 并且当operator<< 尝试取消引用您提供的无效指针。

与许多脚本语言不同,("" + number) 不是在 C++ 中将整数转换为字符串的正确方法。需要使用显式转换函数来代替,比如std::to_string(),eg:

#include <iostream>
#include <string>

int main()
{
    long int number = 255;
    std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
    number = 15155;
    std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
    return 0;
}

或者,您可以简单地让 std::ostream::operator<< 为您处理该转换,例如:

#include <iostream>

int main()
{
    long int number = 255;
    std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
    number = 15155;
    std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
    return 0;
}