Лучшая практика с sprintf?
Вот такая ситуация:
Мы получили код из внешнего источника, который использует sprintf, например strcat. Нравится:
char buffer[1024];
sprintf(buffer, "Some text.");
sprintf(buffer, "%s%s", buffer, "Some more text");
sprintf(buffer, "%s%s", buffer, "again more text");
Это выглядит странно. Мы все согласны с тем, что это выглядит странно. Я не об этом спрашиваю. Все мы знаем, что нужно было использовать strcat, и это более просто. Я спрашиваю о потенциальных проблемах, помимо того, что это может выглядеть странно. Мы работаем на RHEL6 и используем gcc 4.9.3.
Спасибо за вашу помощь.
1 ответ
Функция объявлена как
int sprintf(char * restrict s, const char * restrict format, ...);
обратите внимание на квалификатор типа.
Согласно стандарту C (7.21.6.6 Функция sprintf)
2 Функция sprintf эквивалентна fprintf, за исключением того, что вывод записывается в массив (указанный аргументом s), а не в поток. В конце написанных символов пишется нулевой символ; он не считается частью возвращаемого значения. Если копирование происходит между перекрывающимися объектами, поведение не определено .
Итак, эти звонки
sprintf(buffer, "%s%s", buffer, "Some more text");
sprintf(buffer, "%s%s", buffer, "again more text");
вызвать неопределенное поведение.
Вместо этого звонки можно было бы записать как
char buffer[1024];
int offset = 0;
offset = sprintf( buffer + offset, "Some text.");
offset += sprintf( buffer + offset, "%s", "Some more text");
sprintf( buffer + offset, "%s", "again more text");
Или
char buffer[1024];
char *p = buffer;
p += sprintf( p, "Some text.");
p += sprintf( p, "%s", "Some more text");
sprintf( p, "%s", "again more text");
Что касается квалификатора
restrict
тогда в общем слова в средствах (6.7.3 квалификаторы типа)
8 Объект, доступ к которому осуществляется через ограниченный указатель, имеет особую связь с этим указателем. Эта ассоциация, определенная в 6.7.3.1 ниже, требует, чтобы все обращения к этому объекту использовали, прямо или косвенно, значение этого конкретного указателя.