【问题标题】:What's the behaviour of "" + number and why it compile?\"\" + number 的行为是什么以及为什么编译?
【发布时间】:2022-09-22 22:37:50
【问题描述】:

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

#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  

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

  • 这肯定有重复
  • 直觉上我会说\"\" 返回一个空字符串的第一个元素的地址;然后将number 添加到该地址;然后operator&lt;&lt; 尝试取消引用该新地址以读取字符串,这是未定义的行为。
  • 骗子解释了当您添加char 时会发生什么。你的情况更简单,因为char 首先被提升为int
  • 要更直观地解释这种现象:将\"\" 替换为\"Hello, World!\",将number=255; 替换为number=7;
  • @stef 感谢您的解释解决了我的问题

标签: c++ segmentation-fault


【解决方案1】:

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

将整数添加到指针执行指针算术,这将使指针中的内存地址前进指针声明为的类型的指定元素数量(在本例中为char)。

因此,在您的示例中,... &lt;&lt; ("" + number) &lt;&lt; ... 等效于 ... &lt;&lt; &amp;""[number] &lt;&lt; ...,或更一般地说:

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

这意味着当number 是 0 以外的任何值时,您将超出数组的范围,因此您的代码具有未定义的行为operator&lt;&lt; 试图取消引用你给它的无效指针时,任何事情都可能发生。

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

#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&lt;&lt; 为您处理该转换,例如:

#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;
}

【讨论】:

    【解决方案2】:

    指针算术是罪魁祸首。

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

    如果你打开-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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多