"" + 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
在 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;
}
在下面的代码中,我成功地编译了它,但我不明白为什么对于某些数字值程序崩溃而对于其他值却没有。有人可以解释添加 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
在 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;
}