c ++ sprintf удалить неопределенное поведение - PullRequest
1 голос
/ 08 марта 2020

Я знаю, что что-то подобное

char a[1024] = "Hello";
char b[6] = "World";

sprintf(a, "%s %s", a, b);

вызывает неопределенное поведение. Я знаю, я мог бы использовать другие функции, такие как strcat, но если я хочу использовать функцию sprintf (я знаю риск, что я мог бы записать за границы массива), я мог бы удалить неопределенное поведение, если я напишу что-то подобное

sprintf(a + strlen(a), "%s %s", a, b)

или все еще не определено, и мне нужно использовать временную переменную?

Ответы [ 2 ]

2 голосов
/ 08 марта 2020

Вы правы, что строка

sprintf(a, "%s %s", a, b);

вызовет неопределенное поведение , поскольку строки источника и назначения перекрываются.

Однако строка

sprintf(a + strlen(a), "%s %s", a, b);

будет по-прежнему вызывать неопределенное поведение, поскольку a + strlen(a) является адресом завершающего нулевого символа строки a (что означает исходную строку a и строка назначения a + strlen(a) все еще пересекаются). Если строки не должны перекрываться, то строка должна быть изменена на следующее:

sprintf(a + strlen(a) + 1, "%s %s", a, b);

Поскольку перекрытия больше нет, строка не будет вызывать неопределенное поведение.

Если вы хотите иметь возможность копировать память из одного буфера памяти в другой буфер памяти, который перекрывает первый буфер памяти, тогда я рекомендую использовать функцию memmove. В отличие от memcpy, функция memmove разрешает перекрывающиеся буферы памяти и ведет себя так, как если бы содержимое было сначала записано во временный буфер перед записью в буфер назначения. Следовательно, поведение этой функции не является неопределенным, но четко определено, даже если буферы перекрываются. К сожалению, для строк не существует эквивалентной функции strmove.

2 голосов
/ 08 марта 2020

можно ли удалить неопределенное поведение, если я напишу что-то вроде этого

sprintf(a + strlen(a), "%s", b)

или оно все еще не определено, и мне нужно использовать временную переменную?

Да, ты мог. Нет, это все равно не будет UB.


Редактировать:

Могу ли я удалить неопределенное поведение, если напишу что-то вроде этого

sprintf(a + strlen(a), "%s %s", a, b)

или это все еще не определено, и я должен использовать временную переменную?

Нет, вы не могли. Это все равно будет UB, потому что вы все равно пишете в строку, которую передаете в качестве аргумента.

...