为什么将内存分配给 char 指针不会截断 char 序列
Why allocating memory to a char pointer does not truncate the char sequence
我不明白为什么 char *ptr = new char[7]
不会截断大于 7 个字符的数据输入。还有为什么 eighter char c[7]
会让我输入超过 6 个字符(但在将其赋予超过 6 个字符的字面值时会出错)。
用 malloc function 做这件事对我来说似乎有点困难,这就是为什么我不想使用它。我宁愿暂时不要使用它。
char qs[7] = "1234567"; //error too many
char qs2[7];
cin >> qs2; //input 123456789
cout << qs2; //out same as input, expecting 123456
char *qs3 = new char[7];
cin >> qs3; //input 123456789
cout << qs3; //out same as input, expecting 123456
输入流目前只接受一个指针作为参数。因此它无法知道它填充的缓冲区的大小。因此它不知道是否应该截断。读取比缓冲区长的字符串将导致缓冲区溢出,并且程序的行为将是不确定的。别这样。
自 C++20 起,数组操作数通过引用传递,并且该操作确实知道大小并将截断输入。然而,这对 qs3
的情况没有帮助,因为它只是一个指针而不是数组。
相反,您可以使用:
std::cin.get(qs3, 6);
qs3[6] = '[=10=]';
确保读取的字符不超过缓冲区。
或者如果您不想截断输入,那么您可以读入 std::string
。
Doing it with malloc function seems a little bit to hard for me for a moment, this is why i prefer not to use it.
很好。解决不了你的问题,没必要用,用了也没啥好处。
两个代码片段
char qs2[7];
cin >> qs2; //input 123456789
cout << qs2; //out same as input, expecting 123456
char *qs3 = new char[7];
cin >> qs3; //input 123456789
cout << qs3; //out same as input, expecting 123456
有未定义的行为。超出分配数组的内存被覆盖。结果可以是任何一种。
考虑以下演示程序。
#include <iostream>
int main()
{
char gs1[7] = "123456";
char gs2[7];
char gs3[7] = "ABCDEF";
std::cin >> gs2;
std::cout << '\n';
std::cout << gs1 << '\n';
std::cout << gs2 << '\n';
std::cout << gs3 << '\n';
return 0;
}
如果进入
1234567
那么程序输出可能看起来像
123456
1234567
如您所见,未输出字符串 "ABCDEF"
。这是在该语句
之后附加到数组 gs2
的终止零 '[=18=]'
的结果
std::cin >> gs2;
覆盖数组的第一个字符gs3
。现在它的内容看起来像
{ '[=15=]', 'B', 'C', 'D', 'F', '[=15=]' }
因此,由于数组的第一个元素是终止零,因此在此语句中输出的是空字符串
std::cout << gs3 << '\n';
C 字符串以零结尾,这意味着您应该始终分配大小为字符串长度 + 1 的缓冲区。
char qs[7] = "1234567"; //错误太多
在静态分配的缓冲区中,对于编译器来说很明显,您的缓冲区没有 space 用于终止零。这应该是 char qs[8].
在其他两个示例中,运算符都将指向缓冲区的指针作为参数,并且它无法知道它有多大。它只是填充它直到输入结束。您遇到典型的缓冲区溢出情况,幸运的是那里(在缓冲区边界之后)没有重要的东西。
我不明白为什么 char *ptr = new char[7]
不会截断大于 7 个字符的数据输入。还有为什么 eighter char c[7]
会让我输入超过 6 个字符(但在将其赋予超过 6 个字符的字面值时会出错)。
用 malloc function 做这件事对我来说似乎有点困难,这就是为什么我不想使用它。我宁愿暂时不要使用它。
char qs[7] = "1234567"; //error too many
char qs2[7];
cin >> qs2; //input 123456789
cout << qs2; //out same as input, expecting 123456
char *qs3 = new char[7];
cin >> qs3; //input 123456789
cout << qs3; //out same as input, expecting 123456
输入流目前只接受一个指针作为参数。因此它无法知道它填充的缓冲区的大小。因此它不知道是否应该截断。读取比缓冲区长的字符串将导致缓冲区溢出,并且程序的行为将是不确定的。别这样。
自 C++20 起,数组操作数通过引用传递,并且该操作确实知道大小并将截断输入。然而,这对 qs3
的情况没有帮助,因为它只是一个指针而不是数组。
相反,您可以使用:
std::cin.get(qs3, 6);
qs3[6] = '[=10=]';
确保读取的字符不超过缓冲区。
或者如果您不想截断输入,那么您可以读入 std::string
。
Doing it with malloc function seems a little bit to hard for me for a moment, this is why i prefer not to use it.
很好。解决不了你的问题,没必要用,用了也没啥好处。
两个代码片段
char qs2[7];
cin >> qs2; //input 123456789
cout << qs2; //out same as input, expecting 123456
char *qs3 = new char[7];
cin >> qs3; //input 123456789
cout << qs3; //out same as input, expecting 123456
有未定义的行为。超出分配数组的内存被覆盖。结果可以是任何一种。
考虑以下演示程序。
#include <iostream>
int main()
{
char gs1[7] = "123456";
char gs2[7];
char gs3[7] = "ABCDEF";
std::cin >> gs2;
std::cout << '\n';
std::cout << gs1 << '\n';
std::cout << gs2 << '\n';
std::cout << gs3 << '\n';
return 0;
}
如果进入
1234567
那么程序输出可能看起来像
123456
1234567
如您所见,未输出字符串 "ABCDEF"
。这是在该语句
gs2
的终止零 '[=18=]'
的结果
std::cin >> gs2;
覆盖数组的第一个字符gs3
。现在它的内容看起来像
{ '[=15=]', 'B', 'C', 'D', 'F', '[=15=]' }
因此,由于数组的第一个元素是终止零,因此在此语句中输出的是空字符串
std::cout << gs3 << '\n';
C 字符串以零结尾,这意味着您应该始终分配大小为字符串长度 + 1 的缓冲区。
char qs[7] = "1234567"; //错误太多
在静态分配的缓冲区中,对于编译器来说很明显,您的缓冲区没有 space 用于终止零。这应该是 char qs[8].
在其他两个示例中,运算符都将指向缓冲区的指针作为参数,并且它无法知道它有多大。它只是填充它直到输入结束。您遇到典型的缓冲区溢出情况,幸运的是那里(在缓冲区边界之后)没有重要的东西。