Watch out for sprintf()!
I was looking at some code the other day that does string concatenation with StringCchPrintf(“%s%s”). I can imagine how this would have near optimal performance, and a hopeful developer could easily assume that in fact it has been tuned for this kind of concatenation. But measuring tells all. Three trivial implementations of concat using strsafe.h:
void concat_printf(PCWSTR str1, PCWSTR str2, PWSTR out, size_t max)
{
StringCchPrintfW(out, max, L"%s%s", str1, str2);
}
void concat_copy(PCWSTR str1, PCWSTR str2, PWSTR out, size_t max)
{
StringCchCopyEx(out, max, str1, &out, &max, 0);
StringCchCopy(out, max, str2);
}
void concat_cat(PCWSTR str1, PCWSTR str2, PWSTR out, size_t max)
{
StringCchCopy(out, max, str1);
StringCchCat(out, max, str2);
}
Measurements for short concatenating strings (~10 chars) and long strings (~1000 chars).
method | short | long |
concat_printf | 187 | 10530 |
concat_copy | 15 | 952 |
concat_cat | 15 | 1264 |
Unsurprisingly concat_copy() is the most efficient, with concat_cat() overhead of a strlen() only noticeable with longer strings. But wow, concat_printf() is shocking order of magnitude slower than either of the others. Taking a peak under the covers explains why: MSVCRT is using a FILE* stream abstraction that does a lot more work for every character copy. This is so the code for printf(), fprintf() and sprintf() can all be shared. Generalization at the cost of performance!