Возьмите следующую программу:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char a[8] = "Hello, ";
char b[7] = "world!";
strcat(a, b);
cout << a;
return 0;
}
Заметить, что a
а также b
имеют тот же размер, что и назначенные им строки.
документация утверждает, что для strcat(a, b)
работать, a
должен быть достаточно большим, чтобы содержать объединенную результирующую строку.
тем не менее, cout << a
дисплеи "Hello, world!"
, Я вхожу в неопределенное поведение?
«Я вхожу в неопределенное поведение?»
Да. Область в конце [] была переписана. На этот раз это сработало, но могло принадлежать чему-то другому.
Здесь я использую структуру для управления макетом памяти и демонстрирую ее:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
struct S {
char a[8];
char b[5];
char c[7];
};
S s;
strcpy( s.a , "Hello, " );
strcpy( s.b , "Foo!" );
strcpy( s.c , "world!" );strcat(s.a, s.c);
cout << s.a << endl;
cout << s.b << endl;
cin.get();
return 0;
}
Это выводит:
Hello, world!
orld!
Вместо:
Hello, world!
Foo!
Strcat () растоптал b [].
Обратите внимание, что в реальной жизни такие ошибки могут быть гораздо более тонкими и могут привести вас к удивлению, почему совершенно невинная функция вызывает 250 строк, которые позже вылетают и ужасно сгорают. 😉
РЕДАКТИРОВАТЬ: Могу ли я также рекомендовать использовать вместо strcat_s? Или, что еще лучше, std :: strings:
#include <string>
#include <iostream>
using namespace std;
int main()
{
string a = "Hello, ";
string b = "world!";
a = a + b;
cout << a;
}
Я вхожу в неопределенное поведение?
Да.
Если в документации сказано «a
должен быть достаточно большим, чтобы содержать объединенную результирующую строку, почему ты просто не веришь в это? Что тут сомневаться?
В вашей программе массив a
недостаточно велик, чтобы вместить результат. Следовательно, ваш код неверен и должен быть исправлен. По словам стандарта, вы действительно вводите неопределенное поведение, что означает, что оно может работать или не работать …
strcat
делает то, что говорит на олове, а именно. копирует b в конец a, не заботясь о том, какие данные уже есть. Поскольку обе переменные находятся в стеке одна за другой, все работает. Но попробуй
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char a[8] = "Hello, ";
int i = 10;
char b[7] = "world!";
strcat(a, b);
cout << a << i;
return 0;
}
И вы, вероятно, получите неожиданный результат, так как ваш стек был поврежден strcat
Это правильно …. Поведение не определено. Тот факт, что вы получили этот ответ, не означает, что в следующий раз он не потерпит крах, так как массив a
очень маленький.